我有一個問題,我實際上可以解決自己,但我仍然不明白爲什麼我原來的代碼不起作用,或者如果有一個更優雅的解決方案比我找到。我在這裏介紹我的代碼的簡化版本。「有私人訪問」的錯誤與泛型
考慮下面的抽象超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的私有字段,然後我們稱之爲平方米,該實例。
我有幾個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>
。
令我驚訝的是,你的第二個代碼示例不會編譯 - 但知道這一點,編譯器是完全正確的批評我的原代碼。非常感謝您的詳細解釋! – Bernhard
這裏的消息當然應該是'private'是一個錯誤的訪問修飾符,用於你想要訪問子類的任何字段?爲什麼不使用受保護的修飾符,或提供一個getter方法? – Bobulous
Arkanon - 我沒有訪問子類中的字段,這就是爲什麼我想保持它的私密性。如果您再次查看代碼,您會看到我正在訪問我聲明的類中的私有字段。否則,即使在投射時也會出現編譯錯誤! – Bernhard