传统代码:
public <B extends IBox> List<B> getBoxList(String key)
该方法无法知道调用者实际期望的子类型,因此没有合理的方法来履行此合同。
重要提示:无法从密钥中推断出预期的子类型。
因此签名应为:
public List<IBox> getBoxList(String key)
我的推理是否正确?
答案 0 :(得分:0)
您可以轻松地这样做:
public List<? extends IBox> getBoxList(String key)
答案 1 :(得分:0)
不,它没有。考虑下面的代码甚至不能在Java 8下编译,但会在Java 7下编译并带有警告。调用者实际上期待BoxDB中的BlueBox列表:
List<BlueBox> boxList = boxDB.<BlueBox>getBoxList("123");
但他实际获得的是RedBox列表。因此,该方法无法实现其承诺。
import java.util.*;
public class HelloWorld
{
public static void main(String[] args)
{
BoxDB boxDB = new BoxDB();
List<BlueBox> boxList = boxDB.<BlueBox>getBoxList("123");
for (IBox box: boxList) {
System.out.println(box.getClass().getName());//prints "RedBox"
}
}
}
interface IBox {
String getKey();
}
class RedBox implements IBox {
String key;
public RedBox(String key) {
this.key = key;
}
public String getKey() {
return key;
}
}
class BlueBox implements IBox {
String key;
public BlueBox(String key) {
this.key = key;
}
public String getKey() {
return key;
}
}
class BoxDB
{
public <B extends IBox> List<B> getBoxList(String key) {
List<B> result = new ArrayList<>();
result.add((B)new RedBox("123"));
return result;
}
}
答案 2 :(得分:-1)
两者之间存在细微差别。第一个保留类型,而第二个将类型展平到它的界面。通过移动到第二个,您实际上丢弃了一些可能对调用者有用的信息。
interface IBox {
}
public static <B extends IBox> List<B> getBoxList1(String key) {
return null;
}
public static List<IBox> getBoxList2(String key) {
return null;
}
class ABox implements IBox {
}
class BBox implements IBox {
}
public void test() {
List<ABox> aBox = Test.<ABox>getBoxList1("Hello");
List<BBox> bBox = Test.<BBox>getBoxList1("Hello");
// Not allowed.
List<ABox> cBox = Test.getBoxList2("Hello");
List<IBox> dBox = Test.getBoxList2("Hello");
}
答案 3 :(得分:-1)
为了解释这个,我们先来看一个例子
public RedBox implements IBox{
//implementation here
}
public BlueBox implements IBox{
//implementation here
}
现在假设有一个案例我需要RedBoxe和YellowBox的列表,那么根据第一个代码我的调用将是
List<RedBox> redBoxList = getBoxList(redKey);
List<YellowBox> yellowBoxList = getBoxList(yellowKey);
但在后一种情况下,这将是:
List<RedBox> redBoxList = (List<RedBox>)getBoxList();//Since it returns List<IBox>
List<RedBox> redBoxList = (List<RedBox>)getBoxList();
因此,前一代码在确保类型安全方面非常有效。 前代码更有意义。要阅读有关泛型的更多信息,请参阅Effective Java。