[英]Java Generics and Inheritance recursion
我遇到了以下使用泛型和繼承的Java代碼。 我真的不明白以下代碼片段的作用:
class A<B extends A<B>> {
...
}
這段代碼有什么作用?
(我從MapDB中的DBMaker那里得到了這個)
這幾乎是清楚的,問題實際上分為兩部分:
1)為什么B extends A
?
2)為什么A
內部B extends A<B>
具有通用類型B
?
這些部分的答案將是:
1)在特定示例中,此類( A
)是構建器類(稱為DBMaker
),因此其大多數方法返回某種類型,這會擴展此構建器的類類型。 這解釋了為什么B
應該擴展A
類。
2)但是,實際上,如果我們將隱藏第二部分...extends A<B>
,我們將只收到class A<B>
。 因此A
具有B
類型的變量。 這就是為什么在...extends A<B>
A被標記為具有類型變量B
類型A
這告訴A
需要派生定義才能做一些工作:
public abstract class A<T extends A<T>> {
protected T instance;
T getOne() {
return instance;
}
}
public class B extends A<B> {
public B() {
instance = this;
}
}
public static void test() {
B b = new B();
b.getOne();
}
這在接口定義中最常用,其中一個人想要顯式地使用在返回類型或參數中實現接口的類的實例,而不是接口本身:
public interface TimeSeries<T extends TimeSeries<T>> {
T join(T ts);
}
public class DoubleTimeSeries implements TimeSeries<DoubleTimeSeries> {
@Override
public DoubleTimeSeries join(DoubleTimeSeries ts) {
return null;
}
}
所以我做了一些測試來解決這個問題,這是我的測試用例,看看如何使用這樣的通用案例:
public class A<B extends A<B>> {
int x = 10;
B test;
void printX() {
System.out.println(x);
}
void setB(B b) {
test = b;
}
void printB() {
System.out.println(test);
}
}
public class B extends A<B> {
}
public class Run {
public static void main(String[] args) {
A<B> test = new A<B>();
B myB = new B();
test.printX();
test.setB(myB);
test.printB();
myB.printB();
}
}
我希望代碼可能是自我解釋的。 如果不發表評論,我會嘗試解釋發生了什么。 查看最后一行myB.printB(),這里我們將得到一個null,因為尚未為myB設置B,但僅用於測試。 這表明我們可以無限遞歸到A中的B類(對於那個問題,在B內)。
我們可以說:
myB.test.printB();
這將得到一個錯誤(空指針),但表明我們現在可以從B中訪問A類中的測試,並且我們可以根據需要遞歸到我們想要的盡可能多的情況。 所以A類的函數作為無限多B類的包裝器。 這有意義嗎?
這使得在定義方法返回類型時更容易,例如:
class A<B extends A<B>> {
public B getMe(){
return (B) this;
}
}
這告訴Java編譯器你在getMe()
方法中返回類A
的子類。
class C extends A<C> {
}
C c = new C();
c.getMe(); //returns C
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.