無法具體化標題,抱歉。
例如,我們有一個Parent類和一個Child類:
package test;
public class Parent {
}
package test;
public class Child extends Parent {
}
Parent還有一個可以在其欄位中包含 's 子級的類,稱為a:
package test;
public class Holder<A extends Parent> {
public A a;
}
讓我們創建該類的一個實體并嘗試將值分配給a:
package test;
public class Main {
public static void main(String[] main) {
Holder<Child> holder = new Holder<>();
holder.a = new Child();
}
}
到目前為止,一切都很好。但是假設我們想將此分配移動到 aHolder的建構式:
package test;
public class Holder<A extends Parent> {
public A a;
public Holder() {
a = new Child();
}
}
現在我們得到一個錯誤:
Error:(7, 13) java: incompatible types: test.Child cannot be converted to A.
所以,我的問題是,為什么編譯器看不到那A是 aParent的孩子?即使我們設定<A extends Parent>. 為什么我們可以在類外賦值,但不能在類內賦值?我能以某種方式解決這個問題嗎?
我知道我們可以替換A和Parent洗掉該型別引數或傳遞new Child()給建構式的引數 in Main,但這是因為我給出了一個簡化的問題示例。
uj5u.com熱心網友回復:
有界泛型型別引數,如A extends Something不可寫(以及上限通配符)。除了其他型別的變數之外,任何將任何內容分配給變數的嘗試都會失敗。 ? extends Something aAnull
為了理解原因,讓我們考慮以下代碼:
public class Parent {}
public class Child extends Parent {}
public class GrandChild extends Child {}
public class Holder<A extends Parent> {
public A a;
public void setA(A a) {
this.a = a;
}
}
A在類中只是將在運行時Holder提供的型別的占位符。這是一種告訴編譯器我們現在不知道型別是什么的方法。但它將是在其繼承鏈中具有類的特定型別。編譯器將在檢查對變數執行的操作是否安全時考慮該資訊。Parenta
在下面的代碼中,編譯器將不允許將 的物件分配Child為 的值a,因為它與型別不兼容GrandChild(恰好是 的實際型別A)。只有實體GrandChild及其子型別可以毫無問題地分配。
public static void main(String[] args) {
Holder<GrandChild> grandChildHolder = new Holder<>();
grandChildHolder.setA(new GrandChild()); // no issues
grandChildHolder.setA(new Child()); // compilation error
}
同樣,類中的以下分配Holder也不會成功,因為型別A是已知的,只有Holder類會被實體化。并且 compile 不擁有是否會是 , 等的資訊Child,GrandChild因此它不會認為這些操作是安全的。
public class Holder<A extends Parent> {
public A a;
// instance initialither block (runs when Holder object is being created)
{
a = new Child(); // compilation error - type A could be a GrandChild
a = new GrandChild(); // compilation error - type A could potentially be represented by class incompatible with GrandChild
a = null; // no issues because null is a valid value for any type
}
public void setA(A a) {
this.a = a;
}
}
A extends Parent當希望使類或方法能夠處理不同型別的物件并同時對有效型別的范圍施加一定限制以訪問Parent類的行為時,上限泛型引數(例如)很有用(讓我們假設有一些像 work(),goShoping()等)。
如果您在沒有擴展子句的情況下宣告持有者,Holder<A>則只有Object類 ( hashCode(), equals(), toString()) 的方法可以使用型別的變數和引數訪問A。
此外,子句extends Parent將允許編譯器發現引入無效型別引數的嘗試:
Holder<String> stringHolder; // error:
// type argument String is not within the bounds of type A
uj5u.com熱心網友回復:
A是一個 [型別] 引數。它不是一個實際的型別。像大多數類一樣,您可以通過方法建構式中的引數來初始化成員。
public class Main {
public static void main(String[] args) {
new Holder<Child>(new Child());
}
}
class Parent {
}
class Child extends Parent {
}
class Holder<A extends Parent> {
public A a;
public Holder(A a) {
this.a = a;
}
}
轉載請註明出處,本文鏈接:https://www.uj5u.com/qita/454387.html
下一篇:C#泛型繼承,基類轉換
