簡體   English   中英

“ A級 <T extends SomeClass<T> &gt;”的工作方式不同於B類 <T extends SomeInterface<T> &gt;? (是)

[英]“class A <T extends SomeClass<T>>” works differently from class B <T extends SomeInterface<T>> ? (Yes)

而定義涉及接口可比性

class B <T extends Comparable<T>>

是眾所周知的且可實例化的,所以在擴展類而不是接口時,相同的用法不能以相同的方式起作用。 這是一個例子

class G <T extends Box<T>> {
    T val;
    G(T val) {
        this.val = val;
    }
}

上面的類可以編譯,但是我無法找到實例化G的方法。它似乎需要Box的無限嵌套。

G<Box<Box<..>>>

這是我對Box類的定義

class Box <T> {
    T val;
    Box(T val) {
        this.val = val;
    }
}

為了幫助討論,這里有一些類似的例子。 我測試了所有代碼。

下課的意思對我很清楚

class D <T extends Box<String>> {
    T val;
    D(T val) {
        this.val = val;
    }
}

我們可以實例化使用

    D<Box<String>> d = new D<>( new Box<String> ("hello") );

我們可以對此進行概括,以便Box可以包含任何內容

class F <S, T extends Box<S>> {
    T val;
    F(T val) {
        this.val = val;
    }
}

我們可以實例化使用

    F<String,Box<String>> f = new F<>( new Box<String> ("hello") );

回到最初的問題,以下是什么意思,以及如何/可以將其實例化?

class G <T extends Box<T>> {
    T val;
    G(T val) {
        this.val = val;
    }
}

G類是我對上述D類進行泛化的首次嘗試,以便Box可以容納任何類型,而不僅僅是String。 后來我想到了F類作為解決問題的方法,但我想知道G的含義是什么,為什么它與T extends SomeInterface<T>時的含義不同。

如果Box類沒有帶T構造函數,則可以創建一個擴展Box的類。 例如:

class NewBox extends Box<NewBox> {
    ...
}

然后您可以實例化G

G<NewBox> g = new G<>(new NewBox());

但在您的情況下,Box具有構造函數Box(T val){...} ,那么NewBox需要與super匹配的構造函數,例如:

class NewBox extends Box<NewBox> {
    NewBox(NewBox val) {
        super(val);
    }
}

要實例化它,您應該以null結尾,否則將導致無限嵌套:

G<NewBox> g = new G<>(new NewBox(new NewBox(new NewBox(null))));

更新:回答你原來的問題: G <T extends Box<T>>意味着T必須是類型Box或任何后裔Box 正如您正確提到的那樣,它將導致無限嵌套。 但是您仍然可以實例化它, 而無需使用通配符null作為類G的構造函數的參數來創建額外的類 (如上述NewBox ):

G<?> tg = new G<>(null);

如果您擔心類型綁定T extends Box<T>意味着可以指定為類型參數的唯一類型必須擴展Box

該技術用於指定您可以對類型進行的其他操作(例如,眾所周知的Comparable<T> ),因此使用類而不是接口實際上並不常見。

讓我給你舉個例子。 說我們有以下操作

interface Op1<T>{
    void doOp1(t: T): T
}

interface Op2<T> {
   void doOp2(t: T): T
}

class MyClass implements Op1<MyClass>, Op2<MyClass>{
    //By implementing Op1 and Op2 you
    //specify that operations doOp1 and doOp2
    // can be applied to variable of typr MyClass
}

現在,您要實現通用容器,該容器接受可以將Op1Op2類型的元素應用於

class MyContainer<T extends Op1<T> & Op2<T>>{
   //you can apply doOp1 and doOp2 to any variable of the type T
}

MyContainer<MyClass> t = //... Ok
MyContainer<Integer> t = //... Not ok

在函數式編程中,類似(但不是完全相同)的東西稱為類型類

答案簡介

@Ruslan@Some Name的答案以及@Some Name問題的評論中得出,這是兩者之間區別的概要

class G <T extends SomeClass<T>>
class B <T extends SomeInterface<T>>  
class Enum<E extends Enum<E>>   

我發現編寫經過測試的示例會有所幫助。

1. class G <T extends SomeClass<T>>

G類要求將T類型定義如下

class T extends SomeClass<T> {}

這是一個像T這樣的類的例子

class RussianBox extends Box<RussianBox> {
    RussianBox(RussianBox box) {
        super(box);
    }
}

其中Box類定義為

class Box <T> {
    T value; 
    Box(T value) {
        this.value = value;
    }
    public String toString() {
        return this.getClass().getSimpleName()+" containing {"+this.value+"}";
    }
}

這是一個像G這樣的類的例子

class RussianBoxContainer <T extends Box<T>>   {
    T value; 
    RussianBoxContainer(T value) {
        this.value = value;
    }
    public String toString() {
        return this.getClass().getSimpleName()+" containing {"+this.value+"}";
    }
}

以下代碼實例化了這三個類

    Box<String> box = new Box<>("Gold");
    out.println("box = " + box );

    RussianBox russianBox = new RussianBox( new RussianBox(null) );
    out.println("russianBox = " + russianBox );

    RussianBoxContainer<RussianBox> containerForARussianBox = new RussianBoxContainer<>(russianBox);
    out.println("containerForARussianBox = " + containerForARussianBox );

並產生以下輸出

box = Box containing {Gold}
russianBox = RussianBox containing {RussianBox containing {null}}
containerForARussianBox = RussianBoxContainer containing {RussianBox containing {RussianBox containing {null}}}

2. class B <T extends SomeInterface<T>>

B類要求將T類型定義如下

class T extends SomeClass implements SomeInterface<T> {}

java.lang.Integer類是T類的示例

class Integer extends Number implements Comparable<Integer>

因此,當引用接口而不是類時,此模式的行為將有很大不同。

3. class Enum<E extends Enum<E>>

現在創建一個類似 Enum的類。 這是一個例子

class RussianBoxContainer2 <T extends RussianBoxContainer2<T>>   {
    RussianBoxContainer2<T> value; 
    RussianBoxContainer2(RussianBoxContainer2<T> box) {
        this.value = box;
    }
    public String toString() {
        return this.getClass().getSimpleName()+" containing {"+this.value+"}";
    }
}

就像Enum一樣,我們需要先子類RussianBoxContainer2然后才能使用RussianBoxContainer2 這是一個子類的例子

class RussianBox2 extends RussianBoxContainer2<RussianBox2> {
    RussianBox2(RussianBox2 box) {
        super(box);
    }
}

以下代碼實例化了這兩個類

RussianBox2 russianBox2 = new RussianBox2(new RussianBox2(null));
out.println("russianBox2 = " + russianBox2 );

RussianBoxContainer2<RussianBox2> containerForARussianBox2 = new RussianBoxContainer2<>(russianBox2);
out.println("containerForARussianBox2 = " + containerForARussianBox2 );

並產生以下輸出

russianBox2 = RussianBox2 containing {RussianBox2 containing {null}}
containerForARussianBox2 = RussianBoxContainer2 containing {RussianBox2 containing {RussianBox2 containing {null}}}

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM