簡體   English   中英

如何避免接口的通用編譯器警告

[英]How to avoid generic compiler warning for interface

以前可能已經以某種形式或其他形式提出這個問題,但我仍然無法解決它,所以我想我會在這里問集體智慧。 我有一個這樣的界面 - 我留下了一些評論,因為它們可能有所幫助。

/** Technical note: this generic binding is known as F-bound where class
 * T is 'the worked-on class' by Splittable i.e. the implementing class.
 */
interface Splittable <T extends Element & Splittable<T>> {


/** Returns an object of the same class which has been split off at
 * the point given.
 */ 
public T splitOff(double at);


/** Appends the object provided, which must be of the same class, to
 * this object.
 */
public void append(T el);
}

那么我正在研究一個我在編譯時不知道的元素:

if (el instanceof Splittable) {
    if (nextEl.getClass == el.getClass) {
        // same class so join them
        ((Splittable)el).append(nextEl);
    }
}

這就是我得到編譯器警告的地方 - 未選中調用append(T)作為原始類型Splittable的成員。

在Element子類中,我嘗試了兩種方法

SubClassEl extends Element implements Splittable

SubClassEl extends Element implements Splittable<SubClassEl>

警告沒有區別。

此外,在調用append()時,我試過了

((Splittable)el).splitOff(x).append(nextElement)

但編譯器無法識別splitOff應返回Splittable,只返回Element。

有任何想法嗎?

這里發生的是你正在使用原始類型,它“退出”泛型類型檢查。 當發生這種情況時, T刪除Element 來自Java教程

當使用多邊界時,邊界中提到的第一種類型用作類型變量的擦除。

至於如何在沒有警告的情況下編譯代碼,使用當前設計可能無法實現。 使用instanceof和強制轉換處理普通Element並不能很好地與Splittable聲明的遞歸綁定類型參數混合使用。

避免原始類型,我能得到的最接近的是:

static <T extends Element & Splittable<T>> void maybeAppend(T el1, Element el2) {
    if (el1.getClass() == el2.getClass()) {
        @SuppressWarnings("unchecked") // arguments' runtime types are equal
        final T el2WithNarrowedType = (T)el2;
        el1.append(el2WithNarrowedType);
    }
}

...

if (el instanceof Splittable<?>) {
    maybeAppend(el, nextEl); //compiler error
}

這仍然無法編譯,因為沒有類型參數,就無法表達el既是Element又是自己類型的Splittable

我在這里回答了類似的問題: 將運行時解析參數傳遞給具有多個綁定類型的編譯錯誤的方法 最接近我不能使用的原始類型的解決方案是一個主要的黑客,只適用於某些編譯器。 OP最終使用原始類型。

我給你的建議是避免自我鍵入,並考慮實現這樣的事情:

interface ElementSplitter<T extends Element> {

    T splitOff(T element, double at);

    void append(T element, T appendedElement);
}

如果實現的splitOffappend功能需要訪問給定Element派生的私有成員,則解決方法是使其成為嵌套類,例如:

class SubClassEl extends Element {

    ...

    static class Splitter implements ElementSplitter<SubClassEl> {
        ...
    }
}

我注意到您在Splittable javadoc中寫道:

技術說明:這種通用綁定稱為F-bound,其中T類是Splittable “工作類”,即實現類。

你應該知道Java不支持真正的自我輸入 - 你所擁有的是一個遞歸綁定的類型參數, 據說 ,但不一定是自我類型。 見我的答案在這里有關這種模式及其缺陷的更多細節。

暫無
暫無

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

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