自动装箱与自动拆箱
- Java中的基本思想就是可以通过使用像 Object 这样适当的超类来实现泛型类。以下 Point 类就是这一个例子。
代码 1-1
class Point{
private Object x;
private Object y;
public Object getX() {
return x;
}
public void setX(Object x) {
this.x = x;
}
public Object getY() {
return y;
}
public void setY(Object y) {
this.y = y;
}
}
- 当我们使用这种策略时,有两个细节必须要考虑。第一个细节在代码1-2中阐述,它描述一个 main 方法,该方法坐标 x,y 写入 Point 对象中,然后又从 Point 对象中读出。为了访问这种对象的一个特定方法,必须要强制转化成正确的类型(当然String类型除外,因为可以调用 toString() 方法)。在这里不能使用基本类型,只有引用类型才与 Object 相容。
代码1-2
public class generics{
public static void main(String[] args){
Point point = new Point();
point.setX(10);
point.setY(11);
Integer int wrapperX = (Integer) point.getX();
int x = wrapperX.intValue;
Integer int wrapperY = (Integer) point.getY();
int y = wrapperY.intValue;
System.err.println("打印坐标"+ x +","+ y );
}
}
- 如果一个 int 型量被传递到需要一个 Integer 对象的地方,那么编译器将在幕后插入一个队 Integer 构造方法 Integer.valueOf() 的调用,这就是自动装箱。而如果一个 Integer 对象被放到需要 int 型变量的地方,则编译器将在幕后插入一个 intValue 方法的调用,这就叫自动拆箱。对于其他7种基本类型/包装类型,同样发生类似的情形。代码1-3描述了自动拆箱的使用,相比代码1-2减少了一些代码的书写。
代码 1-3
public class generics{
public static void main(String[] args){
Point point = new Point();
point.setX(10);
point.setY(11);
int x = (Integer) point.getX();
int y = (Integer) point.getY();
System.err.println("打印坐标"+ x +","+ y );
}
}
Integer 的自动装箱
- 前面通过坐标的引入认识了 Integer 的自动拆箱,关于其自动装箱再看一个例子
//在-128~127 之外的数
Integer i1 =200;
Integer i2 =200;
System.out.println("i1==i2: "+(i1==i2));//输出false
//在-128~127 之内的数
Integer i3 =100;
Integer i4 =100;
System.out.println("i3==i4: "+(i3==i4));//输出true
//不使用自动装箱
Integer i3 =new Integer(100);
Integer i4 =new Integer(100);
System.out.println("i3==i4: "+(i3==i4));//显示false
- 前面说了 int 的自动装箱,是系统执行了Integer.valueOf(int i),看看其方法源码:
public static Integer valueOf(int i) {
if(i >= -128 && i <= IntegerCache.high)
// 没有设置的话,IngegerCache.high 默认是127
return IntegerCache.cache[i + 128];
else
return new Integer(i);
}
对于–128到127(默认是127)之间的值,Integer.valueOf(int i) 返回的是缓存的Integer对象。(并不是新建对象)所以范例中,i3 与 i4实际上是指向同一个对象。
而其他值,执行Integer.valueOf(int i) 返回的是一个新建的 Integer对象,所以范例中,i1与i2 指向的是不同的对象。
当然,当不使用自动装箱功能的时候,情况与普通类对象一样
String 的自动拆箱与装箱
- 先看一个例子。
String str1 ="abc";
String str2 ="abc";
System.out.println(str2==str1); //输出为 true
System.out.println(str2.equals(str1)); //输出为 true
String str3 =new String("abc");
String str4 =new String("abc");
System.out.println(str3==str4); //输出为 false
System.out.println(str3.equals(str4)); //输出为 true
equals() 比较方法是比较两个对象的值(内容)是否相同,但是并不会进行类型转换。"==" 比较是两个对象的引用(内存地址),也用来比较两个数据基本类型的变量值是否相等,如果一个操作数是表达式(即包含运算符)则比较的是数值(即会出发自动拆箱的过程)。这个例子中 str1 与 str2 引用的都是同一个对象,而 str3 与 str4 都是各自 new 的对象。
- 再看个例子
String a = "2";
String b = "23";
b = b.substring(0,1);
System.out.println(e.equals(b));//输出true
System.out.println(e == b);//输出false
这个例子中 a 与 b 的初始值不同,因此 a 与 b 各自创建了对象,所以(a==b)为false。
- 再通过一个例子检验自己
public class Main {
public static void main(String[] args) {
Integer a = 1;
Integer b = 2;
Integer c = 3;
Integer d = 3;
Integer e = 321;
Integer f = 321;
Long g = 3L;
Long h = 2L;
System.out.println(c==d);//输出true
System.out.println(e==f);//输出false
System.out.println(c==(a+b));//输出ture
System.out.println(c.equals(a+b));//输出true
System.out.println(g==(a+b));//输出true
System.out.println(g.equals(a+b));//输出false
System.out.println(g.equals(a+h));//输出true
}
}