String a = "Hello ";
final String b = a ;
System.out.println(b);
a+="World!";
System.out.println(b); 与
StringBuilder a = "Hello ";
final StringBuilder b = a ;
System.out.println(b);
a.append("World!");
System.out.println(b);
我的问题是:
1.为什么第二段代码中final变量的值改变了,而第一个却没有
2.String是final类,为什么  a+="World!";  可以改变 a 的值初学Java,第一在这里发帖,望大虾们不吝赐教!

解决方案 »

  1.   


    1.为什么第二段代码中final变量的值改变了,而第一个却没有
    StringBuilder 对象是动态对象,所以它的长度是可以动态变化的,final修饰引用b只能代表这个引用b被初始化指向一个对象后就无法再把它改为指向另一个对象,如b=a;b=c;就是不对的,但是这并不代表引用b所指向的那个对象里面的值不能变,即引用b所指向的那块内存的地址不能变,但是那块内存里面放的东西可以变;第一个没有变化是因为执行a+="World!";后,a所指的对象不再是原来的a = "Hello ";而引用b所指的却还是原来a引用所指的对象,即在执行到第二个System.out.println(b);的时候,b所指向的还是“Hello”,而a所指向的已经是"Hello World!"了。2.String是final类,为什么 a+="World!"; 可以改变 a 的值
    String是final类代表这个类不能被继承,但是这并不代表这个类的所有对象也是final的,除非你声明了。由于你这里的a没有被声明为final,所以它所指向的对象是可以改变的。执行完a+="World!";后,a就不再指向原来的"Hello"了,而是指向一个新的对象"Hello World!",而内存中还是存在"Hello"对象的,只是a不再指向它,或许其它引用还指向它,如上面的b,或许没有引用指向它
      

  2.   

    String对象是存在静态池中
    而StringBuffer是存在堆内存中的
      

  3.   

    Java里很重要的一点是:引用与引用指向的对象,如
    StringBuilder str = new StringBuilder("ABC"); 
    1. str本身是一个引用
    2. str指向的对象是StringBuilder的一个对象(即一个实例)。
    引用与引用指向的对象是两个不同的东西。final StringBuilder str = new StringBuilder("ABC"); 
    1. 这里final修饰的是引用str,而不是str批向的对象,所以是str不能被修改。
    2. 但是str指向的对象因为与引用str不是同一个东西,所以str指向的对象的数据是能被修改的,所以
    str.append("x"); 是正确的,
    但是str = new StringBuilder("new sb"); 却是错误的,因为这个语句的结果是在修改str指向另一个对象。
      

  4.   

    好好研究一下String是不可变的,而StringBuffer与StringBuilder正是为了解决String不可变的缺点而生的。
      

  5.   

    谢谢楼上各位的解释     特别感谢mythofking  Inhibitory