2010-09-24 106 views
2

尽管我可以从更复杂的类结构中简化该代码,在真正的代码中,我使用了这里使用的整数和双精度类型的子类型。使用Java泛型,类型参数和返回列表未经检查的转换警告

我正在尝试将Java泛型与类型参数一起使用。如果用户请求Number.class的类型,我们希望将List<Integer>列表和List<Double>列表组合到一个列表中。

虽然代码有效,但我无法驾驭未经检查的转换警告(请参阅TODO标记)。该警告是:

Type safety: Unchecked cast from List<Integer> to Collection<? extends T> 

但是,如果我删除了演员,我得到一个编译错误:

The method addAll(Collection<? extends T>) in the type List<T> is not applicable for the arguments (List<Integer>). 

我的代码:

import java.util.ArrayList; 
import java.util.Arrays; 
import java.util.Collection; 
import java.util.List; 

public class Generics1 { 

    static final List<Integer> intList = new ArrayList<Integer>(Arrays.asList(
     1, 2, 3, 4)); 
    static final List<Double> dblList = new ArrayList<Double>(Arrays.asList(
     1.1, 2.2, 3.3)); 

    public static <T extends Number> List<T> getObjects(Class<T> type) { 
     List<T> outList = new ArrayList<T>(); 
     if (type == Number.class) { 
      // user asked for everything 
      // TODO: unchecked cast warnings here should be fixed 
      outList.addAll((Collection<? extends T>) intList); 
      outList.addAll((Collection<? extends T>) dblList); 
     } else { 
      // user asked for subtype of number 
      if (Integer.class.isAssignableFrom(type)) for (Integer i : intList) 
       if (type.isInstance(i)) { 
        T obj = type.cast(i); 
        outList.add(obj); 
       } 
      if (Double.class.isAssignableFrom(type)) for (Double d : dblList) 
       if (type.isInstance(d)) { 
        T obj = type.cast(d); 
        outList.add(obj); 
       } 
     } 
     return outList; 
    } 

    public static void main(String[] args) { 
     System.out.println("HI!"); 
     System.out.println("integers: " + getObjects(Integer.class)); 
     System.out.println("doubles: " + getObjects(Double.class)); 
     System.out.println("numbers: " + getObjects(Number.class)); 
    } 
} 
+0

是SuppressWarnings( “未登记”),够吗? – ninjalj 2010-09-24 19:00:24

+0

我忘了提及,我编辑了这篇文章,将代码块中的泛型放置在错误消息中,以便您可以看到正在使用的泛型类型。 – Powerlord 2010-09-24 20:04:10

+0

感谢您编辑帖子。 – 2010-09-25 02:05:11

回答

0

(删除前面的答案)

这里与番石榴这样做的方式:

@SuppressWarnings("unchecked") 
public static <T> List<T> filterAndCollapse(final Class<T> type, 
     Collection<?> a, Collection<?> b) { 
    List combined = new ArrayList(); 
    Predicate<Object> filter = new Predicate<Object>() { 

     public boolean apply(Object obj) { 
      return type.isInstance(obj); 
     } 
    }; 
    combined.addAll(Collections2.filter(a, filter)); 
    combined.addAll(Collections2.filter(b, filter)); 
    return combined; 
} 
// ... 
filter(Number.class, intList, dblList); 

编辑:比较完全型安全的方式。

public static <T> List<T> filterAndCollapse(final Class<T> type, 
     Collection<?> a, Collection<?> b) { 
    List<T> combined = new ArrayList<T>(); 
    Predicate<Object> filter = new Predicate<Object>() { 

     public boolean apply(Object obj) { 
      return type.isInstance(obj); 
     } 
    }; 
    Function<Object, T> transform = new Function<Object, T>() { 

     public T apply(Object obj) { 
      return type.cast(obj); 
     } 
    }; 
    combined.addAll(Collections2.transform(Collections2.filter(a, filter), 
     transform)); 
    combined.addAll(Collections2.transform(Collections2.filter(b, filter), 
     transform)); 
    return combined; 
} 

不幸的是,根据我的了解,没有办法用番石榴过滤和转换。

+0

不使用泛型? List combined = new ArrayList(); – nanda 2010-09-24 19:32:13

+0

@nanda:是的,原因是因为过滤器不会将项目投射到正确的类型。你可以做到这一点,但它需要一个额外的转换,这是运行时开销,因为这只是一个本地原始类型。我会加入另一个来比较。 – 2010-09-24 19:36:48

0
(Class<T> type) 
    List<T> outList = new ArrayList<T>(); 

    if (type == Number.class) { 
     // obviously, T==Number here, though the compiler doesn't know that 
     // so we do the cast. compiler will still warn. since the cast makes 
     // perfect sense and is obviously correct, we are ok with it. 
     List<Number> numList = (List<Number>)outList; 
     numList.addAll(intList); 
     numList.addAll(dblList); 
    } else { 

更好的解决方案,只需

for list in lists 
    for item in list 
    if item instance of type 
     add item to result 
+0

是的,我真的可以使用add(),因为addAll()是我得到编译器警告的地方。如果没有更好的建议来说明如何使用addAll()来禁止警告,那么我会重构代码以支持add()。 – 2010-09-25 02:03:46

相关问题