java - 使用自限泛型的私有(private)访问

标签 java generics visibility

将私有(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> 类型的成员和 OTest<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/

相关文章:

javascript - 展示隐形 parent 的 child

列表项中的 Android ListView ImageView 在滚动时隐藏

java - 将托管 bean 转换为 EJB

java - 未找到 android 项目中的 native 库(UnsatisfiedLinkError)

Swift 泛型错误 : Cannot convert value of type 'Type<T>' to expected argument type 'Type<_>'

ios - Swift 泛型在使用继承时不会实例化泛型

java - 子类成员变量对另一个子类的可见性

java - 如何仅使用 JDK 注入(inject)属性文件?

java - URL.setURLStreamHandlerFactory

java - 为什么不能在 Java 中将 Collection<SomeType> 转换为 Collection<OtherType> ?