如何从列表转换<&燃气轮机;列出<;T>;在Java中使用泛型?
在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
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();
用于(对象项:非类型列表)
类型列表。添加((整数)项);
请注意,上面的代码不会生成任何类型安全警告,理想情况下,您的解决方案也不应该生成任何此类警告
如果listClass
具有公共默认构造函数,那么以下解决方案是否有效
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
是“untyped”输入列表,实际上与untypedList
相同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;
}});
}