黑马程序员技术交流社区

标题: final修饰变量的疑问 [打印本页]

作者: 张成龙    时间: 2012-5-8 16:29
标题: final修饰变量的疑问
class  Demo
{
public static void main(String[] args)
{
  StringBuffer sb = new StringBuffer("gh");
  method(sb);
  }
  public static void method(final  StringBuffer  p)
{
  p.append("agh");
  p.append("a22");
  System.out.println(p);
}
}
被final修饰的变量可视为常量,只能赋值一次,这里的p为什么就可以多次添加元素呢?
作者: 谭景宾    时间: 2012-5-8 16:47
final是修饰变量的,不是修饰对象本身的

举例说明:
final String s = "hello";
这里final是修饰变量s的,而不是修饰"hello"
至于说String不能修改,是因为String类是immutable的,就是不能修改的意思,immutable也是一个修饰符

final StringBuffer sb = new StringBuffer("hello");
这里final修饰了sb,sb就不能指向其它对象了
比如sb = new StringBuffer("hi");这样是不允许的
但是sb所指向的那个对象本身还是可以改变的
比如sb.append(" world");是允许的,因为sb并没有变,sb仍然指向的是那个对象,变化的是对象本身
作者: 隋营营    时间: 2012-5-8 16:48
标题: 最后一分!
本帖最后由 隋营营 于 2012-5-8 16:51 编辑

JAVA的机制:在传递参数前总是将参数拷贝一份。
final并不是说:参数 p 的值必须与变量 sb 的值完全相同!而是指参数 p 不能被重新分配空间!
看代码:
public class Testext {
    public static void main(String[] args) throws Exception {
        StringBuffer sb = new StringBuffer("gh");
        method(sb);
    }

    public static void method(final StringBuffer p) {
        p = new StringBuffer(); //这里出错了:The final local variable p cannot be assigned. It must be blank and not using a compound assignment
        p.append("agh");
        p.append("a22");
        System.out.println(p);
    }
}


作者: 梁清平    时间: 2012-5-8 17:35
注意:被fainl修饰后的变量..变量名如 sp 永远是在栈内存中的..那么既然是变量一定会有一个值..当这个变量的值被锁定下来不能再变的时候..我们姑且可以认为这个变量根常量也没什么区别了..与一般常量不同的是..它有一个名字叫sp..
这里的sp被赋于一个堆内存中的对象的引用地址..也就是一个hash值..通过这个hash值指向了那个对象..那么实际上也就是说现在这个sp的hash值是不能再修改了..而sp指向的对象却不受影响..
再者你可以想象..sp和对象都不在一个内存块中..一个fimal怎么可作用两块不同性质的内存中的数据.
作者: 黄奕豪    时间: 2012-5-8 18:24
本帖最后由 黄奕豪 于 2012-5-8 19:18 编辑

哈哈,他们说得差不多了!!我给你画个图吧!!希望能加深你的理解!顺便如果可以混个技术分

作者: 黑马-王建雨    时间: 2012-5-9 00:29
被final修饰的变量可视为常量,只能赋值一次,意思是该变量指向的引用数据类型的地址是不变的。而对象的具体内容是可以变化的。正如你例子中演示的那样。希望能接触你的疑惑。
作者: It's_Zero    时间: 2012-5-9 12:18
嗯 , 就像前面几位说的那样,final StringBuffer p在栈中创建之后不能再指向其他的内存区或再创建内存区,只能指向method 创建时为p创建的栈内存区,
所以,p里面是什么内容 final管不了,但p指向被分配好的栈内存区,不能被 重新new StringBuffer("****");
也不能被重新定向  StringBuffer sb = new StringBuffer("&*(……*&%"); p=sb;


作者: HeiMaYSL    时间: 2012-5-9 12:57
class  Demo
{
public static void main(String[] args)
{
   StringBuffer sb = new StringBuffer("gh");
   method(sb);
   }
   public static void method(final  StringBuffer  p)   //因为这里你用final修饰的是对象的引用。
{
   p.append("agh");
   p.append("a22");
   System.out.println(p);
}
}

注意:final类在修饰变量时,这时变量就变成了常量。
    而final去修饰对象的引用时,因为,这个对象引用还没有确定去引用哪个对象,所以可以改变了。
切记:final修饰对象的引用时,往往是变化的。

作者: 廖理    时间: 2012-5-9 13:15
首先简单理解啊,比如final int X = 6;之后X还能被赋值吗?显然是不能的。原因就是final修饰的变量必须在定义时就被初始化。对于final修饰的对象引用当然也只能被赋值一次啦
所以final StringBuffer a=new StringBuffer("immutable")中的a不能再被赋值。

当然实质上,final 修饰的是 一个对象的引用,引用中存放的是一个地址值,所以当然是a中存放的地址不能改变,即a不能再指向StringBuffe的其他对象,而a当然可以调用自己的公有成员方法a.append(" broken!");类虽然发生了变化,但a中地址并没有改变





欢迎光临 黑马程序员技术交流社区 (http://bbs.itheima.com/) 黑马程序员IT技术论坛 X3.2