Warning: file_get_contents(/data/phpspider/zhask/data//catemap/5/url/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
如何从列表转换<&燃气轮机;列出<;T>;在Java中使用泛型?_Java_Generics_List_Covariance - Fatal编程技术网

如何从列表转换<&燃气轮机;列出<;T>;在Java中使用泛型?

如何从列表转换<&燃气轮机;列出<;T>;在Java中使用泛型?,java,generics,list,covariance,Java,Generics,List,Covariance,在Java中,如何使用通用方法将List转换为List,以便用单个方法调用替换如下模式: List untypedList = new ArrayList(); // or returned from a legacy method List<Integer> typedList = new ArrayList<Integer>(); for (Object item: untypedList) typedList.add((Integer)item); Li

在Java中,如何使用通用方法将
List
转换为
List
,以便用单个方法调用替换如下模式:

List untypedList = new ArrayList();  // or returned from a legacy method
List<Integer> typedList = new ArrayList<Integer>();
for (Object item: untypedList)
    typedList.add((Integer)item);
List untypedList=new ArrayList();//或者从遗留方法返回
列表类型列表=新的ArrayList();
用于(对象项:非类型列表)
类型列表。添加((整数)项);
请注意,上面的代码不会生成任何类型安全警告,理想情况下,您的解决方案也不应该生成任何此类警告

如果list
Class
具有公共默认构造函数,那么以下解决方案是否有效

public class ListUtil {
    public static <T, L extends List<T>> L typedList(List<?> untypedList, Class<T> itemClass, Class<L> listClass) {
        L list = null;
        try {
            list = listClass.newInstance();
        } catch (InstantiationException e) {
        } catch (IllegalAccessException e) {
        }
        for (Object item: untypedList)
            list.add(itemClass.cast(item));
        return list;
    }
}
公共类ListUtil{
公共静态L类型列表(列表非类型列表、类itemClass、类listClass){
L list=null;
试一试{
list=listClass.newInstance();
}捕获(实例化异常e){
}捕获(非法访问例外e){
}
用于(对象项:非类型列表)
list.add(itemClass.cast(item));
退货清单;
}
}
(请注意,
listClass.newInstance()
抛出
InstantiationException
IllegalAccessException
,如果
Class
的实例没有公共默认构造函数。如果该方法没有正确处理这些异常,可能会出现什么问题?)

注:

  • T
    是结果列表中每个项目的类型
  • L
    是我希望创建的列表类型(扩展了
    list
  • untypedList
    是“untyped”输入列表,实际上与
    list
    相同
  • itemClass
    表示
    T
    的运行时类
  • listClass
    表示
    L
    的运行时类

    • 您有运行时问题,因此它应该独立于泛型。在运行时,每一个“都是一个对象”。如果不能实例化
      listClass
      ,那么实际上传递的是
      java.util.List
      的一个实现,它不提供(公共)空构造函数

      因此,您的问题的解决方案超出了此方法。把它叫做

       List<String> result = typedList(untypedList, String.class, ArrayList.class);
      
      List result=typedList(untypedList、String.class、ArrayList.class);
      
      不应给出运行时错误


      现在我手头有月食。下面的代码编译并没有警告,应该满足您的要求:从非类型化列表转换为类型化列表

      public static <T> List<T> typedList(List<?> untypedList, Class<T> itemClass) {
        List<T> list = new ArrayList<T>();
        for (Object item : untypedList) {
          list.add(itemClass.cast(item));  // TODO - handle ClassCastExpception
        }
        return list;
      }
      
      公共静态列表类型列表(列表非类型列表,类itemClass){
      列表=新的ArrayList();
      用于(对象项:非类型列表){
      list.add(itemClass.cast(item));//TODO-handleClassCastExpection
      }
      退货清单;
      }
      
      我不相信你想做的是可能的。这是因为泛型工作:

      在编译时,检查类型化列表的所有输入类型,并将所有输出对象强制转换为列表的类型——从那时起,我们将讨论非类型化的“列表”。不幸的是,泛型只是语法上的糖。

      该方法抛出两个选中的异常
      IllegalAccessException
      InstantiationException
      。这些必须在方法的方法签名中捕获或声明

      作为记录,这些异常在各种情况下抛出;e、 g

      • 该类不定义参数构造函数
      • 构造函数不可见
      • 该类是抽象的或接口
      • class对象表示数组类型、基元类型或void“type”
      这实际上与方法是泛型的这一事实以及相关的类型问题无关。

      我将使用及其方法以及
      列表中的工厂方法,如下所示:

      List<?> original = ...;
      List<String> typed = Lists.newArrayList(
         Iterables.filter(original, String.class));
      
      List original=。。。;
      List typed=Lists.newArrayList(
      filter(原始,String.class));
      

      这将实际检查原始列表中的每个对象,结果列表将仅包含作为给定类型(
      String,在本例中为
      )或其子类型的实例的元素。我真的不认为让用户为生成的
      列表
      类型提供
      ,并尝试通过反射实例化它是有意义的。

      您想要实现什么?此类代码:

      List l = new ArrayList();
      l.add(new Integer(1));
      List<Integer> li = l;
      
      listl=newarraylist();
      l、 加(新整数(1));
      列表li=l;
      

      只是工作而已。它会产生警告,但有效。但是,在
      li
      中,可能会有一些对象不是
      Integer
      的实例。如果您想确定,请使用google guava,就像ColinD回答的那样。

      与其传入要实例化的列表类型,不如传入要填充的空集合?这为api的用户提供了更大的灵活性,因为使用默认构造函数并不总是理想的。(例如,可能我想要一个集合,其中我提供了预期的元素数量,或者我想要一个排序列表,其中我提供了比较器)

      另外,作为补充说明,您应该始终使用最通用的接口编程。在这种情况下,您的输入只需要一个Iterable,而您的输出只需要一个集合

      考虑到这一点,我会这样写这个方法--

      公共静态C类型安全添加(可从、C到、类listClass){
      用于(对象项:来自){
      to.add(listClass.cast(item));
      }
      返回;
      }
      然后调用代码如下所示:
        public static void main(String[] args) {
          List<?> untypedStringList = LegacyApi.getStringList();
          List<String> typesafeStringList = typesafeAdd(untypedStringList, new ArrayList<String>(), String.class);
        }
      
      publicstaticvoidmain(字符串[]args){
      List untypedStringList=LegacyApi.getStringList();
      List typesafeStringList=typesafeAdd(untypedStringList,new ArrayList(),String.class);
      }

      这里有2条评论:

      • 如果您真的可以信任LegacyApi(或任何提供给您的非类型化列表)只向您返回一个包含预期类型的集合,那么您只需执行一个未经检查的c
          public static void main(String[] args) {
            List<?> untypedStringList = LegacyApi.getStringList();
            List<String> typesafeStringList = typesafeAdd(untypedStringList, new ArrayList<String>(), String.class);
          }
        
        public static <D, S> transform(
            List<D> dst,
            List<S> src,
            Transformer<? extends D, ? super S> transformer
        ) { ... }
        
            private static <T> List<T> typeList(List<?> l, Class<T> klass) {
                List<T> list = new ArrayList<T>();
                for(Object obj : l) {
                    if (klass.isAssignableFrom(obj.getClass())) {
                        list.add((T) obj);
                    }
                }
                return list;
            }
        
        public List<L> convert(List<T> list) {
            return Lists.transform(list,new Function<T,L>() {
        
                public Object apply(T from) {
        
                    L magic = (L)from;
        
                    /* magic here */
        
                    return magic;
                }});
        }