Java 方法覆盖
原文: https://javabeginnerstutorial.com/core-java-tutorial/java-overriding/
从其超类继承该方法的类可以选择覆盖它。 覆盖的好处是可以定义特定于特定类的行为的能力。 对于具体的子类,如果在层次结构中没有其他超类实现抽象类中定义的所有方法,则将其强制实现。 覆盖有时称为运行时绑定。 这意味着将调用哪个覆盖方法将由引用类型而不是实例类型确定。
方法覆盖示例
public class ParentClass
{
public void show()
{
System.out.println("Show method of Super class");
}
}
public class SubClass extends ParentClass
{
//below method is overriding the ParentClass version of show method
public void show()
{
System.out.println("Show method of Sub class");
}
}
方法覆盖规则
- 覆盖方法不能具有比被覆盖的方法更多的限制性访问修饰符,但可以更少。
- 参数列表必须与覆盖的方法完全匹配,如果不匹配,则很可能是您正在重载该方法。
- 返回类型必须与在超类中的覆盖方法中声明的返回类型相同或为该子类型的子类型。
- 覆盖方法可以抛出任何非受检异常(运行时),但是它可以抛出比被覆盖方法声明的范围更广或更新的受检异常,但不能抛出更少或狭窄的异常检查。
- 不能覆盖最终的方法。
- 静态方法无法覆盖。 静态方法看起来可以覆盖,但它是隐藏的。
- 如果方法无法继承,则无法覆盖。
从超类调用被覆盖方法
如果要在执行子类方法之前调用超类的覆盖方法,该怎么办。 您可以使用SUPER
关键字。
public class SubClass extends superclass {
void method() {
super.method();
System.out.println("In Sub Class");
}
public static void main(String[] args) {
SubClass obj = new SubClass();
obj.method();
}
}
class superclass {
void method() {
System.out.println("In Super Class");
}
}
输出量
In Super Class
In Sub Class
静态方法不能被覆盖
静态方法不能被覆盖。 看起来好像它已被覆盖,但事实并非如此。 静态方法可以隐藏。
public class SubClass extends superclass {
static void method() {
// super.method(); // Super keyword will not work here. As it is not overriden method
System.out.println("In Sub Class");
}
@SuppressWarnings("static-access") // The static method method() from the type SubClass should be accessed in a static way
public static void main(String[] args) {
SubClass obj = new SubClass();
obj.method();
SubClass.method();// It is same as above. Same method will be invoked
}
}
class superclass {
static void method() {
System.out.println("In Super Class");
}
}
这里super
关键字不能用于调用超类方法。 因为它没有被超类的方法覆盖。
备忘单
- 不能覆盖构造器。
- 覆盖方法必须具有相同的参数集。
- 覆盖的方法必须具有相同的返回类型。 这些返回类型也可以是子类(协变返回)。
- 覆盖的方法无法具有更严格的访问修饰符。
- 覆盖的方法无法抛出新的或更广泛的异常(受检)。 看下面的示例
- 覆盖的方法可以引发任何非受检异常。
- 最终方法无法覆盖。
- 私有方法没有继承到子类,因此不能在子类中覆盖*。
- 多态适用于覆盖。
- 对象类型确定将调用哪个覆盖方法,并由运行时确定。
方法覆盖异常示例
package com.example.simple;
public class Overridding_Class extends base_class {
@Override
void method() throws exception_3 { // NO PROBLEM, It is not a broader Exception.
}
void method1() throws exception_1 { // It will give COMPILATION ERROR as it is throwing Broader Exception
}
}
class base_class {
void method() throws exception_2 {
}
void method1() throws exception_2 {
}
}
class excepion_1 extends Exception {
}
class exception_2 extends excepion_1 {
}
class exception_3 extends exception_2 {
}
方法覆盖示例
package com.override;
public class MethodOverrideRule {
public static void main(String args[])
{
// Here reference type and Object type is same
MethodOverrideRule scls = new MethodOverrideRule();
OverrideSubclass subcls = new OverrideSubclass();
// Here reference type is of Super class and Object is of child class
MethodOverrideRule subOcls = new OverrideSubclass();
// This will invoke method from Super class
scls.method();
// This will onvoke method form sub class
subcls.method();
/*
* Here overriding will work. Even reference type is of Super class still object type if of Subclass.
* Hence Subclass version of method will get invoked.
*/
subOcls.method();
/*
* Which overridden method is to be executed depends on the actual Object type at run time.
*/
}
void method(){
System.out.println("Overriding method without argument in Super");
}
int method(String str)
{
System.out.println("Overriding method with int argument in Super");
return 9;
}
}
class OverrideSubclass extends MethodOverrideRule{
/*
* Here we are overriding the method from super class.
* @Override annotation is used to confirm the same. It makes sure the all override rules get followed
*
*/
@Override
void method(){
System.out.println("Overriding method without argument in subclass");
}
@Override
int method(String str)
{
System.out.println("Overriding method with int argument in subclass");
return 10;
}
}