簡體   English   中英

使用“原始類型”作為靜態字段/返回類型時,如何避免泛型警告?

[英]How to avoid generics warnings when using “raw types” as static field / return type?

從昨天開始,這基本上是對這個問題的追隨。 我試圖實現“最通用的方式”(我能想到)以構建“真正”的不可修改集合。 下面的代碼工作正常; 但它需要禁止顯示警告(“原始類型”和“未選中”)。

我嘗試了各種方法來避免這些警告。 但根本找不到其他選擇。 因此,我的問題是:是否有一種干凈的方法來避免我壓制的警告?

(我看到了另一個問題 ;但是我不確定100%是否確實適用於我的代碼;因為我不確定是否可以在不使用原始類型的情況下寫下“ Generator”接口)。

private interface Generator<T> {
    T generateNewInstance();
}

@SuppressWarnings("rawtypes")
private final static Generator ListGenerator = new Generator<List>() {
    @Override
    public List generateNewInstance() {
        return new ArrayList();
    }
};

public static <T> List<T> unmodifiableListBasedOnCloneOf(List<T> elements) {
    @SuppressWarnings("unchecked")
    List<T> newInstance = makeNewInstanceOf(elements.getClass(), ListGenerator);
    newInstance.addAll(elements);
    return Collections.unmodifiableList(newInstance);
}

private static <T> T makeNewInstanceOf(Class<T> incomingClass, Generator<T> fallbackGenerator) {
    try {
        return (T) incomingClass.newInstance();
    } catch (IllegalAccessException | InstantiationException e) {
        return fallbackGenerator.generateNewInstance();
    }
}

如果將List<T>的副本復制到新的ArrayList<T> ,並將該引用內聯傳遞給Collections.unmodifiableList ,則除了不可修改的裝飾器之外,沒有其他人可以訪問該副本以對其進行修改:

    List<String> original = new ArrayList<>(Arrays.asList("Hello", "World"));

    // This simply decorates original, so updates to original are
    // reflected in this list.
    List<String> unmodifiableDecorator = Collections.unmodifiableList(original);

    // The reference to the new ArrayList is scoped to the call to
    // Collections.unmodifiableList, so nothing else can have a
    // reference to it.
    List<String> unmodifiableCopy =
        Collections.unmodifiableList(new ArrayList<>(original));

    System.out.println("Before clear:");
    System.out.println(original);
    System.out.println(unmodifiableDecorator);
    System.out.println(unmodifiableCopy);

    original.clear();

    System.out.println("After clear:");
    System.out.println(original);
    System.out.println(unmodifiableDecorator);
    System.out.println(unmodifiableCopy);

輸出:

Before clear:
[Hello, World]
[Hello, World]
[Hello, World]
After clear:
[]
[]
[Hello, World]

因此,除非您可以以某種方式說服unmodifiableList向您提供委托引用,否則unmodifiableCopy不會被修改,也無法被修改。

由於您無法修改它,因此無需使副本與輸入列表具有相同的具體列表類型。 只需將其設置為ArrayList ,因為它具有使用List實現可以實現的最佳讀取性能。

因此,沒有警告或額外類的方法可以是:

public static <T> List<T> unmodifiableListBasedOnCloneOf(List<T> elements) {
  return Collections.unmodifiableList(new ArrayList<>(elements));
}

並非總是可以避免使用@SuppressWarnings注釋。 我嘗試將其范圍限制為局部變量。

我想出了這個:

private interface Generator<T> {

    T generateNewInstance();
}

private static class ListGenerator<T> implements Generator<List<T>> {
    @Override
    public List<T> generateNewInstance() {
        return new ArrayList<>();
    }
};

public static <T> List<T> unmodifiableListBasedOnCloneOf(List<T> elements) {
    @SuppressWarnings("unchecked")
    Class<List<T>> clazz = (Class<List<T>>)elements.getClass();
    List<T> newInstance = makeNewInstanceOf(clazz , new ListGenerator<T>());
    newInstance.addAll(elements);
    return Collections.unmodifiableList(newInstance);
}

private static <T> T makeNewInstanceOf(Class<T> incomingClass, Generator<T> fallbackGenerator) {
    try {
        return (T) incomingClass.newInstance();
    } catch (IllegalAccessException | InstantiationException e) {
        return fallbackGenerator.generateNewInstance();
    }
}

暫無
暫無

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

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