为什么 Java 类型擦除会更改目标集合的非泛型类型?



首先,我来自C#,但我知道Java中的类型擦除。 但我不明白下面的代码示例...

当我使用具体类型定义目标集合时,我希望该集合保留该类型。即使实际集合是泛型方法的结果。 因此,如果分配了不适当的集合,我希望会出现ClassCastException。但是没有发生异常,但目标集合的内部类型在运行时会发生变化...... 我后来迭代了这个集合,我在迭代期间得到了 类投射异常... 我做错了什么吗?还是这种奇怪的行为是正确的?

//There are 2 classes. Both implementing the same interface.
class CA implements IA
class CB implements IA

public void method1()
{
//This is the target-collection. The Type is set to CA(!)
//In Java, I expect an exception here! Why does Java change the type of
//collection? This is very dangerous ... because I have defined a 
//specific type. So I expect to get what I have defined.
Collection<CA> result = getInstances();
//Some Code...
//Time to iterate the instances
for(CA instance : result)
{
//ClassCastException at second instance...
}
}
public <T extends IA> Collection<T> getInstances()
{
//Resulting collection
Collection<T> instances = new LinkedList<T>();

for(int i = 0; i < 2; i++)
{
//In C#, an exception would occure exactly here.
//That would be sooo fine... :(
//I already wrote a solution for this. I use Class<T> to cast at
//this point. So thats not my question. I just want to understand
//why java is allowing to change the inner type of collection
T instance = (T)getInstance(i);
//Add the instance
instances.add(instance);
}
//At this point, the collection will containing CA and(!) CB instances...
return instances;
}
//Non-generic method!
public IA getInstance(int i)
{
if(i == 0)
return new CA();
else
return new CB();
}

你正在做一个未经检查的投射

T instance = (T)getInstance(i);

如果省略强制转换,则会出现编译时错误。如果您添加演员表,您会收到警告,但假设您知道自己在做什么。

在这种情况下,你">

不知道你在做什么",即通过做一个未经检查的投射,你说"用类型系统来见鬼!然后所有的赌注都关闭了,并且在编译时无法验证您正在做正确的事情。在运行时,您可能会收到异常。

GhostCat提到了类型检查集合。您不需要为它们实现自己的类,因为实用程序类包含用于创建检查集合的方法CollectionscheckedListcheckedSet等。它们包含用于检查内容是否属于正确类型的附加Class参数。使用它们会更早地在将元素放入集合中而不是检索它们时提供运行时异常。

当我使用具体类型定义目标集合时,我希望该集合保留该类型

错误的期望。Java中的泛型(几乎(是相关的"仅编译时"。

只有一个 ArrayList 类,它适用于类型Object的参数。添加"错误类型"时从编译器获得的错误如前所述:仅编译时。

当然,您可以创建自己的列表实现,该实现使用具体的Class实例进行实例化,然后在运行时执行相应的检查。并更新:您可以使用 Collection 类的帮助程序方法之一,例如 checkedCollection(( 来创建 collection/list/set/...这正是这样做的。

除此之外:

for(CA instance : result)
{
//ClassCastException at second instance...

在这里,您有一个显式强制转换,您声称:结果列表中的所有对象都将是CA对象,但显然,并非所有对象都是。

相关内容

  • 没有找到相关文章

最新更新