String str1 = new String("你好");
这条语句可以看成两条语句,分别是
String str1;//在栈内开辟空间,此时 str1默认指向 null
str1 = new String("你好"); //new 在堆内开辟空间,并把地址返回给 str1 这时 str1就指向这个堆空间了
String str2 = str1;
显而意见,因为str2是一个对象,那么 str2 = str 一定是引用传递,传递的是 栈 中str1内存放的东西(堆的地址)。这时容易出现一个误差: str2 = "世界"; 给str2赋新值,为什么str1的内容不变,因为在接触的其它引用传递中,既然两个变量都指向一块物理地址,也改变其中一个量,另一个量也应该相应改变。如
public class f {
public static void main(String[] args) {
A a1 = new A();
a1.i = 2;
A a2 = a1;
a2.i = 1;
}
}
class A{
int i;
}
在其中将 a2.i的值修改了,a1.i的值也修改。因为a2与 a1是指向一块内存的。
其实 str2 = "世界"; 与 a2.i = 1;进行的内部操作是不一样的,str2 = "世界";等价于 str2 = new String("世界");(包装类)
所以就出现a2的值改变a1的值不变的情况,a2指向新开辟出的内存,a1还在指向原内存。
刚入门的初学者都知道:==是比较地址的,而equals()用来比较内容。==比较地址好解释 如str1 == str2; str1在哪里,是一块栈空间的名称,栈内存放的是 一块堆内存的地址,所有比较的当然是地址了
而equals()就好奇,为什么 String类型比较的是内容,而Object类型比较内容就不行呢(实际上,只要不重构equals()方法,比较的是地址,也就是说自定义的类用 equals与==比较是没有区别的),查看源代码会发现 自定的类 继承的 Object的equals方法,而这equals方法的返回值 就是 return Object == Object; 而String(所有包装类)都重构了equals方法,所以才能比较内容。这也就导致了理解上的误差。