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

 找回密码
 加入黑马

QQ登录

只需一步,快速开始

测试代码如下:
  1. import java.util.*;
  2. class Person
  3. {
  4.         private int age;
  5.         public Person(){}
  6.         public Person(int age)
  7.         {
  8.                 this.age = age;
  9.         }
  10.         public void setAge(int age)
  11.         {
  12.                 this.age = age;
  13.         }
  14.         public int getAge()
  15.         {
  16.                 return age;
  17.         }
  18. }
  19. class  TestFinal
  20. {
  21.         public static void main(String[] args)
  22.         {
  23.                 //1,定义一个基本类型
  24.                 final int num = 20;
  25.                 //num = 30;          //无法为最终变量num指定值
  26.                 System.out.println("num = "+num);
  27.                
  28.                 //2,定义一个数组
  29.                 final int[] arr = {5,6,12,9};
  30.                 System.out.println("原数组:"+Arrays.toString(arr));
  31.                 Arrays.sort(arr);
  32.                 System.out.println("排序后:"+Arrays.toString(arr));
  33.                 arr[2] = -8;
  34.                 System.out.println("修改后:"+Arrays.toString(arr));
  35.                
  36.                 //3,第一个类类型
  37.                 final Person p = new Person(10);
  38.                 p.setAge(15);
  39.                 System.out.println("修改后的age="+p.getAge());
  40.         }
  41. }
复制代码
运行结果如下:

问题:我知道对于final修饰成员变量而言,一旦有了初始值后,就不能被重新赋值了,以上第1段代码示例能够解释,
          但是,如第2,3段代码所示,我声明了数组和类这2个引用类型,并且也使用final修饰,之后对数组的值和类的实例属性都进行了修改,
          为什么修改成功了?不是说final修饰的变量时最终变量,代码运行时再不能重新赋值吗?请知道的亲们,赐教!


评分

参与人数 1技术分 +1 收起 理由
黄玉昆 + 1 赞一个!

查看全部评分

4 个回复

倒序浏览
Final修饰的基本类型变量时,不能对基本变量重新赋值,因此基本类型变量不能被改变。但对引用类型而言,它保存的仅仅是一个引用,final只保证这个引用的引用地址不会被改变,即一直引用同一对象,但这个对象完全可以改变。所以final修饰的引用变量无法在编译时获取值,而是在运行时获取值。

评分

参与人数 1黑马币 +3 收起 理由
谢洋 + 3 赞一个!

查看全部评分

回复 使用道具 举报
  1. public static void main(String[] args) {
  2.                 // 1,定义一个基本类型

  3.                 final int num = 20;
  4.                 // num = 30; //无法为最终变量num指定值
  5.                 System.out.println("num = " + num);

  6.                 // 2,定义一个数组
  7.                 final int[] arr = { 5, 6, 12, 9 };
  8.                 System.out.println("原数组:" + Arrays.toString(arr));
  9.                 Arrays.sort(arr);
  10.                 System.out.println("排序后:" + Arrays.toString(arr));
  11.                 arr[2] = -8;
  12.                 System.out.println("修改后:" + Arrays.toString(arr));
  13.                 /*
  14.                  * 解释:这你定义的是一个数组,数组属于引用类型,对于引用类型的变量,它保存的是仅仅是一个引用,final只保证这引用的地址不会
  15.                  * 改变,即一直引用一个对象,但这个对象是可以改变的。
  16.                  * 你可以在代码再添加一句代码,就明白了
  17.                  * 代码如:arr=null;这句代码的意思是从新给引用变量赋值。
  18.                  * */
  19.                
  20.                 // 3,第一个类类型

  21.                 final Person p = new Person(10);

  22.                 p.setAge(15);

  23.                 System.out.println("修改后的age=" + p.getAge());
  24.                
  25.                 /*
  26.                  * 解释:同理Person也是一个对象,属于引用类型。p变量仅仅是一个引用,它保存的是堆内存中Person对象的地址,
  27.                  * p.setAge(15);并没有改变引用变量p的值 ,只是改变了堆内存中的Person对象的值。
  28.                  * 同意,你在结尾处添加p=null; 这是就编译不过了,提示你final修饰的变量不可以改变。
  29.                  */

  30.         }
复制代码
希望对你有所帮助!

评分

参与人数 1技术分 +1 收起 理由
黄玉昆 + 1 赞一个!

查看全部评分

回复 使用道具 举报
为了把问题搞清楚,我还是画了个简单的内存图,从内存图中可以看出,arr所引用的对象始终没有发生变化,
这就是final修饰的作用,下面那个也是同样的道理。

详细过程2.png (36.55 KB, 下载次数: 54)

详细过程2.png

评分

参与人数 1技术分 +1 收起 理由
黄玉昆 + 1 赞一个!

查看全部评分

回复 使用道具 举报
袁见 发表于 2013-3-8 20:53
希望对你有所帮助!

谢谢你,对我很有帮助!
回复 使用道具 举报
您需要登录后才可以回帖 登录 | 加入黑马