Java中的比较有两种,是==和equals()方法,equals()是Object类的方法,定义在Object类中的equals()方法是如下实现的:
public boolean equals(Object obj){
return (this==obj);
}
==判断的是地址
String类重写了equals()方法,改变了这些类型对象相等的原则,即判断对象是否相等依据的原则为判断二者的内容是否相等。
String类的本质是字符数组char[],其次String类是final的,是不可被继承的。
使用String时可以直接赋值,也可以用new来创建对象,但是这二者的实现机制是不同的。还有一个String池的概念,Java运行时维护一个String池,池中的String对象不可重复,没有创建,有则作罢。String池不属于堆和栈,而是属于常量池。
String str = “abc”; //1
String str1 = “abc”; //2
首先在String池中创建一个对象“abc”,str指向池中的”abc” 这个对象,第二句执行的时候因为”abc”已经存在String池中了,所以不会再重新创建新的对象,因此实际上str跟str1是指向同一个对象
String str2 = new String(“abc”); //3
new String(“abc”)新创建了一个对象,由于是new出来的对象,所以存在堆内存中,内容是”abc”
由于前面1/2两句中已经在String池中创建一个对象“abc”,所以只会在栈内存创建str2引用,str2指向堆内存中”abc”这个对象的首地址。
String.intern()
存在于.class文件中的常量池,在运行期被JVM装载,并且可以扩充。String的intern()方法就是扩充常量池的一个 方法;当一个String实例str调用intern()方法时,Java查找常量池中是否有相同Unicode的字符串常量,如果有,则返回其的引用, 如果没有,则在常量池中增加一个Unicode等于str的字符串并返回它的引用;
public class Test {
public static void main(String[] args) {
String str = "abc";
String str1 = "abc";
String str2 = new String("abc");
System.out.println(str == str1);
System.out.println(str1 == "abc");
System.out.println(str2 == "abc");
System.out.println(str1 == str2);
System.out.println(str1.equals(str2));
System.out.println(str1 == str2.intern());
System.out.println(str2 == str2.intern());
System.out.println(str1.hashCode() == str2.hashCode());
}
}
运行结果如下: