Java抽象类

示例

抽象类是用abstract关键字标记的类。与非抽象类相反,它可能包含抽象方法(无需实现)。但是,创建没有抽象方法的抽象类是有效的。

抽象类无法实例化。只要子类还是抽象的,或者实现由超类标记为抽象的所有方法,就可以对其进行子类化(扩展)。

一个抽象类的例子:

public abstract class Component {
    private int x, y;
    
    public setPosition(int x, int y) {
       this.x= x;
       this.y= y;
    }

    public abstract void render();
}

当类具有至少一个抽象方法时,必须将其标记为抽象。抽象方法是没有实现的方法。可以在具有实现的抽象类中声明其他方法,以便为任何子类提供通用代码。

尝试实例化此类将提供编译错误:

//错误:组件是抽象的;无法实例化   
Component myComponent = new Component();

但是,此类可以扩展Component,并为其所有抽象方法提供实现,并且可以实例化。

public class Button extends Component {

    @Override
    public void render() {
        //渲染一个按钮
    }
}

public class TextBox extends Component {

    @Override
    public void render() {
        //渲染文本框
    }
}

继承类的实例也可以转换为父类(正常继承),并且在调用abstract方法时它们提供多态效果。

Component myButton = new Button();
Component myTextBox = new TextBox();

myButton.render(); //渲染一个按钮
myTextBox.render(); //呈现文本框

抽象类与接口

抽象类和接口都提供了一种定义方法签名的方法,同时要求扩展/实现类提供实现。

抽象类和接口之间有两个主要区别:

  • 一个类只能扩展一个类,但可以实现许多接口。

  • 抽象类可以包含实例(非static)字段,但是接口只能包含static字段。

Java SE 8

在接口中声明的方法不能包含实现,因此在提供附加方法(实现称为抽象方法)很有用时,使用抽象类。

Java SE 8

Java 8允许接口包含默认方法,这些方法通常使用接口的其他方法实现,从而使接口和抽象类在这方面同样强大。

抽象类的匿名子类

为方便起见,java允许实例化抽象类的子类的匿名实例,这些实例在创建新对象时为抽象方法提供实现。使用上面的示例,它看起来可能像这样:

Component myAnonymousComponent = new Component() {
    @Override
    public void render() {
        // 渲染一个快速的一次性使用组件
    }
}