簡體   English   中英

帶有擦除的Java類型推斷

[英]Java type inference with erasure

在擦除和類型推斷方面遇到一些問題。 我有以下的類層次結構,看起來並不十分復雜:

public class Foo<T> {

}

public class Bar<T> {
    private final Class<T> clazz;

    public Bar(Class<T> clazz) {
        this.clazz = clazz;
    }
}

我想做的是這樣的:

Bar<Foo<?>> bar = new Bar<>(Foo.class);

這當然是行不通的,因為Foo並不是Foo<?> 問題是如何建立這樣的酒吧? 我確實需要Bar<Foo<?>> ,而不是Bar<Foo> ,因為有些方法只接受Bar<Foo<?>>作為參數。 欣賞想法。

抱歉,沒有這樣的Class對象,因為正如您所指出的,擦除意味着不可能。 您需要強制轉換:

((Class<Foo<?>>)(Class)Foo.class)

這將為您提供所需的界限,但可能會產生編譯器警告,因為您正在執行未經檢查的泛型轉換。 這是合理的:編譯器要求您確認您遺漏了泛型的編譯時安全性。 但是在這種情況下,實際上在這種情況下,無論是在您的程序中還是在將來,這種情況都不會產生運行時錯誤,所以很好。

雙播是必要的,因為編譯器知道Foo.class與Class>不兼容,因此您必須首先將其轉換為“原始”類型Class:在表達式中使用原始類型會禁用編譯器的泛型檢查這樣的表達方式,那么“不可能”的轉換就可以了。

如問題帖所示,如果不在<>提供類型信息,就無法創建通用對象。 您必須提供Type或使用原始版本。 如果您被迫使用通配符參數類型,則只需使用原始類型抑制警告,如下所示

@SuppressWarnings("rawtypes")
Bar<Foo<?>> bar = new Bar(Foo.class);       

//Bar is having no type "<>" (but this is not recommended

由於java.lang.Class是不可變的,因此可以在Bar的構造函數中使用較弱的類型聲明:

class Foo<T> {}

class Bar<T> {
    private final Class<? extends T> clazz;

    public Bar(Class<? extends T> clazz) {
        this.clazz = clazz;
    }
}

如果您仍然需要該字段的類型為Class<T>而不是Class<? extends T> Class<? extends T> ,將其強制轉換為構造函數是安全的。

暫無
暫無

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

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