通用变量的编译器警告解决方案

时间:2011-11-21 01:45:28

标签: java generics variadic-functions

这个blog的谜题。与SO1445233类似。

给出以下源列表,解释为什么编译器在调用list方法时产生警告,并提供解除警告的解决方案而不诉诸@SuppressWarnings注释。

public class JavaLanguagePuzzle3 {
  public static void main(String[] args) {
    list("1", 2, new BigDecimal("3.5"));
  }  
  private static <T> List<T> list(T... items) {
    return Arrays.asList(items);
  }
}

警告:

Type safety: A generic array of Object&Serializable&Comparable<?> is created for a varargs parameter

5 个答案:

答案 0 :(得分:3)

改变主体 list("1", 2, new BigDecimal("3.5"));JavaLanguagePuzzle3.<Object>list("1", 2, new BigDecimal("3.5"));

原因:<>语法指定所需的通用方法版本。但是,你需要在它前面放置.以使解析器满意,并且出于同样的原因,在此之前使用类名称。

来源: http://codeidol.com/java/javagenerics/Introduction/Generic-Methods-and-Varargs/

答案 1 :(得分:2)

这是我的想法。

public static interface Foo extends Serializable, Comparable<Object> {
}

public static void main(String[] args) {
  // Problem: Unsafe: varargs has generic type
  implicitList("1", 2, BigDecimal.valueOf(3.5)); // warning: generic vararg

  // Solution 1: Constrain type of varags explicitly through generics
  explicitList1(Object.class, "1", 2, BigDecimal.valueOf(3.5));
  // However, we could still have the same error from problem
  explicitList1(Foo.class, "1", 2, BigDecimal.valueOf(3.5)); // warning: generic vararg
  // Fix: Make containing class to exact type (PECS) an array is both producer and consumer
  explicitList2(Foo.class, "1", 2, BigDecimal.valueOf(3.5)); // error: incompatible args

  // Solution 2: Override varargs by passing array
  implicitList(new Object[] { "1", 2, BigDecimal.valueOf(3.5) });
}

private static <T> List<T> explicitList1(Class<? extends T> klass, T... items) {
  return Arrays.asList(items);
}

private static <T> List<T> explicitList2(Class<T> klass, T... items) {
  return Arrays.asList(items);
}

private static <T> List<T> implicitList(T... items) {
  return Arrays.asList(items);
}

答案 2 :(得分:1)

我刚才问了一个问题。
问题:给定方法头<T extends List<?>> void foo(T... args)您可以在生成的数组中存储非T值(不安全行为)。 (有关详细信息,请参阅下面的问题)
解决方案:在Java 7中,他们添加了一个@SafeVarargs注释,您可以将其放在方法上以抑制该警告。

Simplified Varargs Method Invocation in Java 7

答案 3 :(得分:0)

消息是因为list的args类型混合在一起,而且类型参数T的正确绑定并不明显。一个修复(不是类型安全的精神)是删除泛型:

private static List<Object> list(Object... items) {
    return Arrays.asList(items);
}

答案 4 :(得分:0)

错误消息实际上有点误导。这里的问题不是type参数是通用的,而是它是一个交集类型。只能将该交集类型的一种元素类型作为数组的组件类型。因此,将对象存储到那个实现交集类型的其他元素类型的数组中将不会引发ArrayStoreException

public class Example {
    interface A {}
    interface B {}
    interface C {}

    static class X implements A, B {}
    static class Y implements A, B, C {}

    public static void main(String[] args) {
        // inferred type: A&B, erased down to A resulting in a A[]
        bar(new X(), new Y());
    }

    static <T> void bar(T... ts) {
        Object[] os = ts;
        os[0] = new A() {}; // should fail, does not => warning
        os[0] = new B() {}; // fails as expected
    }
}