我有一些对象的列表
List<MyObject>
但我知道它是从MyObject继承的某个对象的列表
List<ChildObject>
尝试从一个投射到另一个给我一个“Unconvertible Types”警告。但是,如果我首先转换为object然后转换为转换为第二种类型的列表,那么警告就会消失
List<ChildObject> myChildList = (List<ChildObject>) (Object) myObjectList
这似乎工作正常。我有什么理由不这样做吗?它会抛出一个错误,有更好的方法还是被认为是不好的做法?
答案 0 :(得分:3)
现在返回List<? extends MyObject>
返回List<MyObject>
的地方。这将提供避免类型转换
答案 1 :(得分:3)
我有什么理由不这样做吗?
列表中的通用类型参数可以帮助编译器在编译时为您进行类型检查。施放抛弃了这张支票,将支票移动到运行时间。
会抛出错误吗?
是的,如果列表包含ChildObject
以外的对象,则可以。最糟糕的是,演员阵容可能会在一些完全不相关的地方失败,你的代码根本没有演员阵容。
例如,如果你这样做
// Do the hack;
List<ChildObject> myChildList = (List<ChildObject>) (Object) myObjectList;
...
// Iterate over your list
for (ChildObject c : myChildList) {
...
}
在上面的示例中,如果myObjectList
有一些除ChildObject
以外的类,则在运行时会出现类强制转换异常。但是,它会发生在for
循环的标题中,而不是在你的演员阵容中。
有更好的方法,还是被认为是不好的做法?
更好的方法是创建一个ChildObject
的集合,并用原始数组的内容填充它。
答案 2 :(得分:1)
问题是虽然MyObject
和ChildObject
相关,但List<MyObject>
和List<ChildObject>
不相关,这就是您收到错误的原因。
您的铸造解决方案有效,但它会将窗户的类型安全性抛出,这会导致错误。从List<MyObject>
转换为List<ChildObject>
的正确方法是使用通配符定义列表:
//From Child to parent
List<? extends ChildObject> child1 = new ArrayList<>();
List<? extends MyObject> parent1 = child1;
//From parent to child
List<? extends MyObject> parent2 = new ArrayList<>();
List<? extends ChildObject> child2 = (List<? extends ChildObject>) parent2;
您可以在this Java教程中阅读更多相关信息。
答案 3 :(得分:0)
如果你可以在没有施法的情况下做你想做的事,那么这就是滥用铸造。如果您的投射结果导致运行时错误,那么这就是滥用投射。
由于泛型被添加到Java中,因此大多数情况下都不需要进行转换 - 应该将转换保持在最低限度,因为它会隐藏在编译时可以在运行时发现的错误。
答案 4 :(得分:0)
泛型主要用于在编译时进行安全类型检查。并且它们不应该与铸造混合在一起,因为铸造会将此类型安全检查推迟到运行时。请考虑以下示例,其中Vehicle
是由各种类扩展的基类:Bike
,Car
等。
List<Vehicle> vehicles = new ArrayList<>();
vehicles.add(new Bike("Yamaha"));
vehicles.add(new Car("VW"));
vehicles.add(new Car("BMW"));
List<Car> cars = (List<Car>)(Object)vehicles;
for (Car vehicle : cars) {
System.out.println(vehicle.getType());
}
此处我只是在List<Car>
上进行迭代,但您可以看到此程序可能会导致致命错误,因为第一项不是Car
而是Bike
。