将私有(private)字段访问与 CRTP 相结合在 Java 中似乎在可见性规则中遇到了一个奇怪的边缘情况:
public abstract class Test<O extends Test<O>> implements Cloneable {
private int x = 0;
@SuppressWarnings("unchecked")
@Override
protected final O clone() {
try {
return (O) super.clone();
} catch (CloneNotSupportedException ex) {
throw new AssertionError(ex);
}
}
public final int getX() {
return x;
}
public final O withX(int x) {
O created = clone();
created.x = x; // Compiler error: The field Test<O>.x is not visible
return created;
}
}
只需将 withX()
方法更改为此...
public final O withX(int x) {
O created = clone();
Test<O> temp = created;
temp.x = x;
return created;
}
...使代码编译。我在 Oracle 的 javac
和 Eclipse 的编译器中对此进行了测试。给了什么?
最佳答案
这实际上不是泛型的问题。 JLS inheritance rules防止私有(private)字段在子类中可见。因为 X 是私有(private)的,所以它不是 O
类型的成员, 即使它是 Test<O>
类型的成员和 O
是 Test<O>
的子类型.如果您使用了如下代码:
public final O withX(int x) {
Test<O> created = clone();
created.x = x;
return (O) created;
}
它会起作用的。这是 Java 不支持 LSP 的一个实例,但这只是类型系统的一个局部问题,因为私有(private)字段仅对相同类型的对象可用。如果它不以这种方式工作,那么私有(private)字段就不会真正是私有(private)的。我不认为对递归模板规则有特殊异常(exception)是个好主意。
请注意,这实际上绝不是您可以做的事情的限制。当您想要进行更改时,您始终可以将子类型转换为父类(super class)型,就像您在替代代码中所做的那样。
关于java - 使用自限泛型的私有(private)访问,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/7289019/