(一)定义
官方说法:在面向对象的概念中,所有的对象都是通过类来描绘的,但是反过来,并不是所有的类都是用来描绘对象的,如果一个类中没有包含足够的信息来描绘一个具体的对象,这样的类就是抽象类。 抽象:即不具体、或无法具体
抽象类除了不能实例化对象之外,类的其它功能依然存在,成员变量、成员方法和构造方法的访问方式和普通类一样。
由于抽象类不能实例化对象,所以抽象类必须被继承,才能被使用。故,通常在设计阶段决定要不要设计抽象类。
父类包含了子类集合的常见的方法,但是由于父类本身是抽象的,所以不能使用这些方法。
在 Java 中抽象类表示的是一种继承关系,一个类只能继承一个抽象类,而一个类却可以实现多个接口。
(二)抽象类的具体例子
例如:当我们声明一个几何图形类:圆、矩形、三角形类等,发现这些类都有共同特征:求面积、求周长、获取图形详细信息。那么这些共同特征应该抽取到一个公共父类中。但是这些方法在父类中又无法给出具体的实现,而是应该交给子类各自具体实现。那么父类在声明这些方法时,就只有方法签名,没有方法体,我们把没有方法体的方法称为抽象方法。Java语法规定,包含抽象方法的类必须是抽象类。
(三)语法格式
-
抽象方法:被abstract修饰没有方法体的方法。
-
抽象类:被abstract修饰的类。
抽象类的语法格式:
【权限修饰符】 abstract class 类名{
}
【权限修饰符】 abstract class 类名 extends 父类{
}
抽象方法的语法格式 :
【其他修饰符】 abstract 返回值类型 方法名(【形参列表】);
注意:抽象方法没有方法体,抽象类中的抽象方法只是声明,不包含方法体,就是不给出方法的具体实现也就是方法的具体功能。
具体代码:
//抽象类
public abstract class A {
//抽象方法
public abstract void print();
//抽象类中,也有构造方法,是供子类创建对象时,初始化父类成员变量使用的。
public A() {
}
}
//子类继承抽象类
public class AA extends A{
@Override
//方法重写,是子类对父类抽象方法的完成实现,我们将这种方法重写的操作,也叫做 实现方法 。
public void print() {
System.out.println("我是AA");
}
}
public class TestA {
public static void main(String[] args) {
//创建对象
// A a=new A();'A' is abstract; cannot be instantiated:抽象类不能创建对象,如果创建,编译无法通过而报错。只能创建其非抽象子类的对象。
AA a=new AA();
//调用方法
a.print();;
}
}
(四)抽象类的注意事项
关于抽象类的使用,以下为语法上要注意的细节
-
抽象类不能创建对象(抽象类不能被实例化),如果创建,编译无法通过而报错。只能创建其非抽象子类的对象。
理解:假设创建了抽象类的对象,调用抽象的方法,而抽象方法没有具体的方法体,没有意义。
-
抽象类中,也有构造方法,是供子类创建对象时,初始化父类成员变量使用的。
理解:子类的构造方法中,有默认的super()或手动的super(实参列表),需要访问父类构造方法。
-
抽象类中,不一定包含抽象方法,但是有抽象方法的类必定是抽象类。
理解:未包含抽象方法的抽象类,目的就是不想让调用者创建该类对象,通常用于某些特殊的类结构设计。
-
抽象类的子类,必须重写抽象父类中所有的抽象方法,否则,编译无法通过而报错。除非该子类也是抽象类。
理解:假设不重写所有抽象方法,则类中可能包含抽象方法。那么创建对象后,调用抽象的方法,没有意义。
5.构造方法,类方法(用 static 修饰的方法)不能声明为抽象方法。
(五)修饰符的使用问题
修饰符 | 外部类 | 成员变量 | 代码块 | 构造器 | 方法 | 局部变量 | 内部类 |
public | √ | √ | × | √ | √ | × | √ |
protected | × | √ | × | √ | √ | × | √ |
缺省 | √ | √ | × | √ | √ | × | √ |
private | × | √ | × | √ | √ | × | √ |
static | × | √ | √ | × | √ | × | √ |
final | √ | √ | × | × | √ | √ | √ |
abstract | √ | × | × | × | √ | × | √ |
native | × | × | × | × | √ | × | × |
注意事项:
不能和abstract一起使用的修饰符
(1)abstract和final不能一起修饰方法和类
(2)abstract和static不能一起修饰方法
(3)abstract和native不能一起修饰方法
(4)abstract和private不能一起修饰方法
static和final一起使用:
(1)修饰方法:可以,因为都不能被重写
(2)修饰成员变量:可以,表示静态常量
(3)修饰局部变量:不可以,static不能修饰局部变量
(4)修饰代码块:不可以,final不能修改代码块
(5)修饰内部类:可以一起修饰成员内部类,不能一起修饰局部内部类