任何人都可以解释为什么以下代码编译?
List<Long> longNums = new ArrayList(Arrays.asList("one", "two", "three"));
是否由于类型擦除?
如果我有以下方法:
public <T> T readProperty(String propName, Class<T> type);
如何确保它会返回,比如说List<Long>
而不是List<String>
?显然,在调用方法的类型中,我只能提供List.class
并祈祷。
//run and pray
List<Long> longNums = readProperty("prop", List.class);
我已经想到这样一个方法错误地将一个String对象列表分配给一个长号列表,直到我运行它,我才看到ClassCastException
<。 / p>
答案 0 :(得分:9)
您不应该期望程序正常运行,因为您没有正确使用泛型。
首先,你不应该将Generics与Raws混合,这意味着这个陈述
List<Long> longNums = new ArrayList(Arrays.asList("one", "two", "three"));
无效(就正确性而言)。如果是:
List<Long> longNums = new ArrayList<Long>(Arrays.asList("one", "two", "three"));
它甚至不会编译,你会在编译时得到错误(不是在运行时,这可能会更令人困惑和可怕)。
因此,为了编译,您的列表应定义为:
List<String> longNums = new ArrayList<>(Arrays.asList("one", "two", "three"));
此外,关于本声明
//run and pray
List<Long> longNums = readProperty("prop", List.class);
实际上无法确保readProperty
将返回List<Long>
,因此您必须执行强制转换或添加@SuppressWarnings
注释。原因是编译器的类型擦除功能 - 参数化类型Long
被删除,它在运行时消失了(实际执行readProperty()
时prob
的值是通过反思获得。
答案 1 :(得分:1)
你错过了钻石<>
(这不会编译):
List<Long> longNums = new ArrayList<>(Arrays.asList("one", "two","three"));
答案 2 :(得分:1)
这是两个不同的问题。
pom.xml
出于源兼容性原因,在这些情况下允许raw type。你不应该依赖这个,因为正如你所看到的,它打败了泛型的整个想法。
至于第二个问题,你可以通过这样的方式来回避这个问题:
<packaging>war</packaging>
它更像是一种解决方法,而不是解决方案,并不总是适用。 (例如,当您需要更复杂的返回类型时,例如List<Long> longNums = new ArrayList(Arrays.asList("one", "two", "three"));
)
答案 3 :(得分:0)
如果将List定义为ArrayList
,则java不知道其中包含哪种对象。您可以将其分配给ArrayList<Long>
,但在项目上调用方法或属性时会出现错误,因为类型不匹配。
答案 4 :(得分:0)
通用类:
public abstract class GenericClass<T> {
private T managedClass;
public List<T> readListProp(String propName,T object){
//do stuff using T type instead of Long,String,Double,etc
}
Other classes:
public class FirstClass extends GenericClass<String>
{...
//you have a class where T from generic is replaced with String
}
public class SecClass extends GenericClass<Double>
{...
//you have a class where T from generic is replaced with Double
}