我们都知道,“=”等号操作符在编码语言中是个神奇的符号,因为它表示赋值操作而不是单纯的“等于”。我们也知道,“=”进行赋值操作时,有左值和右值的说法,当然左值和右值这里就不详述了,这个不是本文的重点。那么,下面,简单对java中的“=”操作符进行一下简单的说明:
首先,java中的数据类型分为两大类,基本类型和引用类型,基本类型:int、byte、char、short、long、float、double、boolean。引用类型:String、Array、Object。
那么先比较下面两段代码:
1.
1 int a = 3;2 int b = a;3 b++;4 System.out.println(a);
2.
1 String a = "Hello";2 String b = a;3 b = b + "World";4 System.out.println(a);
最终的结果将是上面的 a = 3; a = "Hello"; 表面上看 a的值都没有改变但实际上两者的机制是不一样的。
对基本类型进行“=”只是一个赋值操作,就是将 a这个变量进栈,并将 a的内存区域的内容设成 3。
而引用类型进行“=”却是引用操作,说具体一些就是地址的传递,开始我们 String a = "Hello";时,实际上是堆中开辟了一块内存,内存中存放的内容是字符串 "Hello"对象, 而变量 a却是我们在栈中声明的,这个“=”操作符是让 a去引用 "Hello"这个对象, a真正的值应该是 "Hello"字符串对象的地址!而 String b = a; 时;这时候是将 a的地址赋值给了 b(引用是地址的赋值), a、 b的值都是同一个地址,那么 a、 b指向的是同一个对象, b = b + "world"; 实际上改变了b所引用的对象,不是b所引用的对象的值。 b重新引用了另外一个对象 "Helloworld", a还是引用 "Hello"这个字符串对象。当然 System.out.println(a)的值不会改变(这个,笔者暂时理解成为 println方法传递引用类型对基本类型的一个重载,感兴趣的可以查阅一下javadoc,这个还有待验证)。
拓展一下,讲一下java的内存回收机制,以下面的一段代码为例:
1 String a = "Hello";2 a = a + "World";3 System.out.println(a);
看一下 a = a + "World";这句,我们前面已经知道了 a是对堆中某块内存对象的引用, a + "World";给我们的第一反应就是将这块内存中的改为 "HelloWorld",实际则不然, "Hello"这个 String类型的对象在初始化后就已经是不可变的了, a = a + "World";实际上是在堆区另外开辟一块内存,内存中的内容是 "HelloWorld",原来存放 "Hello"的那块内存区域会被回收, a重新引用 "HelloWorld"这块内存区域, a的值( a的地址)也会改变。
再看一个例子:
1 public class Text{ 2 private String word; 3 public void setWord(String Word){ 4 this.word = Word; 5 } 6 public void printWord(){ 7 System.out.println(this.word); 8 } 9 }10 public class Main{11 public static void main(String[] args){12 Text t1 = new Text();13 t1.setWord("Hello");14 Text t2 = t1;15 t2.setWord("HelloWorld");16 t1.printWord();17 }18 }
t1.printWord()输出的却是 "HelloWorld";说明在 Text t2 = t1;时, t2引用了 t1所引用的对象,就是 new Text()初始化的对象, t2.setWord("HelloWorld");时,这个对象的成员 word被改变了,就是说 t2.word引用的对象的地址变了,但是 t1、 t2引用的由 new Text();初始化的这个对象却没有改变,因为 t1还引用原来的对象, t1.word也会改变。
最后用一句话总结: 变量可以引用对象,但是变量不是对象!