final:可以修饰方法变量

  • 的修饰:表示类不可以被继承;
  • 方法修饰:表示该方法不能被子类重写;
  • 变量修饰:表示该变量不能被修改;

不知道大家有没有遇到一些很奇怪的现象,就是被final修饰变量好像能被修改;
比如下面这段代码吧

public class Model {public String id;public String  userName;public String password;public Model() {id ="model_id";userName="model_userName";password = "model_password";}
public class Test {public static final Model model = new Model();public static void main(String[] args) {//修改前System.out.println(model.toString());//修改id的值;model.setId("fix_model_id");//修改后System.out.println(model.toString());}

这个model对象被final修饰了,正常来讲不应该修改才对啊!那为什么被final修饰之后还会被修改呢?
要理解这个问题,还必须要了解一点Java虚拟机的知识,首先看下Java虚拟机运行时数据区:

虚拟机栈(VM Stack)描述的是Java方法执行的内存模型,每个方法在执行的时候都会创建一个叫栈帧(Stack Frame)的东西用来存储**局部变量表**,操作数栈,动态链接,方法出口等信息。
这其中很重要的信息虚拟机栈中会创建:局部变量表。
局部表量表中有什么?

局部变量表:各种基本数据类型(int,short,long,float,double,char,boolean,byte),引用对象(reference类型,他不同于对象本身,可能是是一个指向对象起始地址的指针;也可能是指向一个对象的句柄或与此对象相关的位置);

也就是说,如果变量不是基本类型,那么存储的值我们可以理解为指向实际对象的内存地址,如下图;

上面的例子:

public static final Model model = new Model();


mode变量对应的值,是一个引用地址;这个地址对应的值是真正的model对象;
因而,变量model被final修饰之后,如果引用的model对象没有变,那么就是正确;但是修改model对象的属性值是可以的,因为final只是确保引用的model对象不变就行;
打个比方:你有张三的电话号码(对象的引用),张三胖了30斤(对象属性值变化),但是你持有的引用仍然还是张三;final的作用相当于就是让你对张三的引用不要变,能随时引用到张三;不管他变胖,变瘦,变高,变矮,他只要是张三就行;但是如果从张三的引用,变成了对张三双胞胎弟弟的引用就不行了会报错;因为持有的引用已经变了,尽管属性值一模一样但是本质变了;
下图就是一个错误引用:

  • 原引用: model -> 0xffff ;
  • 新引用: model -> 0x5fff;
    下图更改引用对象,就会导致报错;

回到最开始的问题,被final修饰的变量的值为什么还是会被修改?
其实看到这里,问题的答案已经很明显了。被final修饰的变量值是没有变的;

public static final Model model = new Model();

被final修饰的model,存储的只是一个内存地址,setId只是通过引用地址找到正真的model实例数据,修改了model对象的实例数据;而model存储的值(指向对象的指针)并没有变,疑惑解除~;

被final修饰的变量到底能不能被修改相关推荐

  1. final修饰的变量是引用不能改变还是引用的对象不能改变

    我们都知道final修饰变量时 会变为常量,但是使 用final关键字修饰一个变量时,是引用不能变,还是引用的对象不能变? 下面让我们来看这段代码: [java] view plain copy /* ...

  2. final修饰的变量就是常量?

    概念 什么是常量? 对于这个问题,可能很多人都可以脱口而出 : 用final修饰的变量是常量 ,或者是在编译时期定义好的字符串.(字符串常量) 但是这种说法是不严谨的,因为准确来说 : 常量是用fin ...

  3. final修饰的变量必须初始化吗?

    final关键字的用法大家应该都知道. 修饰的类不能被继承. 修饰的方法子类可以使用,但是不能进行重写. 修饰的变量只能被赋值一次,引用不可变. 引用不可变的变量,只能被赋值一次.但是如果变量是对象, ...

  4. 关于final修饰的变量赋值的问题

    一.赋值的方式 1.可以定义变量时直接赋值 2.可以在代码块中进行赋值(静态代码块和构造代码块) 3.可以再构造方法中进行赋值. 总结起来,就是要在对象创建之前完成赋值的过程. 二.值能不能改变的问题 ...

  5. final修饰的变量就是常量?final修饰局部变量在栈还是堆还是常量池中?

    概念 常量池 常量池的好处 Class类文件中的常量池 常量池 运行时常量池 包装类常量池对象池 Java中装箱和拆箱 赋值时 方法调用时 方法运算时 参考 概念 什么是常量? 对于这个问题,可能很多 ...

  6. final修饰的变量

    被final修饰的实例变量必须显式指定初始值,而且只能在如下3个位置指定初始值. 1.定义final实例变量时指定初始值; 2.在非静态初始化块中为final实例变量指定初始值; 3.在构造器中为fi ...

  7. Java中被final修饰的变量的几种赋值方式

    关于final final 表示"最后的.最终的"含义,变量一旦赋值后,不能被重新赋值.被 final 修饰的实例变量必须显式指定初始值. final 修饰符通常和 static ...

  8. java 中final修饰的变量_java中final修饰符的使用方法

    本文为大家分享了java中final修饰符的使用,供大家参考,具体内容如下 1.final修饰符的用法: final可以修饰变量,被final修饰的变量被赋初始值之后,不能对它重新赋值. final可 ...

  9. 被final修饰的变量在哪存储_final,static,this,super 关键字总结,一点课堂(多岸学院)...

    final 关键字 final关键字主要用在三个地方:变量.方法.类. 对于一个final变量,如果是基本数据类型的变量,则其数值一旦在初始化之后便不能更改:如果是引用类型的变量,则在对其初始化之后便 ...

最新文章

  1. Exchange 2010 恢复误删除的邮箱账户及其邮箱
  2. 孰优孰劣?Dubbo VS Spring Cloud性能测试大对决!
  3. 更改日期为英文_如何在 Linux 上检查所有用户密码到期日期 | Linux 中国
  4. ubuntu 安装 docky
  5. Javascript 面向对象编程定义接口的一种方法
  6. 面试官:能不能手写一个 Promise?
  7. 数据结构——用栈解决回文字符问题
  8. linux解压zip
  9. Markdown工具之Typora--画思维导图
  10. 一文读懂 12种卷积方法
  11. 千橡校内网更名人人网
  12. 2018安恒杯11月月赛 MISC
  13. 打造海报视觉效果—利用图层模式调色
  14. 用友t3服务器地址在哪里修改,畅捷通T+pos端后续想更换服务器地址链接,怎么操作?...
  15. vb mysql 转义字符,MySQL_在VB.NET应用中使用MySQL的方法, 绪言 在Visual Studio中使用 - phpStudy...
  16. Red Panda DEV-C++更新到6.7.5啦
  17. 文本的检测、识别实战:使用 Tesseract 进行 OpenCV OCR 和文本识别
  18. errno和perror
  19. 如何掌控自己的时间和生活
  20. 2023年——个人每日分享汇总

热门文章

  1. C语言制作通讯录(新手练习推荐)
  2. 启用与关闭 Ad Hoc Distributed Queries
  3. postgreSQl请求方式
  4. MATLAB-随机森林实现数据回归分析预测
  5. Kubadem方式安装Kubernetes(1.10.0)集群
  6. BetterGeo Mod 中文
  7. 第二阶段>>>数据库/SQL/SSM/JDBC/核心总结
  8. 【集训Day1】 Dwarves line up
  9. 算法:求10万以内的质数
  10. 传统安防监控摄像头Onvif云台控制直播流如何转换成GB/T28181对接到国标视频平台公安内网