为什么以下代码不会引发异常?
import java.util.ArrayList;
import java.util.List;
@SuppressWarnings("unchecked")
public class MainRunner {
public static void main(String[] args) {
List<String> s = new ArrayList<String>() {
{
add("a");
add("1");
add("1");
}
};
// List<Integer> i = (List<Integer>) listConvertor(s, new Integer("1"));
List<Integer> i = (List<Integer>) listConvertor(s, Integer.class);
System.out.println(i);
}
@SuppressWarnings("unchecked")
public static <T, P> List<?> listConvertor(List<T> inputList, P outputClass) {
List<P> outputList = new ArrayList<P>(inputList.size());
for (T t : inputList) {
outputList.add((P) t); // shouldn't be classCastException here?
}
return outputList;
}
}
我想返回List<P>
而不是List<?>
。但是当我写List<P>
时,它意味着List<Class<P>>
。即在上述情况下,它表示List<Class<Integer>>
,但我希望List<Integer>
作为回报。
我想要下面的代码:(这样我不必在方法返回时再次强制转换)
List<Integer> i = listConvertor(s, Integer.class);
System.out.println(i);
}
@SuppressWarnings("unchecked")
public static <T, P> List<P> listConvertor(List<T> inputList, P outputClass) {
List<P> outputList = new ArrayList<P>(inputList.size());
for (T t : inputList) {
outputList.add((P) t); // shouldn't be classCastException here?
}
return outputList;
}
}
答案 0 :(得分:1)
public static <T, P> List<P> listConvertor(List<T> inputList, Class<P> outputClass) {
记住,您传递的是Class对象,而不是整数对象。
答案 1 :(得分:1)
不,当然它不会引发异常。泛型用于编译时检查,而不是运行时。在运行时,所有列表都是List<Object>
,并且由JVM隐式地进行转换。
修改:在您的代码中
for (T t : inputList) {
outputList.add((P) t); // shouldn't be classCastException here?
}
实际编译为
for (Object t : inputList) {
outputList.add((Object) t); // shouldn't be classCastException here? -- no
}
例如,使用您的代码,如果您执行i.get(0).getClass()
,则然后会获得ClassCastException
,因为该项目无法从String
转换为{{} 1}}(注意:同样适用于您,因为您无法隐式地将Integer.class
投射到String
。期间。)
如果您真的想要这样做,请将Integer
强制转换为T
(例如,将字符串转换为数字值),然后我建议您使用其他模式。例如:
P
您需要做的就是将static interface ClassConverter<F,T> {
public T convert(F o);
}
static class StringToIntConverter implements ClassConverter<String,Integer> {
public Integer convert(String o) {
try {
return Integer.parseInt(o);
} catch (NumberFormatException e) {
return 0;
}
}
}
public static void main(String[] args) {
List<String> s = new ArrayList<String>() {
{
add("a");
add("1");
add("1");
}
};
// List<Integer> i = (List<Integer>) listConvertor(s, new Integer("1"));
List<Integer> i = (List<Integer>) listConvertor(s, new StringToIntConverter());
System.out.println(i);
System.out.println(i.get(0).getClass().getName());
}
public static <T, P> List<P> listConvertor(List<T> inputList, ClassConverter<T, P> c) {
List<P> outputList = new ArrayList<P>(inputList.size());
for (T t : inputList) {
outputList.add(c.convert(t)); // cast handled by the class method == safer
}
return outputList;
}
接口实现为您希望将ClassConverter
转换为T
并将其传递给P
方法的任何类型。
答案 2 :(得分:1)
这应该可以轻而易举地完成工作:
public static <T, P> List<P> listConvertor(List<T> inputList, Class<P> outputClass) {
List<P> outputList = new ArrayList<P>(inputList.size());
for (T t : inputList) {
if( !outputClass.isInstance(t) )
throw new ClassCastException("Faked CCException");
@SuppressWarnings("unchecked")
P p = (P) t;
outputList.add(p);
}
return outputList;
}
答案 3 :(得分:0)
与@ A.H.的答案相同,但使用Class.cast()
进行了大量简化,并且还摆脱了不必要的T
:
public static <P> List<P> listConvertor(List<?> inputList, Class<P> outputClass) {
List<P> outputList = new ArrayList<P>(inputList.size());
for (Object t : inputList) {
P p = outputClass.cast(t);
outputList.add(p);
}
return outputList;
}