我正在阅读Records的文档, 但不理解“浅不可变”一词。我们所说的浅不可变是什么意思?如果它是不可变的,为什么我们需要一个复制构造函数?为什么有两个“Hello World!”?
对于所有记录类,以下不变量必须成立:如果记录 R 的组件是 c1、c2、... cn,那么如果记录实例被复制如下:
R copy = new R(r.c1(), r.c2(), ..., r.cn()); // copy constructor ?
Run Code Online (Sandbox Code Playgroud)
那么一定是这样的r.equals(copy)。
此代码无法编译:
List<? extends List<Number>> list = new ArrayList<>();
List<List<Double>> anotherList = (List<List<Double>>) list;
Run Code Online (Sandbox Code Playgroud)
请注意,IntelliJ 不会报告任何错误。当我单击“运行”时,它只会编译失败。
我理解为什么这不能在概念层面上编译。list是“扩展的List<Number>东西”的列表,而“东西”永远不会是List<Double>,因为List<Double>它不是 的子类型List<Number>,并且因为它们具有相同的擦除,所以没有类型可以实现两者。
但是,当我尝试按照语言规范中的措辞来确定此强制转换是否有效时,我发现语言规范似乎说这是一个有效的强制转换!
这是我的推理:
强制转换满足从S( List<? extends List<Number>>) 到T( List<List<Double>>)的窄引用转换的所有三个要求。
5.1.6.1 . 允许的缩小参考转换
如果以下所有条件都为真,则存在从引用类型 S 到引用类型 T 的收缩引用转换:
S 不是 T 的亚型
如果存在作为 T 超类型的参数化类型 X 和作为 S 超类型的参数化类型 Y,使得 X 和 Y 的擦除相同,则 X 和 Y 不可证明不同(第 4.5 节) .
以下情况之一适用:
- S 和 …