不可变类的示例
我已经知道不可变类的定义,但我需要一些例子。
标准 API 中一些著名的不可变类:
大多数枚举类都是不可变的,但这实际上取决于具体情况。(不要实现可变枚举,这会在某个时候搞砸你。我认为至少标准API中的所有枚举类实际上是不可变的。
java.math.BigInteger 和 java.math.BigDecimal(至少这些类本身的对象,子类可以引入可变性,尽管这不是一个好主意)
java.io.File.请注意,这表示 VM 外部的对象(本地系统上的文件),该对象可能存在也可能不存在,并且有一些方法可以修改和查询此外部对象的状态。但 File 对象本身保持不可变。(java.io 中的所有其他类都是可变的。
java.awt.Font - 表示用于在屏幕上绘制文本的字体(可能有一些可变的子类,但这肯定没有用)
java.awt.Cursor - 表示鼠标光标的位图(在这里,一些子类也可能是可变的或取决于外部因素)
java.util.Locale - 表示特定的地理、政治或文化区域。
虽然大多数集合都是可变的,但 java.util.Collections 类中有一些包装方法,它们返回集合上的不可修改视图。如果您向它们传递一个在任何地方都不知道的集合,则这些集合实际上是不可变的集合。此外,, 、返回不可变的单元素集合,并且还有不可变的空集合。Collections.singletonMap()
.singletonList
.singleton
java.net.URL 和 java.net.URI - 表示资源(在互联网上或其他地方)
java.time
DateTimeException
java.time
可以说基元类型也是不可变的 - 你不能改变42的值,对吧?
类访问控件上下文是一个不可变的类
AccessControlContext 没有任何变异方法。它的状态由一个保护域列表(这是一个不可变的类)和一个DomainCombiner组成。DomainCombiner是一个接口,因此原则上实现可以在每次调用时执行不同的操作。
事实上,保护域的行为也可能取决于当前有效的政策 - 是否将此类对象称为不可变是有争议的。
和访问控制器?
没有 AccessController 类型的对象,因为这是没有可访问构造函数的最终类。所有方法都是静态的。可以说AccessController既不是可变的,也不是不可变的,或者两者兼而有之。
这同样适用于所有其他不能有对象(实例)的类,最著名的是:
in
out
err
)构造后无法更改不可变类。因此,例如,Java是不可变的。String
要使类不可变,必须使类以及所有字段和 .例如,以下类是不可变的:final
private
final
public final class Person {
private final String name;
private final int age;
private final Collection<String> friends;
public Person(String name, int age, Collection<String> friends) {
this.name = name;
this.age = age;
this.friends = new ArrayList(friends);
}
public String getName() {
return this.name;
}
public int getAge() {
return this.age;
}
public Collection<String> getFriends() {
return Collections.unmodifiableCollection(this.friends);
}
}
我在代码示例中添加了一个方法,演示如何处理集合,这是一个要点。
在可能的情况下,你应该使类不可变,因为这样你就不必担心线程安全之类的事情。