Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/java/360.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_Abstract Class - Fatal编程技术网

Java 使方法实现的返回类型比抽象方法更具体

Java 使方法实现的返回类型比抽象方法更具体,java,abstract-class,Java,Abstract Class,考虑一下这个抽象类 abstract class AbstractBox { abstract Object getContent(); } 现在,我实现了一个StringBox,但是可能还有其他Boxes实现会返回任何类型的内容,这使我无法使抽象方法的返回类型更加具体: class StringBox extends AbstractBox { @Override Object getContent() { return ""; } } 与其让getContent(

考虑一下这个抽象类

abstract class AbstractBox {
  abstract Object getContent();
}
现在,我实现了一个
StringBox
,但是可能还有其他
Box
es实现会返回任何类型的内容,这使我无法使抽象方法的返回类型更加具体:

class StringBox extends AbstractBox {
  @Override
  Object getContent() {
    return "";
  }
}
与其让
getContent()
声明它将返回一个
对象
,显然它将返回一个
字符串
,我还可以这样做

class StringBox extends AbstractBox {
  @Override
  String getContent() {
    return "";
  }
}
这样就清楚地说明了
getContent()
将返回什么,并且仍然覆盖了抽象方法

  • 这个有名字吗
  • 这有什么坏处吗

  • 重写允许指定协变返回类型,在这里您可以在
    StringBox
    子类中使用它

    此功能从Java 1.5开始提供。
    从(重点是我的):

    8.4.5。方法结果

    如果 返回类型是引用类型的概念 返回类型可替换性支持协变返回,即 将返回类型专门化为子类型。

    在实践中,如果使用
    StringBox
    声明的类型操作变量,则类的客户端可以返回更具体的类型,这是一件好事,因为它可以避免降级

    例如:

    StringBox box = new StringBox();
    String boxContent = box.getContent();
    
    但是,如果使用
    AbstractBox
    声明的类型操作变量,则在编译时或运行时不会产生任何副作用,因为客户端仍然希望将
    对象
    作为返回类型:

    AbstractBox box = new StringBox();
    Object boxContent = box.getContent();
    

    在一般情况下,如果协方差返回能使客户机代码更清晰、更简单(就像没有任何强制转换一样),则应使用协方差返回

    重写允许指定一个协变返回类型,在这里您可以在
    StringBox
    子类中使用它

    此功能从Java 1.5开始提供。
    从(重点是我的):

    8.4.5。方法结果

    如果 返回类型是引用类型的概念 返回类型可替换性支持协变返回,即 将返回类型专门化为子类型。

    在实践中,如果使用
    StringBox
    声明的类型操作变量,则类的客户端可以返回更具体的类型,这是一件好事,因为它可以避免降级

    例如:

    StringBox box = new StringBox();
    String boxContent = box.getContent();
    
    但是,如果使用
    AbstractBox
    声明的类型操作变量,则在编译时或运行时不会产生任何副作用,因为客户端仍然希望将
    对象
    作为返回类型:

    AbstractBox box = new StringBox();
    Object boxContent = box.getContent();
    

    在一般情况下,如果协方差返回能使客户机代码更清晰、更简单(就像没有任何强制转换一样),则应使用协方差返回

    我相信这不是问题。如果使用抽象类,例如

     AbstractBox box;
    
    box.getContent()
    您将获得一个对象,如果知道实现,您可以强制转换

    如果使用具体的实现,则会得到字符串(也是一个对象)

    另一个解决方案是使用泛型方法,例如:

    abstract class AbstractBox<T> {
      abstract T getContent();
    }
    
    抽象类AbstractBox{
    抽象T getContent();
    }
    
    在实现中,将其添加为字符串

    class StringBox extends AbstractBox<String> {
      @Override
      String getContent() {
        return "";
      }
    }
    
    类StringBox扩展了AbstractBox{
    @凌驾
    字符串getContent(){
    返回“”;
    }
    }
    

    我认为这没有多大区别,因为您仍然需要使用StringBox来了解实现。我相信这不是问题。如果使用抽象类,例如

     AbstractBox box;
    
    box.getContent()
    您将获得一个对象,如果知道实现,您可以强制转换

    如果使用具体的实现,则会得到字符串(也是一个对象)

    另一个解决方案是使用泛型方法,例如:

    abstract class AbstractBox<T> {
      abstract T getContent();
    }
    
    抽象类AbstractBox{
    抽象T getContent();
    }
    
    在实现中,将其添加为字符串

    class StringBox extends AbstractBox<String> {
      @Override
      String getContent() {
        return "";
      }
    }
    
    类StringBox扩展了AbstractBox{
    @凌驾
    字符串getContent(){
    返回“”;
    }
    }
    
    我认为这没有多大区别,因为您仍然需要使用StringBox来了解实现

  • 是的,它是“协变返回类型”

  • 编译器仍然为
    StringBox
    生成一个返回
    Object
    的“桥接方法”,因此代码大小略有增加(以及性能的潜在降低,但这应该可以通过JIT轻松消除)

  • 正如@khelwood提到的,您经常希望使用泛型而不是协变返回类型(或者除此之外)

  • 是的,它是“协变返回类型”

  • 编译器仍然为
    StringBox
    生成一个返回
    Object
    的“桥接方法”,因此代码大小略有增加(以及性能的潜在降低,但这应该可以通过JIT轻松消除)

  • 正如@khelwood提到的,您经常希望使用泛型而不是协变返回类型(或者除此之外)


  • 使用泛型不是更好吗?然后使用
    AbstractBox
    您就知道它将生成什么类型。请看名称。使用泛型不是更好吗?然后使用
    AbstractBox
    您就知道它将生成什么类型。请参见名称。