不可变类的定义如下: 一旦创建这种类的实例后,实例不可再次更改
java标准API中一些著名的不可变类:
java.lang.String(已经提到)
基本类型的包装器类:
java.lang.Integer,
java.lang.Byte,
java.lang.Character,
java.lang.Short,
java.lang.Boolean,
java.lang.Long,
java.lang.Double,
java.lang.Float
java.lang.StackTraceElement(用于构建异常stacktraces)
大多数枚举类是不可变的,但实际上这取决于具体情况。(不要实现可变的枚举,这会在某种程度上使您陷入困境。)我认为,至少标准API中的所有枚举类实际上都是不可变的。
java.math.BigInteger和java.math.BigDecimal(至少这些类本身的对象,子类可能会引入可变性,尽管这不是一个好主意)
java.io.File。请注意,这表示VM外部的对象(本地系统上的文件),该对象可能存在也可能不存在,并且具有一些方法可以修改和查询此外部对象的状态。但是File对象本身保持不变。(java.io中的所有其他类都是可变的。)
java.awt.Font-表示用于在屏幕上绘制文本的字体(可能有一些可变的子类,但这肯定没有用)
java.awt.BasicStroke-在图形上下文中绘制线条的辅助对象
java.awt.Color-(至少是此类的对象,某些子类可能是可变的,或取决于某些外部因素(如系统颜色)),并且java.awt.Paint的大多数其他实现如下
java.awt.GradientPaint,
java.awt.LinearGradientPaint
java.awt.RadialGradientPaint,
(我不确定java.awt.TexturePaint)
java.awt.Cursor-表示鼠标光标的位图(在这里,某些子类也可能是可变的或取决于外部因素)
java.util.Locale-表示特定的地理,政治或文化区域。
java.util.UUID-尽可能全局唯一的标识符
尽管大多数集合都是可变的,但java.util.Collections类中有一些包装方法,它们返回集合上不可修改的视图。如果将它们传递给任何地方都未知的集合,那么实际上它们是不可变的集合。此外,Collections.singletonMap(),.singletonList,.singleton返回不可变的一个元素的集合,并且也有不可变空的。
java.net.URL和java.net.URI-表示资源(在Internet或其他地方)
java.net.Inet4Address和java.net.Inet6Address,java.net.InetSocketAddress
java.security.Permission的大多数子类(表示某些操作或某些代码所需要的许可权),但java.security.PermissionCollection和子类不是。
java.time除了的所有类别DateTimeException都是不可变的。子包的大多数类java.time也是不可变的。
可以说原始类型也是不可变的-您不能更改42的值,可以吗?
是AccessControlContext类是不可变的类
AccessControlContext没有任何更改方法。它的状态包括一个ProtectionDomains(这是一个不可变的类)列表和一个DomainCombiner。DomainCombiner是一个接口,因此原则上实现可以在每次调用时执行不同的操作。
实际上,ProtectionDomain的行为也可能取决于当前生效的策略-是否将此类对象称为不可变是有争议的。
和AccessController?
没有类型为AccessController的对象,因为这是没有可访问构造函数的最终类。所有方法都是静态的。有人会说AccessController既不是可变的也不是不可变的,或者两者都不是。
这对于所有其他没有对象(实例)的类都有效,最著名的是:
java.lang.Void
java.lang.System中的(但是这有一些可变的静止状态- ,in,)outerr
java.lang.Math(这也是-随机数生成器)
java.lang.reflect.Array
java.util.Collections
java.util.Arrays