这种通用方法签名是否有意义?

时间:2015-06-24 08:17:43

标签: java generics

传统代码:

public <B extends IBox> List<B> getBoxList(String key)

该方法无法知道调用者实际期望的子类型,因此没有合理的方法来履行此合同。

重要提示:无法从密钥中推断出预期的子类型

因此签名应为:

public List<IBox> getBoxList(String key)

我的推理是否正确?

4 个答案:

答案 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。