Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/java/390.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Java 这个通用方法签名有意义吗?_Java_Generics - Fatal编程技术网

Java 这个通用方法签名有意义吗?

Java 这个通用方法签名有意义吗?,java,generics,Java,Generics,遗留代码: public <B extends IBox> List<B> getBoxList(String key) public List getBoxList(字符串键) 方法无法知道调用方实际期望的子类型,因此没有合理的方法来实现此约定 重要提示:无法从键推断预期的子类型 因此,签名应为: public List<IBox> getBoxList(String key) public List getBoxList(字符串键) 我的推理正确吗

遗留代码:

public <B extends IBox> List<B> getBoxList(String key)
public List getBoxList(字符串键)
方法无法知道调用方实际期望的子类型,因此没有合理的方法来实现此约定

重要提示:无法从键推断预期的子类型

因此,签名应为:

public List<IBox> getBoxList(String key)
public List getBoxList(字符串键)

我的推理正确吗?

你可以很容易地这样做:

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

public List两者之间有细微的区别。第一个保留类型,而第二个将类型展平到其接口。通过移动到第二个,您实际上是在丢弃一些可能对调用方有用的信息

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");
}
接口IBox{
}
公共静态列表getBoxList1(字符串键){
返回null;
}
公共静态列表getBoxList2(字符串键){
返回null;
}
类ABox实现了IBox{
}
类BBox实现IBox{
}
公开无效测试(){
List aBox=Test.getBoxList1(“你好”);
List bBox=Test.getBoxList1(“Hello”);
//不允许。
List cBox=Test.getBoxList2(“Hello”);
List dBox=Test.getBoxList2(“Hello”);
}

为了解释这一点,让我们从一个例子开始

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 redBoxList=getBoxList(redKey);
List yellowBoxList=getBoxList(yellowKey);
但在后一种情况下,这将是:

List<RedBox> redBoxList = (List<RedBox>)getBoxList();//Since it returns List<IBox>
List<RedBox> redBoxList = (List<RedBox>)getBoxList();
List redBoxList=(List)getBoxList()//因为它返回列表
List redBoxList=(List)getBoxList();
因此,前一个代码在确保类型安全方面非常有效。
以前的代码更有意义。要了解有关泛型的更多信息,请参考有效的Java。

不,它没有。考虑下面的代码,这些代码甚至不会编译在java 8下,但会在java 7下编译并发出警告。调用者实际上希望从BoxDB获得一个BlueBox列表:

List<BlueBox> boxList = boxDB.<BlueBox>getBoxList("123");
List-boxList=boxDB.getBoxList(“123”);
但他实际上得到的是一张红盒子的清单。因此,这种方法没有兑现其承诺

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;
  }
}
import java.util.*;
公共类HelloWorld
{
公共静态void main(字符串[]args)
{
BoxDB BoxDB=新的BoxDB();
List-boxList=boxDB.getBoxList(“123”);
用于(IBox:boxList){
System.out.println(box.getClass().getName());//打印“RedBox”
}
}
}
接口IBox{
字符串getKey();
}
类RedBox实现了IBox{
字符串键;
公共红色框(字符串键){
this.key=key;
}
公共字符串getKey(){
返回键;
}
}
类BlueBox实现了IBox{
字符串键;
公共蓝盒(字符串键){
this.key=key;
}
公共字符串getKey(){
返回键;
}
}
类BoxDB
{
公共列表getBoxList(字符串键){
列表结果=新建ArrayList();
结果。添加((B)新的红色框(“123”);
返回结果;
}
}

我不明白这个问题。为什么您认为第二个选项更好?可以将泛型方法调用为
foo。getBoxList(…)
。我声明不可能履行合同,当然您可以始终强制转换结果。@Roland:有可能履行合同--只需
返回null
--它只是不太有用。对了,您将如何实现
getBoxList1
的方法体来实例化预期的返回类型?@Roland-也许键会将我指向工厂或构造函数?这里的本质是,第一个保留了最大数量的类型信息,而第二个丢弃了其中的一些信息。我将尝试发布一个更真实的演示。@OldCurmudgeon:
B
完全由调用方独立决定。好的,您将如何实现getBoxList的方法体来实例化预期的返回类型?前者肯定是非常不安全的类型<代码>列表yellowBoxList=getBoxList(红键)
完全合法。@Roland这要看情况而定。如果方法的实现类似于工厂或服务,那么它可以根据传递给方法getBoxList(红色)的键来决定返回类型。同样,返回类型表明,无论用户返回什么,都应该实现IBox接口。如果类型参数不是必需的,为什么需要单独的类型参数呢。类型参数在大多数情况下是有意义的,但不是所有情况。这与这两种情况无关。