设有两个赋值语句:
a = Integer.parseInt("1024");
b = Integer.valueOf("1024").intValue();
这里的a和b都是整数类型变量并且他们的值相等。
intValue()是把Integer对象类型变成int的基础数据类型; parseInt()是把String变成int的基础数据类型; Valueof()是把String转化成Integer对象类型;(现在JDK版本支持自动装箱拆箱了),在这串代码中:parseInt得到的是基础数据类型int,valueof得到的是装箱数据类型Integer,然后再通过valueInt转换成int,所以得到这个结果。
现在对于包装类和基本数据的比较总结如下:
Integer n1 = new Integer(1000);
Integer n2 = new Integer(1000);
int value =1000;
String a = "1000";
Integer n3=2000,n4=2000;
Integer n5=47,n6=47;
int n1_int = n1.intValue();
Integer a_integer = Integer.valueOf(a);
System.out.println(value==n1); //true
System.out.println(n1_int==n2); //true 把n1转成了n1_int为int型,和Integer的n2比较拆箱,比较值
System.out.println(n1 == n2); //false 引用类型比较的是地址
System.out.println(n3==n4); //false
System.out.println(n5==n6); //true
System.out.println(n1.equals(n2)); //true equals内部都转换成了基本数据类型
System.out.println(a_integer.equals(n2)); //true
-
System.out.println(value = = == ==n1)
输出是true,因为value是Int型,n1是Integer型,两者在进行 = = == ==比较的时候,Integer会自动拆箱为int型,而int属于基本数据类型,基本数据类型的 = = == ==比较是比较的值,因此都是1000为true。 -
System.out.println(n1_int = = == ==n2)
输出是true,因为n1_int是把n1转成了int类型(intValue方法是把Integer类型转成int类型),所以还是变成了①的情况int和Integer的比较,拆箱后变成值得比较为true。 -
System.out.println(n1 = = == ==n2)
输出是false,因为n1和n2都是Integer是包装类型,且n1和n2都new了一个对象,则声明是在栈中,而对象在堆中,这个时候包装类型进行 = = == ==比较比较的就是地址,而n1和n2这是两个在java堆中的不同的对象,所以返回false。 -
System.out.println(n3 = = == ==n4)
输出是false,因为这里n3和n4还是对象(类比String a = “abc”),n3和n4在虚拟机栈的局部变量表中,但是他们的2000是在常量池里面的两个不同的常量,所以n3和n4的 = = == ==比较比较的是地址,因此返回的是false。 -
System.out.println(n5 = = == ==n6)
输出的是true,虽然n5和n6都是对象,但是因为他们对应的值是[-128,127]之间,所以当n5创立好后开始创建n6的时候,他会去缓存中找对应的值,然后把这个值给n6,所以这里是同一个地址,因此返回的是true。 -
System.out.println(n1.equals(n2))
输出的是true。在讲为什么之前先说一下对于Object的equals的源码:
public boolean equals(Object obj) {
return (this == obj);
}
我们可以看到,对于object类型他的equals其实就是
=
=
==
==号比较,
=
=
==
==的比较规则是:如果传入的是引用类型,则比较的是地址,如果传入的是基本数据类型,则比较的是值。
而我们的Integer的equals对上面的equals进行了重写,当然String也对上面的equals进行了重写,下面给出Integer的重写的代码:
public boolean equals(Object obj) {
if (obj instanceof Integer) {
return value == ((Integer)obj).intValue();
}
return false;
}
这里的value是我们的n1的值。他会做以下几件事:
①首先他会判断我们括号的n2是不是Integer类型(或者是子类),如果是则进入if,不是就返回false。
②接着让value和((Integer)obj).intValue()进行比较,value是我们n1的值,是int类型(源码中是private final int value),
=
=
==
==右边是把我们传参传进来的obj(n2)转成Integer类型,然后调用intValue()方法把Integer类型转成int类型。
所以我们的equals方法其实实质性的比较是比较两个int基本数据类型,也就是值的比较,因此这里n1.equals(n2)中n1和n2值都是1000,返回true。
如果是String类型,下面我们给出String类型重写的equals:
public boolean equals(Object anObject) {
if (this == anObject) {
return true;
}
if (anObject instanceof String) {
String aString = (String)anObject;
if (coder() == aString.coder()) {
return isLatin1() ? StringLatin1.equals(value, aString.value)
: StringUTF16.equals(value, aString.value);
}
}
return false;
}
他主要完成了以下几件事:
①先比较我们的调用者对象和传入的参数的anObject对象是不是同一个地址(==),如果是则直接返回true。这个相当于就是自己和自己进行equals了,返回当然就是true。
②然后判断我们传入的anObject对象是不是String类型或者是String类型的子类,如果是则进入if,对调用者的值(也就是字符串)和参数的值(anObject对象的字符串)进行挨个比较,如果都相等则返回true,否则返回false。
所以这里对于String,也相当于是值得比较。
- System.out.println(a_integer.equals(n2))
返回的是true,原理和上面的⑥