📜  Java中将final与继承一起使用

📅  最后修改于: 2020-03-22 15:12:17             🧑  作者: Mango

先决条件:在Java中重写继承
final是Java中用于限制某些功能的关键字。我们可以使用final关键字声明变量、方法和类。

将final与继承一起使用

在继承期间,我们必须声明带有final关键字的方法,在所有派生类中,我们都需要对它们执行相同的实现。注意,在继承的初始阶段不必声明最终方法(始终为基类)。我们可以在任何我们想要的子类中声明最终方法,如果任何其他类扩展了该子类,则它必须遵循与该子类相同的方法实现。

// Java展示final和继承一起使用
// 基类
abstract class Shape
{
    private double width;
    private double height;
    // 构造函数
    public Shape(double width, double height)
    {
        this.width = width;
        this.height = height;
    }
    // getWidth被声明为final,任何子类不能重写此方法
    public final double getWidth()
    {
        return width;
    }
    // getHeight被声明为final,任何子类不能重写此方法
    public final double getHeight()
    {
        return height;
    }
    // getArea()被声明为final,任何子类不能重写此方法
    abstract double getArea();
}
// 派生类1
class Rectangle extends Shape
{
    // 构造器
    public Rectangle(double width, double height)
    {
        // 调用构造函数
        super(width, height);
    }
    // getArea被重写,被声明为final,任何子类不能重写此方法
    // Rectangle cann't override it
    @Override
    final double getArea()
    {
        return this.getHeight() * this.getWidth();
    }
}
// 派生类2
class Square extends Shape
{
    // 构造器
    public Square(double side)
    {
        // 调用构造器
        super(side, side);
    }
    // getArea被重写,被声明为final,任何子类不能重写此方法
    @Override
    final double getArea()
    {
        return this.getHeight() * this.getWidth();
    }
}
// 测试代码
public class Test
{
    public static void main(String[] args)
    {
        // Rectangle对象
        Shape s1 = new Rectangle(10, 20);
        // Square对象
        Shape s2 = new Square(10);
        // s1的宽和高
        System.out.println("s1宽 : "+ s1.getWidth());
        System.out.println("s1高 : "+ s1.getHeight());
        // s2的宽和高
        System.out.println("s2宽 : "+ s2.getWidth());
        System.out.println("s2高 : "+ s2.getHeight());
        // s1的面积
        System.out.println("s1面积 : "+ s1.getArea());
        // s2的面积
        System.out.println("s2面积 : "+ s2.getArea());
    }
}

输出:

s1宽 : 10.0
s1高 : 20.0
s2宽 : 10.0
s2高 : 10.0
s1面积 : 200.0 
s2面积 : 100.0

使用final防止继承

当一个类声明为final时,则不能将其子类化,即,任何其他类都不能对其进行扩展。例如,当创建一个不可变的类(如预定义的String类)时,这特别有用。以下片段说明了带有类的final关键字:

final class A
{
     // 声明方法和fields
}
// 下面的声明不合法.
class B extends A
{
    // ERROR! Can't subclass A
}

注意 :

  • 将类声明为final时,也隐式将其所有方法声明为final。
  • 以下非法:声明一个类既是抽象的,并使用final,因为一个抽象类是不完整的本身,并在它的子类依靠提供完整的实现,但final类不能拥有子类。有关抽象类的更多信息,请参考Java中的抽象类。

使用final防止重写

当一个方法声明为final的话,就无法通过subclasses.The重写对象类做到这一点,它的一些方法是final的。以下片段通过方法说明了final关键字:

class A
{
    final void m1()
    {
        System.out.println("这是一个final方法.");
    }
}
class B extends A
{
    void m1()
    {
        // 报错,不能重写.
        System.out.println("非法!");
    }
}

通常,Java在运行时动态地解决对方法的调用。这称为后期绑定或动态绑定。但是,由于无法重写final方法,因此可以在编译时解决对某个方法的调用。这称为早期绑定或静态绑定