1) 基本数据类型如byte, short, char, int,long, float, double, boolean
可直接用"=="来比较它们数值的大小
2) 引用数据类型,包括类,接口,数组等
当他们用"=="进行比较时,比较的是他们在内存中的存放地址,除非是同一个new出来的对象,他们的比较后的结果为true,否则比较后结果为false。
JAVA当中所有的类都是继承于Object这个基类的,在Object中的基类中定义了一个equals的方法,这个方法的初始行为是比较对象的内存地址,但在一些类库当中这个方法被覆盖掉了,如String,Integer这些类当中会重写equals方法,比较的就不是地址了, 只要没有重写equals方法,它和"=="在比较引用数据类型是等价的。下面看几个例子
例1public class Test {
public static void main(String[] args) {
String str1 = "java";
String str2 = "java";
System.out.println(str1.equals(str2));
System.out.println(str1 == str2);
}
}
输出结果为true
true
例2
public class Test {
public static void main(String[] args) {
String str1 = "java";
String str2 = new String("java");
System.out.println(str1.equals(str2));
System.out.println(str1 == str2);
}
}
输出结果为true
false
我们再来看看在String类中的equals方法实现和Object里的equals方法实现
String类中
public boolean equals(Object anObject) {
if (this == anObject) {
return true;
}
if (anObject instanceof String) {
String anotherString = (String)anObject;
int n = value.length;
if (n == anotherString.value.length) {
char v1[] = value;
char v2[] = anotherString.value;
int i = 0;
while (n-- != 0) {
if (v1[i] != v2[i])
return false;
i++;
}
return true;
}
}
return false;
}
Object类中
public boolean equals(Object obj) {
return (this == obj);
}
可以看到String确实对equals方法进行了重写,如果是同一个对象返回true,若不是同一个对象但是是同一种类型则比较它们的值,相同则返回true
那为什么在例1中没有显式new对象,但"=="的结果是true呢?
原因是程序在运行的时候会创建一个字符串缓冲池当使用 str1 = "java" 这样的表达是创建字符串的时候,程序首先会在这个String缓冲池中寻找相同值的对象,在例1中,str1先被放到了池中,所以在str2被创建的时候,程序找到了具有相同值的 str1,将str2引用str1所引用的对象"java",在例2中使用了 new 操作符,于是一个新的"java" String对象被创建在内存中。他们的值相同,但是存储的位置不同,所以"=="的结果是false。
Java的String类中还有一种方法叫intern方法,当一个String实例str调用intern()方法时,Java查找常量池中是否有相同Unicode的字符串常量,如果有,则返回其的引用, 如果没有,则在常量池中增加一个Unicode等于str的字符串并返回它的引用,见下面的例子
例3
public class Test {
public static void main(String[] args) {
String str1 = "java";
String str2 = new String("java");
str2 = str2.intern();
System.out.println(str1.equals(str2));
System.out.println(str1 == str2);
}
}
输出结果为true
true
也就是说虽然str2重新new了一个String对象,但之后执行了intern方法,在str2前,str1的对象就已经在缓冲池中且值与str2相同,故str2的引用直接指向了str1的引用指向的对象,所以"=="的结果是true,这个时候新new出来的对象没有引用指向它,不就便会被垃圾回收器回收掉。