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

 找回密码
 加入黑马

QQ登录

只需一步,快速开始

© wangchao1686 中级黑马   /  2013-12-8 12:03  /  2474 人查看  /  7 人回复  /   0 人收藏 转载请遵从CC协议 禁止商业使用本文

使用final关键字修饰一个变量时,是引用不能变还是引用的对象不能变?
  1. public class test {
  2.   public static void main(String[] args)
  3.   {
  4.           final        StringBuffer s=new StringBuffer("abc");
  5.           s.append("haha");
  6.           //s=new StringBuffer("bcd");       //编译出错
  7.    System.out.println(s);
  8.   }
  9. }
复制代码

对于出现的现象,请坛友给个专业的解释。

评分

参与人数 1技术分 +1 收起 理由
简★零度 + 1

查看全部评分

7 个回复

倒序浏览
我认为是引用不能改变,你看,你new 了个 StringBuilder,但是你仍然可以像里面添加数据,对吧?(s.ppend("add"));也就是说堆内存中存储的数据仍然可以改变,但是不能改变的是,s是指向你new的那个StringBuilder实例的地址的,也就是说这种对应的关系不可以变,也就为什么你再次将新new 的StringBuilder映射到s的时候会报错,因为s已经和别人绑定关系了,且不能解除绑定关系。不知道你听懂了没有,个人理解,仅供参考。

评分

参与人数 1技术分 +1 收起 理由
简★零度 + 1

查看全部评分

回复 使用道具 举报
final标记的变量即为常量,只能赋值一次.
1.对于你的例子中,final修饰 的s 的值为一个StringBuffer类的对象的引用,即地址值。
但是对象里的内容还是可以变化的,即可以调用append方法。

2.出错的原因在于,你将s 的引用(即地址值)变化了,因为你重新new了一个对象,即s 被赋另一个地址值了,这是不行的

3.综上,是引用不能变化

评分

参与人数 1技术分 +1 收起 理由
简★零度 + 1

查看全部评分

回复 使用道具 举报
引用不能变吧,final修饰的 是一个常量,可以对这个常量进行操作,但是不可以改变常量的值
回复 使用道具 举报
final对象s 现在指向的在堆内存中的一块区域,那么其实现在s村的就是一个地址,后面你又new StringBuffer 赋值给s 那么就是重新给s赋值(即修改了s指向的地址值)

那么可以下结论,就你这种情况是不能修改引用的。同时被final修饰的常量在以后也是不能被修改的,
回复 使用道具 举报
final修饰的引用类型,该引用不可再重新指向其他的java对象。
但是fianl修饰的引用,该引用指向的对象的属性是可以修改的。
public static void main(String[] args) {

                final Customer c = new Customer("JACK", 15);

                // c是final的,无法重新赋值。
                // c = new Customer("LUCY",20);//Error

                c.name = "李四";
                c.age = 25;

                System.out.println(c.name);
                System.out.println(c.age);

        }
}

class Customer {

        String name;
        int age;

        Customer(String name, int age) {
                this.name = name;
                this.age = age;
        }

评分

参与人数 1技术分 +1 收起 理由
简★零度 + 1

查看全部评分

回复 使用道具 举报
  1. public class test {
  2.   public static void main(String[] args)
  3.   {
  4.           final   StringBuffer s=new StringBuffer("abc");
  5.           s.append("haha");
  6.           [color=Red]//s=new StringBuffer("bcd");       //编译出错[/color]
  7.    System.out.println(s);
  8.   }
  9. }
复制代码




你好!其实你的提问已经在你的代码中有了答案!
我来简单的分析下代码运行过程中告诉我们的答案吧!

1、你fianl new了一个StringBuffer对象  
2、你往里面传了值!
关键:3、当你再new一个相同对象的StringBuffer的时候~报错!这个时候其实编译器就告诉了我们
:::错误: 无法为最终变量s分配值:::
所以很明显~被fianl的对象不能变
4、而且你用StringBuffer类型来实验不合适~可以单单使用String类型来测试~你可以变化存储在堆内存的值试试~这样答案自然而喻了

评分

参与人数 1技术分 +1 收起 理由
贺奕凯 + 1

查看全部评分

回复 使用道具 举报
final StringBuffer s=new StringBuffer("abc");

          s.append("haha");

          //s=new StringBuffer("bcd");       //编译出错

final修饰的变量也称之为常量,之所以被称为常量就是因为不能再改变这个引用的值了。当然在这里面可以理解为final将s引用的指向和堆内存的每一块区域绑定了。其中s.append方法任然可以用,所以不是对象不可变,而是引用不可变

评分

参与人数 1技术分 +1 收起 理由
乔兵 + 1

查看全部评分

回复 使用道具 举报
您需要登录后才可以回帖 登录 | 加入黑马