例子
public class Square {
long width;
public Square(long l) {
width = l;
}
public static void main(String arg[]) {
//声明了3个Square类型的变量a,b,c
//在stack中分配3个内存,名字为a,b,c
Square a, b, c;
//在heap中分配了一块新内存,里边包含自己的成员变量width值为42L,然后stack中的a指向这块内存
a = new Square(42L);
//在heap中分配了一块新内存,里边包含自己的成员变量width值为42L,然后stack中的b指向这块内存
b = new Square(42L);
//stack中的c也指向b所指向的内存
c = b;
//在stack中分配了一块内存,值为42
long s = 42L;
}
}
以上代码在内存中的情况:
如何来对各种不同的变量作比较?
java的数据类型分为:
- 基本数据类型
- 引用数据类型
上例中的变量a,b,c属于引用数据类型,s属于基本数据类型
==强调栈中的比较,可以理解为地址比较
==可以用于基本数据类型相互比较,此时比较二者的值是否相等
==也可以用于引用数据类型的相互比较,此时比较二者的地址是否相等
==不能用于基本数据类型和引用数据类型比较,不同的基本数据类型之间也不能比较,例如string不能与char[]比较
equals强调对象的内容比较
equals不能用于基本数据类型比较,因为这是一个方法,不是运算符,继承自object
equals用于进行对象的比较,比较二者的引用地址是否相同
特殊情况:
1)数值型基本类型和数值型类会存在自动装箱和自动拆箱.
2)字符串会以常量形式存在, 如果多个字符串变量值相同, 则他们指向同一个地址.
3)数值类型会存在类型自动转换.
根据给出的例子判断
-
由图可以看出a和b指向的不是同一个引用,所以a!=b
-
一个Square类型不能与一个long型比较,编译就错误,所以不存在s==a这种比较
-
由图可以看出b和c指向的是同一个引用,所以b==c
-
程序会把s封装成一个Long类型,由于Square没有重写Object的equals方法,
所以调用的是Object类的equals方法,源码如下
public boolean equals(Object obj) {
return (this == obj);
}
其实就是判断两个引用是否相等,所以a.equals(s) == false在java中进行比较,我们需要根据比较的类型来选择合适的比较方式:
- 对象域,使用equals方法 。
- 类型安全的枚举,使用equals或== 。
- 可能为null的对象域 : 使用 == 和 equals 。
- 数组域 : 使用 Arrays.equals 。
- 除float和double外的原始数据类型 : 使用 == 。
- float类型: 使用Float.foatToIntBits转换成int类型,然后使用==。
- double类型: 使用Double.doubleToLongBit转换成long类型,然后使用==。