在Java中,协变返回类型是什么?在面向对象编程中呢?
在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中被覆盖的方法必须声明返回Object
类型,因此调用代码必须明确将方法调用的结果向下转型(即使双方“知道”它只能是MyFoo的一个实例)。
请注意,clone()
没有什么特别之处,任何被覆盖的方法都可以有协变返回 - 我在这里使用它作为示例,因为这是一个标准方法,经常使用到该特性。
List<Foo>
和 List<FooBar>
相关吗? - zinkingclone()
的顶层定义视为Method<Void, Object>
,并询问更具体的Method<Void, MyFoo>
是否可分配给该父类型。只有当Java方法在其返回类型上是协变的时,才会是这样的情况。 - Andrzej Doyle这里有另一个简单的例子:
Animal
类
public class Animal {
protected Food seekFood() {
return new Food();
}
}
Dog
类
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();
}
}
Parent.foo()
返回一个与类型 A
无关的类型 A
,而 Child.foo()
返回从 A
派生出来的类型 B
。 - Davis Herring除了以上的回答,协变返回类型中可以进行重写,但有一个限制,即重写方法(子类方法)的返回类型应该是被重写方法(父类方法)返回类型的子类。这个规则从Java 5开始就有效。
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();
}
}
在Java 5之前,不可能通过改变返回类型来覆盖任何方法。但是,自从Java5以后,如果子类覆盖了返回非原始类型的任何方法,且将其返回类型更改为子类类型,则可以通过更改返回类型来覆盖方法。
当覆盖方法时,我们可以自由地拥有更具体的返回类型。
有助于防止返回值时出现运行时ClassCastException异常。
参考: www.geeksforgeeks.org
interface Interviewer {
default Object submitInterviewStatus() {
System.out.println("Interviewer:Accept");
return "Interviewer:Accept";
}
}
class Manager implements Interviewer {
@Override
public String submitInterviewStatus() {
System.out.println("Manager:Accept");
return "Manager:Accept";
}
}
class Project {
public static void main(String args[]) {
Interviewer interviewer = new Manager();
interviewer.submitInterviewStatus();
Manager mgr = new Manager();
mgr.submitInterviewStatus();
}
}
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;
}
}
Function.java
@FunctionalInterface
public interface Function<T, R> {
........
........
........
........
static <T> Function<T, T> identity() {
return t -> t;
}
}