Java 中,一个 final 的 List 变量,被往里加了元素,算不算违反了 final 这个关键词在这里暗示的约定?

2021-12-31 10:44:16 +08:00
 Newyorkcity
final 关键词在 java 中,只能保证变量的值不变,但如果变量的值是一个本身提供了修改自身的方法的对象,那调用这一方法对值(内部)做修改,final 是约束不到的。

然而这样的修改,是否是违背了 final 这个关键词放在这里时暗示的约定——该变量是不可变的?或者说,如果让一个全知全能的家伙来编写 Java ,它是否会为 final 所修饰的变量保证无论如何都无法被修改而不仅仅只是引用无法被修改的限制?(也就是说,java 之所以不能实现到这一步,是否可能是因为在编译器层面强制实现这一程度所需要的工程量太大划不来)

谢谢
4235 次点击
所在节点    问与答
55 条回复
mineralsalt
2021-12-31 10:51:07 +08:00
final 是限制变量不能被再次赋值, 而修改变量内部数据不属于 final 的管辖范围, 这根本就是两码事, 你要限制数组不能改动 , 可以用别的方法
aptupdate
2021-12-31 10:53:34 +08:00
我也想过这个问题,但是没想通。
dqzcwxb
2021-12-31 10:55:42 +08:00
不违反,你改的是字段不是当前这个对象你把这俩分开想就行
banmuyutian
2021-12-31 10:56:38 +08:00
final 只是限制不能再次赋值,但是对象内的行为是管不到的,如果你不想 List 被修改可以用 ImmutableList
wolfie
2021-12-31 11:03:07 +08:00
final 项目经理 = 张三。
张三将任务分配给 李四。
张三将任务重新分配给 王五。
Newyorkcity
2021-12-31 11:06:07 +08:00
@wolfie 你这个比喻张三做了事但没有影响到他本身。。但如果
张三.去洗脚店()
张三.被逮捕( 10 年)
你看,这个张三是不是就没法继续当项目经理了?
Cabana
2021-12-31 11:13:03 +08:00
你需要的是 ImmutableList
misdake
2021-12-31 11:13:58 +08:00
想要内部不可变,java 的话就改用不可变对象,或者对外只暴露不可变接口。反正是可以做到,但可能费一些功夫去写接口。我在一定程度上赞同写一套只读接口,再 extend 出一个读写接口,有点啰嗦,但比较规整。
otakustay
2021-12-31 11:16:31 +08:00
final 和 immutable 是不一样的概念
seanzxx
2021-12-31 11:28:27 +08:00
final 是保证变量的值不变,但什么是变量的值你没清楚

final int a = 3; // a 的值是 3 ,你不能再修改 a 的值
a = 4; // 编译错误: cannot assign a value to final variable a

final List b = new ArrayList(); // b 的值是 List 对象的地址(引用),你不能改变 b 的值
b= new LinkedList(); // 编译报错:cannot assign a value to final variable b
Newyorkcity
2021-12-31 11:31:33 +08:00
@seanzxx 一个数组,在 A 时间点,里面啥元素点也没有,在 B 时间点,有了几个元素在里面。这个数组是否发生过变化?不纠结于数组,一个人,A 时间点身高一米七,B 时间点身高一米八,这个人算变化了吧?
agagega
2021-12-31 11:32:37 +08:00
因为你这里的 List 不是值语义
Vegetable
2021-12-31 11:32:55 +08:00
final 和 readonly/mutable 其实是不同层面的概念。在扩大解释之前应该慎重,不要想当然。
aragakiyuii
2021-12-31 11:33:03 +08:00
@Newyorkcity #11 身份证号没变
yangzzzzzz
2021-12-31 11:38:24 +08:00
张三吃胖了还是张三
Kaciras
2021-12-31 11:40:43 +08:00
final 修饰的是指针本身,不是所指的对象。
dying4death
2021-12-31 11:41:43 +08:00
kop1989
2021-12-31 11:42:25 +08:00
@Newyorkcity #11 但 final ,其实指的是户口本上的这个“人”与生物学上的“人”的绑定关系。虽然你的体态、甚至性别都变了,你的户口本依然是你的户口本。
mineralsalt
2021-12-31 11:47:25 +08:00
那为啥 final AtomicInteger a= new AtomicInteger(0) 的 a ,由 0 变 1 是没有违背 final 所暗示的语义呢?

你这种描述根本就不对, a 既不是 0 也不是 1, 它是一个对象, 只要这个对象的指针不改变, 那就没有违反 final
wolfie
2021-12-31 11:49:01 +08:00
@Newyorkcity #6
final 就是不存在张三被换掉的可能。

程序角度 final 限制栈修改,实际堆中的对象里面的成员是否被替换 管不着。


class 项目经理 {

实际干活的 = 李四、王五; // 这个指派张三为项目经理的人管不着。加不加 final 由张三决定。

}

这是一个专为移动设备优化的页面(即为了让你能够在 Google 搜索结果里秒开这个页面),如果你希望参与 V2EX 社区的讨论,你可以继续到 V2EX 上打开本讨论主题的完整版本。

https://www.v2ex.com/t/825448

V2EX 是创意工作者们的社区,是一个分享自己正在做的有趣事物、交流想法,可以遇见新朋友甚至新机会的地方。

V2EX is a community of developers, designers and creative people.

© 2021 V2EX