【发布时间】:2013-12-19 03:13:46
【问题描述】:
我遇到了一个我可以自己解决的问题,但我仍然不明白为什么我的原始代码不起作用,或者是否有比我找到的更优雅的解决方案。我在这里展示我的代码的简化版本。
考虑以下抽象超类 X:
public abstract class X{
private int i;
public void m1(X x){
x.i = 1;
m2(x);
}
public abstract void m2(X x);
}
当调用 m1 时,我们操作传递的实例的 X 的私有字段,然后使用该实例调用 m2。
我有几个 X 的子类,它们在某种意义上都是相似的,它们也声明了它们操作的私有成员。为了实现这一点,他们总是需要在 m2 开始时进行演员表。这是其中之一:
public class Y extends X{
private int j;
public void m2(X x){
Y y = (Y) x;
y.j = 0;
}
}
但是 - 我可以保证每次调用 X 的子类的实例的 m1 都将始终具有相同类型的参数,例如当我有 Y 的实例时,方法 m1 的参数将始终是 Y 的另一个实例。
由于这个保证,我想通过引入泛型来使强制转换变得不必要。这就是我希望我的子类的样子:
public class Y extends X<Y>{
private int j;
public void m2(Y y){
y.j = 0;
}
}
超类 X 现在必须是什么样子?我的第一次尝试是:
public abstract class X<T extends X<T>>{
private int i;
public void m1(T x){
x.i = 1;
m2(x);
}
public abstract void m2(T x);
}
但是 - 这不起作用,当我编译它时,我收到以下错误:
X.java:6: error: i has private access in X
这通常是您尝试访问另一个类的私有成员时得到的结果。显然,Java 并不承认 T 也始终是 X 的实例,尽管我在声明中使用了“T extends X”。
我这样固定 X:
public abstract class X<T extends X<T>>{
private int i;
public void m1(T x){
X<?> y = x;
y.i = 1;
m2(x);
}
public abstract void m2(T x);
}
至少我不再使用强制转换了——但是为什么需要这个额外的分配呢?为什么原始代码不起作用?另外,我发现很奇怪我必须使用X<?>,而不能使用X<T>。
【问题讨论】:
标签: java generics inheritance