Java 什么是协变返回类型?

Java 什么是协变返回类型?,java,oop,covariance,Java,Oop,Covariance,Java中的协变返回类型是什么?在面向对象编程中,协变返回通常意味着当重写方法时,重写方法的返回类型可以是被重写方法的返回类型的子类型 为了用一个例子说明这一点,一个常见的例子是Object.clone()——它被声明为返回一种类型的Object。您可以在自己的类中重写它,如下所示: public class MyFoo { ... // Note covariant return here, method does not just return Object publi

Java中的协变返回类型是什么?在面向对象编程中,协变返回通常意味着当重写方法时,重写方法的返回类型可以是被重写方法的返回类型的子类型

为了用一个例子说明这一点,一个常见的例子是
Object.clone()
——它被声明为返回一种类型的
Object
。您可以在自己的类中重写它,如下所示:

public class MyFoo
{

   ...

   // Note covariant return here, method does not just return Object
   public MyFoo clone()
   {
       // Implementation
   }
}
这里的好处是,任何持有对MyFoo对象的显式引用的方法都能够调用
clone()
,并且知道(无需强制转换)返回值是
MyFoo
的实例。如果没有协变返回类型,MyFoo中被重写的方法必须声明为返回
对象
——因此调用代码必须显式地向下转换方法调用的结果(即使双方都“知道”它只能是MyFoo的一个实例)


请注意,
clone()
没有什么特别之处,任何被重写的方法都可以有协变返回-我在这里以它为例,因为它是一个标准方法,通常非常有用。

从JDK 1.5版本开始,Java中引入了协变类型。我将用一个简单的例子来解释它:当我们重写一个函数时,函数可以对它的行为进行更改,这是你在大多数书中看到的,但是他们{authors}错过的是,我们也可以更改返回类型。 检查下面的链接以获得澄清,我们可以更改返回类型,只要可以将其分配给方法基本版本的返回类型

所以这个返回派生类型的特性叫做协变


这里是另一个简单的例子:

动物

public class Animal {

    protected Food seekFood() {

        return new Food();
    }
}
public class Dog extends Animal {

    @Override
    protected Food seekFood() {

        return new DogFood();
    }
}
Dog
class

public class Animal {

    protected Food seekFood() {

        return new Food();
    }
}
public class Dog extends Animal {

    @Override
    protected Food seekFood() {

        return new DogFood();
    }
}
可以将
Dog
seekFood()
方法的返回类型修改为
DogFood
——一个
Food
的子类,如下所示:

@Override
protected DogFood seekFood() {

    return new DogFood();
}

这是一个完全合法的覆盖,而
Dog
seekFood()
方法的返回类型被称为协变返回类型

协变返回类型仅仅意味着返回自己的类引用或其子类引用

class Parent {
 //it contain data member and data method
}

class Child extends Parent { 
//it contain data member and data method
 //covariant return
  public Parent methodName() {
     return new Parent();
          or 
     return Child();
  }

}
  • java中的协变返回类型允许缩小返回类型的范围 重写的方法的
  • 此功能将有助于避免向下投射 在客户端。它允许程序员无需编程 类型检查和向下浇铸
  • 协变返回类型始终为 仅适用于非基本返回类型
另一个例子来自Java

UnaryOperator.java

@FunctionalInterface
public interface UnaryOperator<T> extends Function<T, T> {

    /**
     * Returns a unary operator that always returns its input argument.
     *
     * @param <T> the type of the input and output of the operator
     * @return a unary operator that always returns its input argument
     */
    static <T> UnaryOperator<T> identity() {
        return t -> t;
    }
}
@functioninterface
公共接口一元运算符扩展函数{
/**
*返回始终返回其输入参数的一元运算符。
*
*@param运算符的输入和输出类型
*@return始终返回其输入参数的一元运算符
*/
静态一元运算符标识(){
返回t->t;
}
}
Function.java

@FunctionalInterface
public interface Function<T, R> {

    ........
    ........
    ........
    ........

    static <T> Function<T, T> identity() {
        return t -> t;
    }
}
@functioninterface
公共接口功能{
........
........
........
........
静态函数标识(){
返回t->t;
}
}

协变返回类型指定返回类型可能在与子类相同的方向上变化

class One{  
    One get(){return this;}  
}  

class Two extends One{  
  Two get(){return this;}  

void message(){
  System.out.println("After Java5 welcome to covariant return type");
}  

public static void main(String args[]){  
    new Two().get().message();  
}  
}
在Java5之前,不可能重写任何方法 通过更改返回类型。但是现在,自从Java5

可以通过更改返回类型来重写方法 如果子类重写任何方法 其返回类型为非原语 但它将其返回类型更改为子类类型

  • 它有助于避免混淆类层次结构中存在的类型强制转换 从而使代码可读、可用和可维护
  • 在重写时,我们可以自由地使用更具体的返回类型
    方法

  • 帮助防止返回时出现运行时ClassCastException

参考:
www.geeksforgeks.org

在Java5之前,不可能通过更改返回类型来覆盖任何方法。但现在,自Java5以来,如果子类重写任何返回类型为非原语的方法,但它将其返回类型更改为子类类型,则可以通过更改返回类型来重写方法。

要添加到上述答案中,可以在共变量返回类型之间进行重写,具有覆盖方法(子类方法)的返回类型应为被覆盖方法(超类方法)的返回类型的子类的约束。这从Java 5开始生效。

这篇博文()解释了这一点,只是在这里添加了知识库。@AkhilJain:这篇博文精彩而简单。这是我见过的关于Java如何支持协变返回类型的最好的示例解释。@kevinarpe谢谢,我很高兴它对这么多人有帮助。它不应该与
List
List
相关吗?这是广义上的协变类型,而不仅仅是这里所问的协变返回类型。不过,这是相同的基本原则-您可以将
clone()
的顶级定义视为一种
方法,并询问更具体的
方法是否可分配给该父类型。当且仅当Java方法的返回类型是协变的时,它才是协变的。它还包括
Parent.foo()
返回一个不相关的类型
A
Child.foo()
返回从
A
派生的类型
B