Java基础之(十九)抽象类

来源:互联网 发布:手机屏保软件下载 编辑:程序博客网 时间:2024/06/10 01:06

说明
在自上而下的继承层次结构中,位于上层的类更具有通用性,甚至可能更加抽象。从某种角度看,祖先类更加通用,它只包含一些最基本的成员,人们只将它作为派生其他类的基类,而不会用来创建对象。甚至,你可以只给出方法的定义而不实现,由子类根据具体需求来具体实现。

这种只给出方法定义而不具体实现的方法被称为抽象方法,抽象方法是没有方法体的,在代码的表达上就是没有“{}”。包含一个或多个抽象方法的类也必须被声明为抽象类。

使用 abstract 修饰符来表示抽象方法和抽象类。

抽象方法

只有方法的定义,没有方法体的方法被称为抽象方法:

abstract void fun();

看一个简单的例子:

class Person{    String name;    int age;    Person(String name,int age){        this.name = name;        this.age = age;    }    public void info(){    System.out.println("此人名为"+ name+", 年龄是 "+age);      }    abstract void eat();}
输出结果:编译报错

包含一个或多个抽象方法的类也必须被声明为抽象类。

抽象类

在Java语言中使用abstract class来定义抽象类。

抽象类的规则如下:

  • 抽象类不能被实例化,即无法使用new关键字来生成对象;

  • 如果一个类当中包含有抽象方法,那么这个类必须被声明为抽象类;

  • 如果一个类中没有抽象函数,它也可以声明为抽象类;

  • 抽象类可以包含Field、方法(普通方法和抽象方法均可)、构造器、初始化块、内部类、枚举类。抽象类的构造器不能用于创建实例,主要是用于被其子类调用。

    由于抽象类不能实例化对象,所以抽象类必须被继承,才能被使用。

下面定义一个Person抽象类:

abstract class Person{    String name;    int age;    protected Person(){        System.out.println("Person的构造函数");    }    protected Person(String name,int age){        this.name = name;        this.age = age;    }    public void info(){        System.out.println("此人名为"+ name+", 年龄是 "+age);      }    abstract void eat();}

上面的Person类里包含了成员变量,普通方法,抽象方法和构造器,抽象类的构造器定义为protected,因为它主要只用于被其子类调用。

下面定义一个Chinese类,Chinese类被定义成普通类,因此必须实现Person类里的所有抽象方法,通过复写的方式。

class Chinese extends Person{        String address;        Chinese(){            super();            System.out.println("Chinese的构造函数");        }        Chinese(String name,int age,String address){            super(name,age);            this.address = address;        }        void eat(){            System.out.println("吃饭");        }    } 

上面的Chinese类继承了Person抽象类,并实现了抽象类的抽象方法,是一个普通类,因此可以创建实例。

class Test{    public void mian(String[] args){        Person p = new Chinese();        p.eat();    }}
输出结果:Person的构造函数Chinese的构造函数吃饭

使用abstract的注意事项

利用抽象类和抽象方法的优势,我们可以更好的发挥多态的优势,使程序更加灵活。

  • abstract修饰的类只能被继承;abstract修饰的方法必须由子类复写实现。final修饰的类不能被继承,final修饰的方法不能被重写。因此,final和abstract不能同时使用。

  • abstract不能用于修饰Field、局部变量、构造器

  • abstract不能和static同时使用

  • abstract不能和private同时使用

抽象类的作用

当编写一个类时,往往会为该类定义一些方法,这些方法用于描述该类的行为方式,这些方法都有具体的方法体。但在某些情况下,某个父类只是知道其子类应该包含怎样的方法,但无法确切地知道这些子类如何实现这些方法。例如我们定义了一个Printer(打印机)类,这个类提供了一个打印方法print();但不同的Printer子类打印的方式是不同的,(比如针式打印机和喷墨式打印机)Printer类无法准确地得知其子类的打印方式,这个时候就要用到抽象方法。

当然,可能有人会说,我们可以在Printer类中定义一个空方法,然后在子类中重写这个空方法。看下面这个例子:

class Printer{    void open(){    System.out.println("open");    }    void close(){    System.out.println("close");    }    void print(){    }}
class HPPrinter extends Printer{    void print(){    System.out.println("针式打印机");    }}
class CanonPrinter extends Printer{    void print(){    System.out.println("喷墨打印机");    }}
class Test{    public static void main(String[] args){        Printer p1 = new HPPrinter();        p1.open();        p1.close();        p1.print();        Printer p2 = new CanonPrinter();        p2.open();        p2.close();        p2.print();    }}
输出结果:open close针式打印机openclose喷墨打印机

虽然结果没有问题,但是代码中存在着安全隐患。
如果HPPrinter里忘记了重写print方法,这时代码却依然能够执行,p1.print();这行代码执行的时候,实际调用的是父类中的空方法,就不会出现想要的结果。

为了避免这种情况,Java建议使用abstract来修饰这种方法。

0 0