簡體   English   中英

Java Generics和未選中的強制轉換

[英]Java Generics and unchecked cast

我正在努力解決Java中泛型的這個方面。 希望有人可以幫我看看方法。

我有一個包含對象列表的類。 這段代碼有效,但我想擺脫演員表。 我怎樣才能使這更通用?

public class Executor {
    List<BaseRequest<BaseObj>> mRequests = new ArrayList<BaseRequest<BaseObj>>();

    public Executor() {
    }

    @SuppressWarnings("unchecked")
    public <T extends BaseObj> void add(final BaseRequest<T> request) {
        mRequests.add((BaseRequest<BaseObj>) request);
    }

    public void execute() {
        for (BaseRequest<BaseObj> r : mRequests) {
            // DO SOMETHING WITH r
        }
    }
}

在發布的代碼片段中,您需要進行BaseRequest<? extends BaseObj>因為BaseRequest<? extends BaseObj> BaseRequest<? extends BaseObj>不是BaseRequest<BaseObj>的子類型,並且由於類型擦除而無法在運行時檢查BaseRequest<BaseObj> ,這就是編譯器警告您的原因。 但是如果你改變了mRequests的聲明:

public class Executor  {

    List<BaseRequest<? extends BaseObj>> mRequests = new ArrayList<>();

    public Executor() {
    }

    public <T extends BaseObj> void add(final BaseRequest<T> request) {
        mRequests.add(request);
    }

    public void execute() {
        for (BaseRequest<? extends BaseObj> r : mRequests) {
            // DO SOMETHING WITH r
        }
    }
}

class BaseRequest<T> {}

class BaseObj {}

讓我們一步一步解決問題。 你希望能夠打電話

req.add(new BaseRequest<ExtObj1>());
req.add(new BaseRequest<ExtObj2>());
req.add(new BaseRequest<ExtObj3>());

其中ExtObj[1|2|3] extends BaseObj 給定List接口:

List<T> {
  void add(T el);
}

我們需要為BaseRequest<ExtObj1>BaseRequest<ExtObj2>BaseRequest<ExtObj3>找到一個公共超類型。 一個超類型是BaseRequest<?> ,另一個是BaseRequest<? extends BaseObj> BaseRequest<? extends BaseObj> 我選擇了第二個,因為它是最可能限制的。 你應該知道,在Java中BaseRequest<ExtObj1>不是一個亞型BaseRequest<BaseObj>因為泛型是不變的。

現在我們有了mRequests的正確聲明,找到Executor.add()的API非常簡單。 順便說一句,如果你需要的方法體非常簡單,你甚至不需要type參數:

public void add(BaseRequest<? extends BaseObj> request) {
  mRequests.add(request);
}

警告不是錯誤。 有警告,所以你檢查是否有錯誤,因為它可能不會被自動檢查。 您應該檢查它,然后使用注釋注意已經檢查過警告。

在你的情況下,它警告BaseRequest<T>不等於BaseRequest<BaseObj>

例:

public class NumberWrapper<N extends Number> {
    private N value;
    public void setValue(N value) {
        this.value = value;
    }
}

public class MainClazz {
    private NumberWrapper<Integer> wrappedNumber = new NumberWrapper<Integer>();
    public void run() {
        Number n = externalSource.getNumber();
        wrappedNumber.setValue(n); // <-- Error. What if getNumber returns a double?
    }
}

您可以出現此錯誤,而不是取決於您完成/集成所顯示代碼的方式。

暫無
暫無

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

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