考虑下面的类,我相信它正确地称为 self-typed类:
public abstract class Example<E extends Example<E>> {
/** Constructs an instance of the subclass */
protected abstract E construct();
/** Do a private operation in the base class */
private void specialOp() {}
public E get1() {
E obj = construct();
// Error: The method specialOp() from the type Example<E> is not visible
obj.specialOp();
return obj;
}
public E get2() {
Example<E> obj = construct();
obj.specialOp();
// Warning: Type safety: Unchecked cast from Example<E> to E
return (E)obj;
}
public E get3() {
E obj = construct();
((Example<E>)obj).specialOp();
return obj;
}
}
也就是说,扩展此类的实现将具有如下所示的类型签名:
public class SubExample extends Example<SubExample>
三个中的每一个 get*()
方法表面上做同样的事情 - 构造 Example
的子类,在实例上执行私有(private)方法,并将其作为其子类型返回。但是,只有最后一个示例可以在没有警告的情况下进行编译。
get1()
中的行为即使没有泛型也是一个错误,请考虑:
public class Example {
private void specialOp() {};
public void get(SubExample e) {
// Error: The method specialOp() from the type Example is not visible
e.specialOp();
}
public static class SubExample extends Example {}
}
我理解,即使这对我来说似乎是不必要的限制。同样get3()
有道理,虽然我不喜欢这样的 Actor 。但是get2()
让我困惑。我明白了E
从技术上讲,是 Example<E>
的子类型,但这个泛型的边界不能确保所有 Example<E>
也是E
是?如果是这样,为什么这样类型转换不安全?是否可以从 Example<E>
进行转换至E
没有警告?
最佳答案
并非全部Example<E>
s 必须是 E
s:
public class A extends Example<A> { ... }
public class B extends Example<A> { ... }
Example<A> notAnA = new B();
所以编译器是正确的。
请注意get3()
也可以写成:
public E get3() {
E obj = construct();
Example<E> objAsEx = obj;
objAsEx.specialOp();
return obj;
}
因此,即使没有显式强制转换,编译器也知道代码是正确的。不过,它似乎并没有应用这些知识来允许私有(private)成员在不手持的情况下进行访问。
关于Java自类型方法: cannot safely cast to actual type,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/24115354/