一.equals与==的区别
==:对于基本类型,比较的是它们的值。对于复合类型(直接在堆中分配空间),比较的是它们在内存中的地址。
equals:该方法属于Object,而所有类都继承于Object这个基类,因此每个类都有这个方法。Object类中equals的默认实现是return (this == obj);,即默认是比较对象的内存地址。但在库中的一些类会覆盖从写equals这个方法,如:String、Integer、Date这些类中equals有自身的实现,而不再是比较类在堆内存中的地址。String中的equals,首先判断==,如果地址相同,那一定是返回true;如果地址不相同,再比较字符串字面值是否相等。
二
JAVA中的变量和基本类型的值存放于栈内存,而New出来的对象本身存放于堆内存,指向对象的引用还是放在堆内存。例如一下代码
int i=1;
String s = new String( "Hello World" );
变量i和s以及1存放在栈内存,而s指向的对象”Hello World”存放于堆内存。
注意:栈内存的特点是内存共享,这样设计是为了减小内存消耗,前面定义了i=1,i和1都在栈内存内,如果再定义一个j=1,此时将j放入栈内存中,然后查找栈内存是否有1,如果有的话则j指向1。
如果再给j赋值2,则在栈内存中查找是否有2,如果没有就在栈内存放一个2,然后j指向2。也就是如果常量在栈内存中,就将变量指向该常量,如果没有就在该栈内存增加一个该常量,并将变量指向该常量。
如果此时j++,此时原来的1的值不会变化,而是在栈内找一个值为2的常量,如果栈内存有就指向它,如果没有就在栈内存加入2并将该变量j指向这个2的常量。
之前讲的是int类型,那么String类型又有什么区别吗?
String w="hello world";
String q="hello world";
String s=new String("hello world");
String y=new String("hello world");
System.out.println(w==q);
System.out.println(s==y);
System.out.println(s==w);
程序运行结果:
true
false
false
分析:
1.分析w==q
对于直接赋值的字符串常量w,q是存放在栈内存中的,由于栈内存就有数据共享,所以w,q所指向的是同一”hello world”。所以s==w返回true
2.分析s==y
而String s=new String(“hello world”);后,变量s在栈内存内,Hello World 这个String对象在堆内存内。同样String y=new String(“hello world”),也会在堆内存创建一个新的String对象,变量y也在栈内存中,所以当用“==”来比较内存地址时,显然指向的是两个String对象,所以返回false。
3.分析s==w
一个在栈内存中,一个在堆内存中,显然内存地址不一样,所以false.
三.如题
public class Main{
private static final String MESSAGE="taobao";
public static void main(String [] args) {
String a ="tao"+"bao";
String b="tao";
String c="bao";
System.out.println(a==MESSAGE);
System.out.println((b+c)==MESSAGE);
}
}
程序运行结果:
true
false
这道题主要考察的是String类型的认识以及编译器优化。
1.分析a==MESSAGE
String a = “tao” + “bao” ;和String a = “taobao” ;编译出的字节码是一样的。所以等到运行时,根据上面说的栈内存是数据共享原则,a和MESSAGE指向的是同一个字符串
2.分析(b+c)==MESSAGE
b+c只能等到运行时才能判定是什么字符串,编译器不会优化,想想这也是有道理的,编译器怕你对b的值改变,所以编译器不会优化。运行时b+c计算出来的”taobao”和栈内存里已经有的”taobao”是一个吗?不是。b+c计算出来的”taobao”应该是放在堆内存中的String对象。因此结果是false,也由此可以看出一个b+c在堆内存中,而MESSAGE在栈内存中。
四StringBuffer
那么JAVA对字符串的相加该用什么呢
public class Main{
private static final String MESSAGE="taobao";
public static void main(String [] args) {
String a = "tao" + "bao";
StringBuffer b = new StringBuffer("tao");
b.append("bao");
String c = String.valueOf(b);
System.out.println(c);
System.out.println(a == MESSAGE);
System.out.println(c == MESSAGE);
}
}
程序运行结果:
taobao
true
false
因此StringBuffer的字符串也是在堆内存中。