Java基础七--抽象类

在面向对象的概念中,所有的对象都是通过类来描绘的,但是反过来,并不是所有的类都是用来描绘对象的,如果一个类中没有包含足够的信息来描绘一个具体的对象,这样的类就是抽象类。

抽象类除了不能实例化对象之外,类的其它功能依然存在,成员变量、成员方法和构造方法的访问方式和普通类一样。

由于抽象类不能实例化对象,所以抽象类必须被继承,才能被使用。也是因为这个原因,通常在设计阶段决定要不要设计抽象类。

父类包含了子类集合的常见的方法,但是由于父类本身是抽象的,所以不能使用这些方法。

在Java中抽象类表示的是一种继承关系,一个类只能继承一个抽象类,而一个类却可以实现多个接口。

抽象类和抽象方法的声明格式

1
2
3
4
5
6
7
abstract class <类名> {
成员变量;
方法(){
方法体
}//一般方法
abstract 方法(){}//抽象方法
}

例如:

1
2
3
4
5
6
7
8
9
abstract public class Animal {
public String name;

public void eat(){
System.out.println("animal eating...");
}
abstract public void sleep();

}

从例子中可以看出,抽象类是用关键字 abstract 修饰的。抽象类中有一种特殊方法,即用 abstract 关键字来修饰的方法,称为”抽象方法“。


抽象类和抽象方法的特点

  • 抽象方法不允许直接实例化,换句话说抽象类不能创建对象,他只能作为其他类的父类。但可以通过向上转型,指向实例化。

  • 抽象方法只有声明,不能实现,也就是说仅有方法头,而没有方法体和操作实现。

    如:abstract void sleep();


抽象类的意义

  • 为其子类提供一个公共的类型(父类引用指向子类)

    1
    Animal a = new Cat();
  • 封装子类中重复内容(成员变量和方法)

  • 将父类设计成抽象类后,既可借由父子继承关系限制子类的设计随意性,在一定程度上避免了无意义父类的实例化


重点注意

  • 含有抽象方法的类,只能被定义成抽象类

    1
    2
    3
    4
    5
    6
    7
    8
    9
    public class Animal {//这里报错了
    public String name;

    public void eat(){
    System.out.println("animal eating...");
    }
    abstract public void sleep();

    }
  • 抽象类不一定包含抽象方法

    1
    2
    3
    4
    5
    public class Animal {
    public void eat(){
    System.out.println("animal eating...");//一般方法
    }
    }
  • 在抽象类中的成员方法可以包括一般方法和抽象方法

    1
    2
    3
    4
    5
    6
    7
    8
    abstract public class Animal {
    public String name;

    public void eat(){
    System.out.println("animal eating...");
    }
    abstract public void sleep();
    }
  • 抽象类不能实例化,及时抽象类里不包含抽象方法 ,这个抽象类 也不能创建实例,抽象类的构造方法主要是用于被其子类调用

    例子:

    Animal 抽象类中不包含抽象方法

    1
    2
    3
    4
    5
    6
    7
    abstract public class Animal {
    public String name;

    public void eat(){
    System.out.println("animal eating...");
    }
    }

    测试类中实例化 Animal ,编译器会报错

    1
    2
    3
    4
    5
    public class Main {
    public static void main(String[] args) {
    Animal a = new Animal();//这里报错了
    }
    }
  • 一个类继承抽象类后,必须实现其所有抽象方法,否则也是抽象类,不同的子类对父类的抽象方法可以有不同的实现

    如父类:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    abstract public class Animal {
    public String name;

    public void eat(){
    System.out.println("animal eating...");
    }

    abstract public void sleep();
    }

    则其子类 Cat 有两种做法

    方案一:重写抽象方法 sleep(),使方法得以实现

    1
    2
    3
    4
    5
    6
    7
    8
    9
    public class Cat extends Animal{

    public void sleep(){
    System.out.println("猫要睡大觉!");
    }
    public void run(){
    System.out.println("我不想跑");
    }
    }

    方案二:子类 Cat 类也定义为抽象类

    1
    2
    3
    4
    5
    6
    abstract public class Cat extends Animal{//没有实现父类中的抽象方法,所以是抽象类

    public void run(){
    System.out.println("我不想跑");
    }
    }
  • 即使父类是具体的,但其子类也可以是抽象的,如 Object 是具体的,但可以创建抽象子类

  • abstract 方法不能用 static 和 private 修饰;对于类,不能同时用 final 和 abstract 修饰,因为 final 关键字使得类不可继承,而 abstract 修饰的类如果不可以继承将没有任何意义。两者放一起回起冲突


一个完整的抽象类的例子

父类:

1
2
3
4
abstract public class Shape {
//抽象父类 Shape
abstract double area();//抽象方法
}

子类:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
public class Circle extends Shape {
public double r;
Circle(){

}
//创建带参构造函数
public Circle(double r){
this.r = r;
}

public double getR() {
return r;
}

public void setR(double r) {
this.r = r;
}

@Override
double area() {
return (3.14*r*r);
}
}

测试类:

1
2
3
4
5
6
public class Main {
public static void main(String[] args) {
Circle c = new Circle(3.5);
System.out.println("圆的面积为:"+c.area());
}
}

运行结果:

圆的面积为:38.465


小结

  • 抽象类不能被实例化,如果被实例化,就会报错,编译无法通过。只有抽象类的非抽象子类可以创建对象
  • 抽象类中不一定包含抽象方法,但是有抽象方法的类必定是抽象类
  • 抽象类中的抽象方法只是声明,不包含方法体,就是不给出方法的具体实现
  • 构造方法,类方法(用 static 修饰的方法)不能声明为抽象方法
  • 抽象类的子类必须给出抽象类中的抽象方法的具体实现,除非该子类也是抽象类
-------------本文结束感谢您的阅读-------------

本文标题:Java基础七--抽象类

文章作者:Cui Zhe

发布时间:2018年10月18日 - 11:10

最后更新:2018年10月21日 - 10:10

原始链接:https://cuizhe1023.github.io/2018/10/18/Java基础七-抽象类/

许可协议: 署名-非商业性使用-禁止演绎 4.0 国际 转载请保留原文链接及作者。