Java包装类泛型编程
- 游戏开发
- 2025-09-02 17:09:02

Java包装类&泛型编程
个人主页:顾漂亮
文章专栏:Java数据结构
文章目录 Java包装类&泛型编程1.包装类1.1装箱和拆箱1.2面试题 -- java中`Integer`类的缓存机制**`Integer` 的缓存机制****`==` 比较的是对象引用** 2.泛型编程2.1什么是泛型2.2泛型代码示例2.3泛型类的使用2.4泛型如何编译2.5泛型的上界 3.通配符3.1 `? extends 类` : 设置通配符上界3.2`? super 类` : 设置通配符下界3.3 总结 1.包装类 在Java中,由于基本类型不是继承自Object,为了在泛型代码中可以支持基本类型,Java给每一个基本类型对应了一个包装类型除了Integer和Charater,其余基本类型的包装类都是首字母大写 1.1装箱和拆箱 public static void main(String[] args) { int a = 10; Integer b = a;//自动装箱 Integer c = (Integer) a;//显示装箱 int d = b;//自动拆箱 int e = c;//显示拆箱 } 1.2面试题 – java中Integer类的缓存机制 public static void main(String[] args) { Integer a = 127; Integer b = 127; Integer c = 128; Integer d = 128; System.out.println(a);//127 System.out.println(b);//127 System.out.println(c);//128 System.out.println(d);//128 System.out.println(a == b);//true System.out.println(c == d);//false System.out.println(c.equals(d));//true } Integer 的缓存机制Java 对 Integer 类有一个缓存机制,范围为 -128 到 127。当你通过自动装箱(如 Integer a = 127;)创建 Integer 对象时:
如果值在 -128 到 127 之间,Java 会从缓存中返回同一个 Integer 对象。如果值超出这个范围(如 128),Java 会创建一个新的 Integer 对象。在你的代码中:
Integer c = 128; 和 Integer d = 128; 的值都超出了缓存范围(128 > 127),因此 c 和 d 是两个不同的 Integer 对象。== 比较的是对象引用
在 Java 中,== 用于比较两个对象的引用(即内存地址),而不是对象的值。由于 c 和 d 是两个不同的对象,它们的引用(内存地址)不同,因此 c == d 的结果是 false。
c != d 是因为 128 超出了 Integer 的缓存范围,导致 c 和 d 是两个不同的对象。== 比较的是对象引用(内存地址),而不是值。如果需要比较值,请使用 equals 方法。 2.泛型编程 2.1什么是泛型一般的类和方法,只能使用具体的类型: 要么是基本类型,要么是自定义的类。如果要编写可以应用于多种类型的
代码,这种刻板的限制对代码的束缚就会很大。----- 来源**《Java编程思想》**对泛型的介绍。
泛型是在JDK1.5引入的新的语法,通俗讲,泛型:就是适用于许多许多类型。从代码上讲,就是对类型实现了参数
化。
2.2泛型代码示例 class MyArray { public Object[] array = new Object[10]; public Object getPos(int pos) { return this.array[pos]; } public void setVal(int pos,Object val) { this.array[pos] = val; } } public class TestDemo { public void main(String[] args) { MyArray myArray = new MyArray(); myArray.setVal(0,10); myArray.setVal(1,"hello");//字符串也可以存放 String ret = myArray.getPos(1);//编译报错 System.out.println(ret); } } 上述代码,看似是可以存放任何类型的数据,但是我们很难用一种类型去接受其中的数据。所以,更多情况下,我们希望的是只能持有一种数据类型将上述代码改为泛型类:
class MyArray<T> { public Object[] array = new Object[10]; public T getPos(int pos) { return (T)this.array[pos]; } public void setVal(int pos,T val) { this.array[pos] = val; } } public class TestDemo { public void main(String[] args) { MyArray myArray = new MyArray(); myArray.setVal(0,10); myArray.setVal(1,12);//编译时,自动进行类型转换 myArray.setVal(2,"ghr");//字符串也可以存放 System.out.println(myArray.getPos(2)); } }注释:
类名后的代表占位符,表示当前类是一个泛型类规范: E表示ElementK表示KeyV表示ValueN表示NumberT表示Type 2.3泛型类的使用 LinkedList<Integer> list1 = new LinkedList<>(); ArrayList<String> list2 = new ArrayList<>();注意:
泛型只能接受类,所有的基本数据类型必须使用包装类,其中传入的参数必须全部是Object的子类
上述代码第二个<>可以不填写类,编译器可以推导出实例化需要的类型实参为Integer
泛型的优点:数据类型参数化,编译时自动进行类型检查和转换
2.4泛型如何编译在编译的过程当中,将所有的T替换为Object这种机制,我们称为:**擦除机制**
Java的泛型机制是在编译级别实现的,编译器生成的字节码在运行期间并不包含泛型的类型信息
2.5泛型的上界示例1:
class Test<E extends Number> { }没有指定类型边界E,可以默认视为E extends Object
示例2:
class Test<E extends Comparable<E>> { }E必须是实现了**Comparable**接口的
3.通配符?用在泛型中,即通配符
//使用示例 class Message<T> { private T message ; public T getMessage() { return message; } public void setMessage(T message) { this.message = message; } } public class TestDemo { public static void main(String[] args) { Message<Integer> message = new Message<>() ; message.setMessage(99); fun(message);//编译出错,只能传入String类型参数 } public static void fun(Message<String> temp){ System.out.println(temp.getMessage()); } } //解决方案 class Message<T> { private T message ; public T getMessage() { return message; } public void setMessage(T message) { this.message = message; } } public class TestDemo { public static void main(String[] args) { Message<String> message = new Message<>() ; message.setMessage("我爱学习编程!!"); message.setMessage(99); fun(message); } public static void fun(Message<?> temp){//将String替换为通配符 ? System.out.println(temp.getMessage()); } }注意:通配符的使用场景:可以接受所有泛型类型,但是又不能够让用户随意修改。这种情况就需要使用通配符来解决问题。
3.1 ? extends 类 : 设置通配符上界 class Food { } class Fruit extends Food { } class Apple extends Fruit { } class Banana extends Fruit { } class Message<T> { // 设置泛型 private T message ; public T getMessage() { return message; } public void setMessage(T message) { this.message = message; } } public class TestDemo { public static void main(String[] args) { Message<Apple> message = new Message<>() ; message.setMessage(new Apple()); fun(message); Message<Banana> message2 = new Message<>() ; message2.setMessage(new Banana()); fun(message2); } // 此时使用通配符"?"描述的是它可以接收任意类型,但是由于不确定类型,所以无法修改 public static void fun(Message<? extends Fruit> temp){ //temp.setMessage(new Banana()); //仍然无法修改! //temp.setMessage(new Apple()); //仍然无法修改! System.out.println(temp.getMessage()); } } 3.2? super 类 : 设置通配符下界 class Food { } class Fruit extends Food { } class Apple extends Fruit { } class Plate<T> { private T plate ; public T getPlate() { return plate; } public void setPlate(T plate) { this.plate = plate; } } public class TestDemo { public static void main(String[] args) { Plate<Fruit> plate1 = new Plate<>(); plate1.setPlate(new Fruit()); fun(plate1); Plate<Food> plate2 = new Plate<>(); plate2.setPlate(new Food()); fun(plate2); } public static void fun(Plate<? super Fruit> temp){ // 此时可以修改!!添加的是Fruit 或者Fruit的子类 temp.setPlate(new Apple());//这个是Fruit的子类 temp.setPlate(new Fruit());//这个是Fruit的本身 //Fruit fruit = temp.getPlate(); 不能接收,这里无法确定是哪个父类 System.out.println(temp.getPlate());//只能直接输出 } } 3.3 总结 通配符类型语法使用场景特点上界通配符<? extends T>接受 T 或其子类的集合只能读取,不能写入(除了 null)下界通配符<? super T>接受 T 或其父类的集合可以写入 T 或其子类的对象,读取为 Object无界通配符<?>接受任意类型的集合只能读取为 Object,不能写入(除了 null)Java包装类泛型编程由讯客互联游戏开发栏目发布,感谢您对讯客互联的认可,以及对我们原创作品以及文章的青睐,非常欢迎各位朋友分享到个人网站或者朋友圈,但转载请说明文章出处“Java包装类泛型编程”