6

我终于开始尝试摆脱 Java 7 友好生成的所有那些新的编译器警告。我这两个离开了我无法理解的。有什么方法可以在不压制它们的情况下摆脱它们?

构造一个泛型对象数组(我可以在哪里放置一个数组创建?):

  static final int N = 10;
//warning: [unchecked] unchecked conversion
  static final Set<Widget>[] queued = new ConcurrentSkipListSet[N];
//required: Set<Widget>[]
//found:    ConcurrentSkipListSet[]

通用可变参数(似乎几乎在我接受通用类型可变参数的所有地方都会发生):

class Foo<T> {
//warning: [unchecked] Possible heap pollution from parameterized vararg type T
  public void add(T... entries) {
//where T is a type-variable:
//T extends Object declared in class Foo

顺便说一句:我已经有:

  // Add many entries to the list.
  public void add(List<T> entries) {
    // ...
  }

  // Add a number of entries.
  public void add(T... entries) {
    // Make a list of them.
    add(Arrays.<T>asList(entries));
  }
4

4 回答 4

7

对于第一个:

static final Set<Widget>[] queued = new ConcurrentSkipListSet<>[N];

在 Java 7 之前,它必须是:

static final Set<Widget>[] queued = new ConcurrentSkipListSet<Widget>[N];

但是,您最好将其声明为ArrayList<Set<Widget>>. 通常,在 Java 中混合数组和泛型有点困难。

static final List<Set<Widget>> queued = new ArrayList<>();
// or new ArrayList<Set<Widget>>();

关于第二个,请参阅此线程。尽管您可以隐藏该消息,但它实际上是在警告真正的危险。该线程的底线是安全的做法是将您的方法签名(和相应的调用)更改为:

class Foo<T> {
    public void add(List<T> entries) {
        . . .

这个问题与第一个问题基本相同:您不应该创建泛型数组。

于 2013-03-21T16:05:48.273 回答
2

要解决第二个问题,您需要添加@SafeVarargs到方法声明中。

javadocs,这是:

程序员断言带注释的方法或构造函数的主体不会对其 varargs 参数执行潜在的不安全操作。将此注释应用于方法或构造函数会抑制有关不可具体化变量 arity (vararg) 类型的未经检查的警告,并抑制有关在调用站点创建参数化数组的未经检查的警告。

于 2013-03-21T16:10:44.287 回答
1

通用数组创建:

static final ConcurrentSkipListSet<Widget>[] queued = newArray(N);
// note: declare the most specific type for private objects


@SafeVarargs
static <E> E[] newArray(int length, E... array)
{
    return Arrays.copyOf(array, length);
}

它是如何工作的 - 因为newArray是一个可变参数方法,E[] array所以必须传入一个参数,因此方法体可以访问E[]. 这在理论上是正确的,如果没有擦除,它将在运行时完全是类型安全的。通过擦除,我们只E[]在运行时擦除了 的类型,这很好,我们也返回相同的擦除类型。

于 2013-03-21T17:52:17.943 回答