下面的类是不可变的吗?如果没有,为什么?
如何更改字段?
public class Student {
private String name;
private String age;
public Student(String name, String age) {
this.name = name;
this.age = age;
}
public String getName() {
return name;
}
public String getAge() {
return age;
}
}
答案 0 :(得分:2)
@fge答案可能更完整。但我不知道不可变的必须是线程安全的。对我来说,它们是不同的属性,即使将它们联系起来也是有意义的。
然而,对于不可变的可变性方面,是的,你的班级是。
确实,我不知道这个概念是否存在,但我会说你的课程是“不可改变的”#34; :不仅你不能改变其属性的引用(我称之为shallow immutability
),但你不能改变它的属性值,因为它们本身是不可变的。
---- UPDATE
我错了。
我阅读了约书亚布洛赫在Effective Java中给出的定义,但遗漏了以下内容(其他人提到):
所以正确答案是:
public final class Student {
private final String name;
private final String age;
public Student(String name, String age) {
this.name = name;
this.age = age;
}
public String getName() {
return name;
}
public String getAge() {
return age;
}
}
答案 1 :(得分:2)
它不是一成不变的,因为它可以被子类化(类和getter都不是最终的)。子类可以覆盖getter并暴露可能发生变化的状态。另一个持有Student
引用的类无法保证其状态不会发生变化,因为可能存在可变子类。
不相关的是这些字段不是final或volatile。因此,无法保证另一个线程会看到最新值。
答案 2 :(得分:1)
从技术上讲,除非您执行以下操作,否则它不是永久性的:
final
,否则我可以编写一个更改类的行为的子类,即使其“行为”像一个可变类或使所有的getters最终或使构造函数变为私有并提供静态工厂方法,因此无法有效地进行子类化; final
,因此它们是线程安全的。作为参考,请参阅this page或查看Effective Java。
答案 3 :(得分:1)
让我们看看开源工具Mutability Detector对您的Student
课程的看法:
(免责声明:我是作者)
结果:
Expected: org.mutabilitydetector.stackoverflow.Student to be IMMUTABLE
but: org.mutabilitydetector.stackoverflow.Student is actually NOT_IMMUTABLE
Reasons:
Can be subclassed, therefore parameters declared to be this type could be mutable subclasses at runtime. [Class: org.mutabilitydetector.stackoverflow.Student]
Field is not final, if shared across threads the Java Memory Model will not guarantee it is initialised before it is read. [Field: name, Class: org.mutabilitydetector.stackoverflow.Student]
Field is not final, if shared across threads the Java Memory Model will not guarantee it is initialised before it is read. [Field: age, Class: org.mutabilitydetector.stackoverflow.Student]
让我们看看两种原因,解释它们的含义:
final
或通过不提供公共构造函数来修复。如果您不将类导出到其他用户,并且可以保证代码库中没有子类,则此问题就会消失。final
,尽管还有其他方法可以实现相同的效果。如果你只是在单线程执行中运行,那么这个问题就会消失。使用Mutability Detector here查看产生结果的测试用例。
虽然这个答案与Snicolas的结果相同,但我认为值得向您展示一个可以回答相同问题的自动化工具。