A股上市公司传智教育(股票代码 003032)旗下技术交流社区北京昌平校区

 找回密码
 加入黑马

QQ登录

只需一步,快速开始

© 张成龙 中级黑马   /  2012-5-8 16:29  /  2764 人查看  /  8 人回复  /   0 人收藏 转载请遵从CC协议 禁止商业使用本文

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为什么就可以多次添加元素呢?

评分

参与人数 1技术分 +1 收起 理由
攻城狮 + 1 赞一个!

查看全部评分

8 个回复

倒序浏览
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仍然指向的是那个对象,变化的是对象本身

评分

参与人数 1技术分 +1 收起 理由
攻城狮 + 1 赞一个!

查看全部评分

回复 使用道具 举报

最后一分!

本帖最后由 隋营营 于 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);
    }
}

评分

参与人数 1技术分 +1 收起 理由
攻城狮 + 1 加油··黑马见····

查看全部评分

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

哈哈,他们说得差不多了!!我给你画个图吧!!希望能加深你的理解!顺便如果可以混个技术分
回复 使用道具 举报
被final修饰的变量可视为常量,只能赋值一次,意思是该变量指向的引用数据类型的地址是不变的。而对象的具体内容是可以变化的。正如你例子中演示的那样。希望能接触你的疑惑。
回复 使用道具 举报
嗯 , 就像前面几位说的那样,final StringBuffer p在栈中创建之后不能再指向其他的内存区或再创建内存区,只能指向method 创建时为p创建的栈内存区,
所以,p里面是什么内容 final管不了,但p指向被分配好的栈内存区,不能被 重新new StringBuffer("****");
也不能被重新定向  StringBuffer sb = new StringBuffer("&*(……*&%"); p=sb;

回复 使用道具 举报
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修饰对象的引用时,往往是变化的。
回复 使用道具 举报
首先简单理解啊,比如final int X = 6;之后X还能被赋值吗?显然是不能的。原因就是final修饰的变量必须在定义时就被初始化。对于final修饰的对象引用当然也只能被赋值一次啦
所以final StringBuffer a=new StringBuffer("immutable")中的a不能再被赋值。

当然实质上,final 修饰的是 一个对象的引用,引用中存放的是一个地址值,所以当然是a中存放的地址不能改变,即a不能再指向StringBuffe的其他对象,而a当然可以调用自己的公有成员方法a.append(" broken!");类虽然发生了变化,但a中地址并没有改变
回复 使用道具 举报
您需要登录后才可以回帖 登录 | 加入黑马