Java 列表对象的继承和转换
我无法将水果列表向下转换为列表中包含的水果子类Java 列表对象的继承和转换,java,list,inheritance,casting,downcast,Java,List,Inheritance,Casting,Downcast,我无法将水果列表向下转换为列表中包含的水果子类 public class Response { private List<Fruit> mFruitList; public List<Fruit> getFruitList() { return mFruitList; } } public class Fruit { } public class Orange extends Fruit { } List<Fruit&
public class Response {
private List<Fruit> mFruitList;
public List<Fruit> getFruitList() {
return mFruitList;
}
}
public class Fruit {
}
public class Orange extends Fruit {
}
List<Fruit> oranges = response.getFruitList();
公共类响应{
私人名单;
公共列表getFruitList(){
返回mFruitList;
}
}
公共级水果{
}
公共级橙汁{
}
List oranges=response.getFruitList();
我如何投射橙色,使其成为橙色类的列表?这是一种糟糕的设计模式吗?基本上,我从一个服务器得到一个JSON响应,它是一个水果列表。对于每个对Web服务的特定调用,我知道我将得到哪个Fruit子类,因此我需要适当地转换该列表 您应该强制转换列表,并测试每个元素是否为橙色的实例,然后在测试后强制转换为橙色。这是“最佳实践”。类型转换背后的整个想法是能够告诉编译器,“嘿,我比你知道的更多。”在你的代码中,编译器无法安全地将
列表
向下转换为列表
,因为它不知道在运行时列表将包含什么
如果您完全确定该列表将仅为Orange
实例,并且它使您的代码更易于向下转换,那么就使用它
List<Orange> oranges = (List<Orange>) response.getFruitList();
List oranges=(List)response.getFruitList();
当然,编译器会给你一个警告,因为你正在做它认为不应该做的事情。要知道,如果你错了,JVM可能会抛出一个
CastClassException
,让你笑到最后 如果您知道每个特定调用将得到水果的哪个子类,那么您应该使用泛型而不是强制列表
public class Response<T extends Fruit> {
private List<T> mFruitList;
public List<T> getFruitList() {
return mFruitList;
}
}
Response<Orange> response = // create
List<Orange> oranges = response.getFruitList();
公共类响应{
私人名单;
公共列表getFruitList(){
返回mFruitList;
}
}
响应=//创建
List oranges=response.getFruitList();
编辑:我说的模板是泛型类型。对不起,我现在有太多C++了,
> P。由于这种继承和铸造将不会以您期望的方式工作。在您给出的示例中,您可以将桔子和苹果都放在
列表中。如果列表中既有苹果又有橙子,您如何将其转换为列表
如果您需要一个列表
,那么为什么还要麻烦使用列表
。如果您明确地强制转换它,并且您确切地知道它包含什么,那么它可能是一个不必要的抽象
如果您正在使用一个API,您无法更改它,但您确切知道它包含什么,那么您应该使用instanceof check循环,以确保在需要使用橙色API时,明确地将每个水果实例转换为橙色。
List<Fruit> getFruits() {...}
List getFruits(){…}
你不能打字
List<Orange> oranges = (List<Orange>) getFruits();
List橙子=(List)getFruits();
由于类型擦除,在运行时getFruits的类型只是List。编译器甚至不允许您进行向下转换(我对此表示怀疑,所以在回答之前我在Eclipse中进行了尝试)
您可以告诉编译器您的列表将包含Fruit的某些子类,在这种情况下,您需要在方法上使用通配符:
List<? extends Fruit> getFruits() {...}
List您是否尝试过只List oranges=(List)response.getFruitList()代码>?是的,我尝试了很多强制铸造,但没有积极的结果。我正在考虑我的方法。也许最好将Response子类化,并为每个水果子类实现适当的列表。90%的响应包含每个水果类相同的成员,除了列表。更新,共识是-泛型而不是子类。你所说的模板到底是什么意思?我的理解是java没有C++所说的模板,这很有趣。让我试试这个。也许最好将Response子类化,并为每个相应的水果子类实现适当的列表?@Arch Stanton,而不是将Response子类化,您还可以对其进行泛型化<代码>公共类响应{private List fruit;/*etc.*/}
@talnicolas ha…我还没有看到你的评论。英雄所见略同同意。我最后一次使用Java是在泛型被引入之前,我开始对它们感到困惑。
@SuppressWarnings("unchecked")
List<Orange> oranges = (List<Orange>) getFruits();
@SuppressWarnings("unchecked")
List<Orange> oranges = (List) getFruits();
List<Orange> oranges = Arrays.asList((Orange[])getFruits().toArray())