Compiler warning solution for generic varargs

The puzzle is from this blog . Similar to SO1445233 .

Given the following list of sources, explain why the compiler generates a warning when invoked by the list method and provides a solution to remove the warning without resorting to the @SuppressWarnings annotation.

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); } } 

Attention:

 Type safety: A generic array of Object&Serializable&Comparable<?> is created for a varargs parameter 
+4
source share
5 answers

Here are my thoughts.

 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
source

Change the body of the main list("1", 2, new BigDecimal("3.5")); in JavaLanguagePuzzle3.<Object>list("1", 2, new BigDecimal("3.5"));

Reason: syntax <> indicates which version of the generic method you want. But this must be addressed . to make the parser happy, and the class name before that for the same reason.

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

+3
source

I asked a question about this a while ago.
Problem: given the header of the <T extends List<?>> void foo(T... args) method, you can store non-T values ​​in the generated array (unsafe behavior). (For more details see my question below)
In Java 7, they added the @SafeVarargs annotation, which you can apply to your method to suppress this warning.

Simplified call to Varargs method in Java 7

+1
source

The message is that a mixture of types like args for list and the correct binding for a parameter of type T not obvious. One fix (not in the spirit of type safety) is to remove generics:

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

The error message is actually a little misleading. The problem here is not that the type argument is general, it is an intersection type. Only the element type of this intersection type can be confirmed as the type of the array component. Thus, storing objects in this array that implement some of the other types of intersection type elements will not result in an 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 } } 
0
source

Source: https://habr.com/ru/post/1382204/


All Articles