在Java中使用协变返回类型的方法重写和重载
在面向对象的编程语言中,返回类型共变是指当一个方法在子类或子类中被重载时,其返回类型可以被一个更窄的类型所取代。在限制自定义方法的返回类型时,它消除了对返回类型的投掷或验证的需要。
只有非原始的返回类型可以使用共变的返回类型。子类方法可以通过改变覆盖方法的返回类型来覆盖基类方法。术语 "方法重载 "指的是改变一个方法的参数,本文将进一步讨论。
变量返回类型
返回语句将控制权返回给方法的调用者。每个Java方法在使用前都必须有一个返回类型。像int
,float
,reference
, 或void
这样的原始类型可以作为返回值。
正如我们前面所说,共变返回类型意味着当一个方法在子类或子类中被重载时,其返回类型可以被替换成更窄的类型。在这里,我们将深入研究如何使用协变返回类型来覆盖方法。
关于协变返回类型的规则
对于协变返回类型,主要有三条规则需要记住。
下面是它们的列表。
- 如果一个子类的覆盖方法返回相同的类型,那么该子类的覆盖方法应该与它的超类或子类的返回类型相匹配。
- 子类中的下划线方法不应该覆盖父类中的方法,反之亦然。
- 开发者只能对对象类型使用协变返回类型,不能对原始类型使用协变返回类型。
为了演示协变返回类型,让我们看看如何通过调整一个方法的返回类型来覆盖它。
//base class
class Color{
// method getcolor returns an object of type color
public Color getColor(){
Color s = new Color();
return s;
}
}
//this class will inherit from the class color and will override the getcolor() method returning the object of the type red class
class Red extends Color{
@Override
public Red getColor(){
Red s = new Red();
return s;
}
}
当Base和Derived的返回类型互换时,上面的应用就会失败。
@override注解
方法覆盖是在子类中声明一个在父类中已经存在的方法。覆盖被用来允许子类覆盖父类的方法实现。
在使用Java时,覆盖一个有异常的方法需要你遵循这三个关键的准则。
以下是其中几条。
- 如果覆盖的方法没有使用throws子句,那么覆盖的方法就不能抛出检查过的或编译时的异常,或未检查过的或运行时的异常。
- 抛出未检查或运行时异常的被覆盖方法可以抛出任何不受控制的运行时异常或与被覆盖方法相同的异常。
- 子类方法可以对超类方法抛出的异常进行子类化,但是子类方法不能对超类异常进行子类化,而且子类方法可以抛出任何未检查的或运行时的异常。
假设你不利用@Override annotation
。在这种情况下,它不会引起任何问题,也就是说,当一个超类方法(被覆盖的方法)说它可以抛出一个异常时,任何覆盖必须声明它们可以抛出同一类型的异常或该异常的子类型。
这也有一些好处,我们将在下面看到。
- 它方便了对代码的阅读。
- 它简化了程序的维护。
- 因此,返回类型更加明确,减少了对类型转换的需要。
- 这段代码防止了
ClassCastExceptions
,避免了ClassCastException的发生,ClassCastException表示一个对象被投到它不是实例的子类中的尝试。
现在让我们来看看一个基于@override注解的例子。
class Vehicle {
Vehicle getObject() {
System.out.println("The Base class method.");
return new Vehicle();
}
}
class Car extends Vehicle {
//Overriding getObject method.
@Override
Car getObject() {
System.out.println("Derived class method from Base class.");
return new Car(); .
}
}
public class Main {
public static void main(String[] args) {
Car lexus = new Car();
lexus.getObject();
}
}
输出
Derived class method from Base class.
因为类是非原始的返回类型,共变类型只是可以想象的,通过这样,你应该注意到这一点。
共变返回类型的优点
- 它使代码更容易理解,更容易辨认,更容易管理。
- 由于协变返回类型的存在,方法重写可能会有更具体的返回类型。
ClassCastExceptions
通过在运行时使用协变返回类型,可以防止返回。
方法重载
方法重载是指改变方法的参数的过程,如前所述。Java虚拟机(JVM)一直支持基于返回类型的重载。
因为JVM会查找或解析一个方法的完整签名,这在JVM中是可以接受的。在同一个类中可能存在多个同类方法。协变返回类型是由java编译器(javac)支持和实现的。
另一方面,你可以使用Java类文件反汇编器Javac来验证代码。Java中的协变返回类型之所以能够实现,是因为javac采用了这种方法。为了支持协变返回类型,JVM不需要做任何改变。
你不能只在方法重载期间改变返回类型。如果我们只是改变返回类型,编译器将很难确定使用哪个函数。因此,改变返回类型并不是一种选择。
下面是方法重载的一些优点。
- Java中的重载是指用相同的名称但不同的参数构造许多方法的能力。
- 这样做的关键好处是,代码更有条理。
- 方法重载的使用提高了应用程序的可读性。
反汇编的红色类代码
这段代码是由javac根据前面的颜色和红色类的例子生成的。
class Red extends Color {
Red();
public Red getColor();
public Color getColor();
}
总结
在Java中把方法声明为子类或派生类,并且名称与父类或基类相同,参数数量也相同,可以说重载方法在返回类型上是不变的。
如果返回类型是被覆盖方法的返回类型的子类,我们可以通过修改其返回值来覆盖一个方法。在Java中,主方法可以被重载,但JVM只运行原来的主方法;它从不调用重载的主方法。