Java 泛型 SuppressWarnings ("unchecked") 之谜

标签 java generics java-7 suppress-warnings unchecked

为什么替代代码 (1) 编译时没有警告,而替代代码 (2) 产生“未经检查的转换”警告?

两者的共同点:

class Foo<T> {
    Foo( T [] arg ) {
    }
}

备选方案 (1):

class Bar<T> extends Foo<T> {
    protected static final Object [] EMPTY_ARRAY = {};

    @SuppressWarnings("unchecked")
    Bar() {
         super( (T []) EMPTY_ARRAY );
    }
}

备选方案 (2):

class Bar<T> extends Foo<T> {
    @SuppressWarnings("unchecked")
    Bar() {
         super( (T []) EMPTY_ARRAY );
    }

    protected static final Object [] EMPTY_ARRAY = {};
}

备选方案 (2) 产生:

javac -Xlint:unchecked Foo.java Bar.java 
Bar.java:4: warning: [unchecked] unchecked cast
             super( (T []) EMPTY_ARRAY );
                           ^
  required: T[]
  found:    Object[]
  where T is a type-variable:
    T extends Object declared in class Bar
1 warning

这是:

java version "1.7.0_07"
Java(TM) SE Runtime Environment (build 1.7.0_07-b10)
Java HotSpot(TM) 64-Bit Server VM (build 23.3-b01, mixed mode)

最佳答案

我无法在 JLS 中找到任何内容,包括 @SuppressWarnings ( JLS 9.6.3.5 ) 和未经检查的警告 ( JLS 5.1.9 ) 部分似乎没有任何可能导致此问题的问题。我的猜测(没有亲自测试您的 SSCE)是您在编译器中发现了一个错误。我推荐 filing a bug report with Oracle并将报告链接添加到您的问题。

简而言之,类中成员的顺序应该完全独立于警告的处理方式。它可能只是未经检查的警告代码中的边缘情况,也可能是更大的问题。

与此同时,您可以通过做您一开始就应该做的事情来消除所有问题,并动态生成空数组而不是强制转换现有数组,如 this question 中所述。 .

编辑

I don't see how the linked proposal would work in case of my EMPTY_ARRAY that is a static final.

不要成功static final再提供一个Class<T>在你的构造函数中:

@SuppressWarnings("unchecked") // Still need this
public Bar(Class<T> clazz) {
    super((T[]) Array.newInstance(clazz, 0));
}

Java 几乎从不使用 final 的值除死代码外的警告变量。否则,您会遇到这样的边缘情况:

class Bar<T> extends Foo<T> {
    // Is it really empty?
    protected static final Object [] EMPTY_ARRAY = SomeOtherClass.getEmptyArray();

    @SuppressWarnings("unchecked")
    Bar() {
         super( (T []) EMPTY_ARRAY );
    }
}

他们必须将该逻辑写入编译器。对于像“空数组”这样的边缘情况,这是不必要的复杂化,此外,像这样的转换最终都是代码味道。

除了这个答案之外,您可能还有另一个选择是使用 var args。 Foo :

class Foo<T> {
    Foo( T ... arg ) {
    }
}

Bar :

class Bar<T> extends Foo<T> {

    Bar() {
         super();
    }
}

这应该有效,并且它消除了所有转换、空数组、警告等。查看有关 var args 及其可能调用的更多信息 here .

关于Java 泛型 SuppressWarnings ("unchecked") 之谜,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/13829753/

相关文章:

C# 使用 Convert.ChangeType() 的错误转换

Java 表达式

java - 如何避免Google App Engine不支持Runtime.addShutdownHook

java - 如何创建实例

java - 将 setText 设置为 EditText 时出现 NullPointerException - onDateSet

java - spring事务超时不起作用

java - 将方法转换为具有多种数据类型的泛型

java - 在java中创建DIV

Scala 泛型 < : and multiple traits

operating-system - Windows 2000 上的 Java 7