被final修饰的变量到底能不能被修改
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修饰的变量到底能不能被修改相关推荐
- final修饰的变量是引用不能改变还是引用的对象不能改变
我们都知道final修饰变量时 会变为常量,但是使 用final关键字修饰一个变量时,是引用不能变,还是引用的对象不能变? 下面让我们来看这段代码: [java] view plain copy /* ...
- final修饰的变量就是常量?
概念 什么是常量? 对于这个问题,可能很多人都可以脱口而出 : 用final修饰的变量是常量 ,或者是在编译时期定义好的字符串.(字符串常量) 但是这种说法是不严谨的,因为准确来说 : 常量是用fin ...
- final修饰的变量必须初始化吗?
final关键字的用法大家应该都知道. 修饰的类不能被继承. 修饰的方法子类可以使用,但是不能进行重写. 修饰的变量只能被赋值一次,引用不可变. 引用不可变的变量,只能被赋值一次.但是如果变量是对象, ...
- 关于final修饰的变量赋值的问题
一.赋值的方式 1.可以定义变量时直接赋值 2.可以在代码块中进行赋值(静态代码块和构造代码块) 3.可以再构造方法中进行赋值. 总结起来,就是要在对象创建之前完成赋值的过程. 二.值能不能改变的问题 ...
- final修饰的变量就是常量?final修饰局部变量在栈还是堆还是常量池中?
概念 常量池 常量池的好处 Class类文件中的常量池 常量池 运行时常量池 包装类常量池对象池 Java中装箱和拆箱 赋值时 方法调用时 方法运算时 参考 概念 什么是常量? 对于这个问题,可能很多 ...
- final修饰的变量
被final修饰的实例变量必须显式指定初始值,而且只能在如下3个位置指定初始值. 1.定义final实例变量时指定初始值; 2.在非静态初始化块中为final实例变量指定初始值; 3.在构造器中为fi ...
- Java中被final修饰的变量的几种赋值方式
关于final final 表示"最后的.最终的"含义,变量一旦赋值后,不能被重新赋值.被 final 修饰的实例变量必须显式指定初始值. final 修饰符通常和 static ...
- java 中final修饰的变量_java中final修饰符的使用方法
本文为大家分享了java中final修饰符的使用,供大家参考,具体内容如下 1.final修饰符的用法: final可以修饰变量,被final修饰的变量被赋初始值之后,不能对它重新赋值. final可 ...
- 被final修饰的变量在哪存储_final,static,this,super 关键字总结,一点课堂(多岸学院)...
final 关键字 final关键字主要用在三个地方:变量.方法.类. 对于一个final变量,如果是基本数据类型的变量,则其数值一旦在初始化之后便不能更改:如果是引用类型的变量,则在对其初始化之后便 ...
最新文章
- Exchange 2010 恢复误删除的邮箱账户及其邮箱
- 孰优孰劣?Dubbo VS Spring Cloud性能测试大对决!
- 更改日期为英文_如何在 Linux 上检查所有用户密码到期日期 | Linux 中国
- ubuntu 安装 docky
- Javascript 面向对象编程定义接口的一种方法
- 面试官:能不能手写一个 Promise?
- 数据结构——用栈解决回文字符问题
- linux解压zip
- Markdown工具之Typora--画思维导图
- 一文读懂 12种卷积方法
- 千橡校内网更名人人网
- 2018安恒杯11月月赛 MISC
- 打造海报视觉效果—利用图层模式调色
- 用友t3服务器地址在哪里修改,畅捷通T+pos端后续想更换服务器地址链接,怎么操作?...
- vb mysql 转义字符,MySQL_在VB.NET应用中使用MySQL的方法, 绪言
在Visual Studio中使用 - phpStudy...
- Red Panda DEV-C++更新到6.7.5啦
- 文本的检测、识别实战:使用 Tesseract 进行 OpenCV OCR 和文本识别
- errno和perror
- 如何掌控自己的时间和生活
- 2023年——个人每日分享汇总