Java 抽象类

Java 抽象类

Java 中有一个叫做抽象方法的机制,它只有声明而没有方法体:

abstract void functionName();

包含抽象方法的类叫做抽象类。如果一个类包含一个或多个抽象方法,那么这个类就必须限定为抽象类,否则编译器会报错。

abstract class ClassName {
    abstract void functionName();
}

抽象类不能被直接实例化:

ClassName c = new ClassName(); // 编译器会报错

如果创建一个继承抽象类的新类,那么必须为它父类的所有抽象方法提供定义,如果不这么做,这个新类仍然是一个抽象类,编译器会强制我们为新类加上abstract关键字。

可以将一个不包含任何抽象方法的类声明为抽象类,这样做虽然有点别扭,但是它可以实现不能被实例化的特性。

总结起来,抽象类有以下三类:

  • 仅包含抽象方法
  • 既包含抽象方法又包含常规方法
  • 仅包含常规方法,不包含抽象方法

一个简单的示例:

public class AbstractClassTest {

    public static void main(String[] args)
    {
        Bmw myCar = new Bmw();
        myCar.illuminate();
        myCar.soundWhistle();
    }
}

abstract class Car {
    /**
     * 鸣笛
     * 不同的汽车对于实现鸣笛的方式不同
     */
    abstract void soundWhistle();

    /**
     * 灯光
     * 每个车的灯光是一样的
     */
    public void illuminate()
    {
        System.out.println("Light On!");
    }

}

class Bmw extends Car {
    @Override
    void soundWhistle() {
        System.out.println("Bee Bee!");
    }
}

为什么需要抽象类和抽象方法呢?

抽象方法和抽象类看上去是多余的,对于抽象方法,不知道如何实现,定义一个空方法体不就行了吗,而抽象类不让创建对象,看上去只是增加了一个不必要的限制。

引入抽象方法和抽象类,是Java提供的一种语法工具,对于一些类和方法,引导使用者正确使用它们,减少被误用。

使用抽象方法,而非空方法体,子类就知道他必须要实现该方法,而不可能忽略。

使用抽象类,类的使用者创建对象的时候,就知道他必须要使用某个具体子类,而不可能误用不完整的父类。

就好比定义了一个模板,你需要遵守规则的情况下来设计代码。

另外,送上在java - Can we instantiate an abstract class? - Stack Overflow看到的一个问题,抽象类真的不能被实例化吗?


abstract class my {
    public void mymethod() {
        System.out.print("Abstract");
    }
}

class poly {
    public static void main(String a[]) {
        my m = new my() {};
        m.mymethod();
    }
}

按照那个链接中网友所说的,这里的m并不是严格意义上的抽象类实例化,而是实例化了抽象类的匿名子类。

对象的实例化应该是new ClassName();,分号在()之后,而不是在{}之后,那样的话是实例化了一个匿名类(anonymous class)。

抽象类和接口

抽象类和接口有类似之处,都不能用于创建对象,接口中的方法其实都是抽象方法。如果抽象类中只定义了抽象方法,那抽象类和接口就更像了。但抽象类和接口根本上是不同的,一个类可以实现多个接口,但只能继承一个类。

抽象类和接口是配合而非替代关系,它们经常一起使用,接口声明能力,抽象类提供默认实现,实现全部或部分方法,一个接口经常有一个对应的抽象类。


参考来源:

Java编程的逻辑 (20) - 为什么要有抽象类? - 老马说编程 - 博客园 (cnblogs.com)