簡體   English   中英

使用未知的泛型類型實例化並應用泛型方法-Java

[英]Instantiate and apply generic method with unknown generic type - Java

我需要實例化具有未知通用類型的對象,然后對其應用通用方法。 我站在這里:

public static void main(String[] args)
{
    BarIf bar = newRandomBarImpl();

    Foo foo1 = newFooBar(bar.getClass()); // warning
    Foo<?> foo2 = newFooBar(bar.getClass()); // error
    Foo<? extends BarIf> foo3 = newFooBar(bar.getClass()); // error

    foo1.doSomething(bar); // warning
    foo2.doSomething(bar); // error
    foo3.doSomething(bar); // error
}

static <T extends FooIf<S>, S extends BarIf> T newFooBar(Class<S> barClass){}

static <T extends BarIf> T newRandomBarImpl(){}

interface FooIf<T extends BarIf>
{
    public void doSomething(T t);
}

interface BarIf{}

class Foo<T extends BarIf> implements FooIf<T>
{
    public void doSomething(T t){}
}

奇怪的是,對於foo2和foo3,newFooBar()方法返回FooIf而不是Foo。 我猜類型推斷是一團糟。 但是由於我不知道Bar類型,所以無法傳遞方法的通用參數。

我需要的是Foo<bar.getClass()> 有辦法嗎?

我嘗試使用TypeToken,但最終得到的是T類型而不是實際的Bar類型。 有機會使用嗎?

首先,像

static <T extends BarIf> T newRandomBarImpl(){}

廢話 它基本上說:“無論調用者用什么替換T ,該方法都將返回它”。 換句話說,你可以寫

ArbitraryTypeExtendingBarIf x=newRandomBarImpl();

沒有得到編譯器警告。 顯然,這是行不通的。 newRandomBarImpl()ArbitraryTypeExtendingBarIf一無所知。 方法名稱建議您實際上要表達newRandomBarImpl()可以返回BarIf的任意實現,但這是對BarIf的不必要使用,

BarIf newRandomBarImpl(){}

已經表示此方法可以返回BarIf的任意子類型。 實際上,由於BarIf是抽象類型,因此此方法必須返回BarIf的子類型,並且在任何地方都沒有指定它將是哪種類型。

聲明同樣如此

static <T extends FooIf<S>, S extends BarIf> T newFooBar(Class<S> barClass){}

它還聲稱,調用者可以選擇FooIf方法將返回的實現。 正確的聲明是

static <S extends BarIf> FooIf<S> newFooBar(Class<S> barClass){}

該方法決定返回的FooIf實現,而不是調用方。


關於您處理FooIf的其他嘗試,您不能使用帶通配符參數化的類型來以這種方式工作,也不能使用Reflection對其進行修復。 但是您可以使用類型參數編寫通用代碼:

public static void main(String[] args)
{
    BarIf bar = newRandomBarImpl();
    performTheAction(bar.getClass(), bar);
}
static <T extends BarIf> void performTheAction(Class<T> cl, BarIf obj) {
    FooIf<T> foo=newFooBar(cl);
    foo.doSomething(cl.cast(obj));
}
static <S extends BarIf> FooIf<S> newFooBar(Class<S> barClass){}
static BarIf newRandomBarImpl(){}

interface FooIf<T extends BarIf> {
    public void doSomething(T t);
}
interface BarIf{}

performTheAction方法是通用的,換句話說,它適用於表示為類型參數T的未知類型。 可以使用未知類型調用此方法? extends BarIf main方法中所示? extends BarIf

但是,請記住,每個對類型X引用都意味着所引用的對象可能具有X的子類型,而不必擔心它。

您可以在此處簡單地使用基類BarIf ,而不管對象的實際BarIf子類型為:

BarIf bar = newRandomBarImpl();
FooIf<BarIf> foo=newFooBar(BarIf.class);
foo.doSomething(bar);

請注意,當您要使用接口中未指定的實際實現類型Foo方法時,必須將FooIfFoo 您可以將FooIf<BarIf>Foo<BarIf>而不發出警告,因為如果Foo<X> implements FooIf<X> ,則泛型類型轉換是正確的。

但是,它可能會在運行時失敗,因為不需要newFooBar方法來返回Foo實例而不是其他任何FooIf實現。 這就是為什么顯式類型轉換是唯一正確的解決方案的原因,因為它記錄了有關對象的實際運行時類型的假設。 所有其他嘗試將在某處生成至少一個編譯器警告。

暫無
暫無

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

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