![](/img/trans.png)
[英]Instantiate a concrete Java class that uses recursive generics in Kotlin
[英]How to instantiate recursive bound generics with inner class in Java?
我想將內部類作為參數的泛型外部類。 我期待,我將從基類派生出來,或者使用它的內部,或者從內部派生出來。 在每個級別,我都希望從當前的派生水平開始限制內部類別的使用。
不幸的是,我在使用模式時會遇到各種錯誤和警告,這使我無法想象,如何使用它。
package tests.java;
public class Try_GenericInnerRecursion {
// base class, consisting of outer and inner parts
public static class Outer1<E extends Outer1<E>.Inner1> {
public class Inner1 {
}
public void addElement(E e) {
System.out.println("Added " + e.toString());
}
}
// extending outer, but not inner
public static class Outer2<E extends Outer1<E>.Inner1> extends Outer1<E>{
}
// extending both outer and inner
public static class Outer3<E extends Outer3<E>.Inner3> extends Outer1<E>{
public class Inner3 extends Inner1 {
}
}
// extending both outer and inner and stopping extension
public static class Outer4 extends Outer1<Outer4.Inner4> {
public class Inner4 extends Outer1<Inner4>.Inner1 {
}
}
// instantiating
public static void main(String[] args) {
Outer1<Outer1.Inner1> a1; // WARNING: Outer1.Inner1 is a raw type
a1 = new Outer1<Outer1.Inner1>(); // WARNING: Outer1.Inner1 is a raw type
Outer1<?> a2; // OK
a2 = new Outer1<?>(); // ERROR: Cannot instantiate the type Outer1<?>
Outer1<Outer1<?>.Inner1> a3; // ERROR: Bound mismatch: The type Outer1<?>.Inner1 is not a valid substitute for the bounded parameter <E extends Outer1<E>.Inner1> of the type Outer1<E>
Outer1<? extends Outer1<?>.Inner1> a4; // OK
a4 = new Outer1<Outer1.Inner1>(); // ERROR: Type mismatch
Outer2<Outer1.Inner1> b1; // WARNING: Outer1.Inner1 is a raw type
b1 = new Outer2<Outer1.Inner1>(); // WARNING: Outer1.Inner1 is a raw type
// and so on
}
}
我該如何正確使用這種模式?
我相信你可以做到
DerivedCorpus1<?>
在通配符捕獲期間,它變成了
DerivedCorpus1<x> where x extends Corpus<x>.Element
哪個是正確的。
在你的例子中
DerivedCorpus1<? extends Corpus<?>.Element>
在通配符捕獲期間,它變成了
DerivedCorpus1<x> where x extends Corpus<x>.Element
and x extends Corpus<?>.Element
顯然, extends Corpus<?>.Element
子句是多余的。
Outer1<Outer1.Inner1> a1; // WARNING: Outer1.Inner1 is a raw type
實際上,我得到“類型參數Outer1.Inner1不在類型變量E`的范圍內”。
Outer1.Inner1
是原始類型,因為Outer1
是原始類型。 要使用非原始類型,您需要編寫Outer1<something>.Inner1
。 但是, something
也必須依次擴展Outer1<something>.Inner1
。 為了像這樣進行遞歸,你需要一個命名的遞歸類型。 不幸的是,由於Inner1
是一個非靜態內部類,它有一個對Outer1
實例的隱式引用,因此任何擴展它的類都需要有一個封閉的Outer1
實例。 Outer4
和Inner4
基本上都是這樣做的。
Outer4 a1 = new Outer4(); // compiles fine
a2 = new Outer1<?>(); // ERROR: Cannot instantiate the type Outer1<?>
你永遠不能做new something<?>()
。
Outer1<Outer1<?>.Inner1> a3; // ERROR: Bound mismatch: The type Outer1<?>.Inner1 is not a valid substitute for the bounded parameter <E extends Outer1<E>.Inner1> of the type Outer1<E>
這是真的。 Outer1<?>.Inner1
不是Outer1<E>.Inner1
的子類型Outer1<E>.Inner1
- 它是另一種方式Outer1<E>.Inner1
是Outer1<?>.Inner1
的子類型Outer1<?>.Inner1
。 這就像ArrayList<?>
不是ArrayList<String>
的子類型一樣; 反過來說。
Outer1<? extends Outer1<?>.Inner1> a4; // OK
這沒關系,因為你在頂層有一個通配符,你的通配符的邊界與類型參數E
的綁定相交。 事實上,任何滿足E
的原始界限的東西都必須滿足這個界限,所以這個界限是沒用的,這與Outer1<?> a2;
以上。
a4 = new Outer1<Outer1.Inner1>(); // ERROR: Type mismatch
由於其他原因導致a1
不起作用的原因( Outer1.Inner1
不滿足E
的界限), Outer1.Inner1
不起作用。 它還不滿足你的界限( Outer1<?>.Inner1
)我相信。
Outer2<Outer1.Inner1> b1; // WARNING: Outer1.Inner1 is a raw type
出於同樣的原因,這實際上給出了與a1
相同的錯誤
通用規范
在我繼續討論實例化問題之前,我修改了你的通用定義:
Outer1<E extends Outer1<E>.Inner1>
Outer1基本上應該包含Inner1類型的元素或它的任何子類。 因此,Outer1對象的類型不相關,可以使用以下代碼替換:
Outer1<E extends Outer1<?>.Innter1>
此外,使用上面提到的稍微修改了擴展類。
實例化
對於對象的實例化,您說明如下:
Outer1<Outer1.Inner1> a1; // WARNING: Outer1.Inner1 is a raw type a1 = new Outer1<Outer1.Inner1>(); // WARNING: Outer1.Inner1 is a raw type
正如newacct已經提到的,雖然在實例化對象時沒有指定任何類型,但是Outer1
被聲明為泛型類型。 因此,代碼應更改為以下代碼:
Outer1<Outer1<?>.Innter1> a1; // or simply Outer1<?> a1;
a1 = new Outer1<Outer1<?>.Innter1>(); // or simply a1 = new Outer1<>();
類似於分配將基類擴展為該基類類型的類。
您可以使用泛型類型定義指定實例將包含的元素類型。
像這樣的聲明
Outer1<Outer1<?>.Innter1> test;
將接受任何擴展Outer1
實例,它們也匹配泛型類型。 這意味着您只能分配
test = new Outer1<Outer1<?>.Inner1>();
test = new Outer2<Outer2<?>.Inner1>();
它,但不是Outer3
甚至Outer4
!
即使您進一步修改代碼以添加fe
public static class Outer5<E extends Outer1<?>.Inner1> extends Outer1<E>{
public class Inner5 extends Inner1 {
}
}
你只能添加
test = new Outer5<Outer5<?>.Inner1>();
但不是
test = new Outer5<Outer5<?>.Inner5>(); // FAILS!
將Inner1
定義為類型參數的東西。
但是,這個問題實際上是一個非常簡單的解決方案。 如果您像這樣定義對象:
Outer1<? extends Outer1<?>.Inner1> test2;
你實際上可以做以下事情:
test2 = new Outer1<Outer1<?>.Inner1>();
test2 = new Outer2<Outer2<?>.Inner1>();
test2 = new Outer3<Outer3<?>.Inner3>();
test2 = new Outer4();
test2 = new Outer5<Outer1<?>.Inner1>();
test2 = new Outer5<Outer5<?>.Inner1>();
test2 = new Outer5<Outer5<?>.Inner5>();
正如您現在明確告訴編譯器允許Inner1
類型本身或其任何擴展。
碼
我已經更新了你的代碼並添加了一些新的賦值,以驗證所做的更改實際上不會產生任何編譯錯誤或警告,除了redundant type arguments in new expression
的redundant type arguments in new expression
因為顯式指定了類型參數而不是使用菱形運算符<>
:
public class GenericInnerRecursion
{
// base class, consisting of outer and inner parts
public static class Outer1<E extends Outer1<?>.Inner1> {
public class Inner1 {
}
public void addElement(E e) {
System.out.println("Added " + e.toString());
}
}
// extending outer, but not inner
public static class Outer2<E extends Outer1<?>.Inner1> extends Outer1<E>{
}
// extending both outer and inner
public static class Outer3<E extends Outer3<?>.Inner3> extends Outer1<E>{
public class Inner3 extends Inner1 {
}
}
// extending both outer and inner and stopping extension
public static class Outer4 extends Outer1<Outer4.Inner4> {
public class Inner4 extends Outer1<Inner4>.Inner1 {
}
}
public static class Outer5<E extends Outer1<?>.Inner1> extends Outer1<E>{
public class Inner5 extends Inner1 {
}
}
// instantiating
public static void main(String[] args) {
Outer1<Outer1<?>.Inner1> a1;
a1 = new Outer1<Outer1<?>.Inner1>();
Outer1<?> a2;
a2 = new Outer1<>();
Outer1<Outer1<?>.Inner1> a3;
Outer1<? extends Outer1<?>.Inner1> a4;
a4 = new Outer1<Outer1<?>.Inner1>();
Outer2<Outer1<?>.Inner1> b1;
b1 = new Outer2<Outer1<?>.Inner1>();
// and so on
// assigning extension-classes to the parent-class
Outer1<Outer1<?>.Inner1> c1;
c1 = new Outer2<Outer2<?>.Inner1>();
// assigning inner-extension-classes to parent-class
Outer1<Outer3<?>.Inner3> c2;
c2 = new Outer3<Outer3<?>.Inner3>();
// assigning extension class without specified generics to parent class
Outer1<Outer4.Inner4> c3;
c3 = new Outer4();
Outer1<Outer1<?>.Inner1> test;
test = new Outer1<>();
test = new Outer2<>();
test = new Outer5<Outer5<?>.Inner1>();
Outer1<? extends Outer1<?>.Inner1> test2;
test2 = new Outer1<Outer1<?>.Inner1>();
test2 = new Outer2<Outer2<?>.Inner1>();
test2 = new Outer3<Outer3<?>.Inner3>();
// new Outer3<Outer3<?>.Inner1>(); not possible as generic type extends Outer3<?>.Inner3 and not Outer1<?>.Inner1!
test2 = new Outer4();
test2 = new Outer5<Outer1<?>.Inner1>();
test2 = new Outer5<Outer5<?>.Inner1>();
test2 = new Outer5<Outer5<?>.Inner5>();
}
}
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.