抽象类
- 抽象类在形式上是abstract关键字修饰的类,抽象类是不能实例化的类,就是我们不能new一个抽象类对象,但是我们能定义抽象类对象变量,用它引用继承了抽象类的非抽象子类对象。
- 抽象方法就是abstract关键字修饰的类,包含一个或多个抽象方法的类必须声明为抽象类,但注意抽象类中不仅存在抽象方法,同时可以包含具体数据和具体方法,通俗理解就是,有抽象方法的类一定是抽象类,但抽象类不一定有抽象方法,帮助理解。抽象方法没有具体的实现,只包含方法名称,返回值,参数列表,访问修饰符,形式如代码所示
- 抽象类具体的应用场景,抽象类大多用于抽取相关 Java 类的共用方法实现或者是共同成员变量,然后通过继承的方式达到代码复用的目的。
- 抽象方法充当占位的角色,它们的具体实现在子类之中。子类在继承抽象父类的时候,必须要将父类中的抽象方法进行实现或者将子类也定义为抽象类
- 抽象类使用频率在业务开发中并不多,因为接口的存在
//抽象类
public abstract class Pet {
private String name;
private int age;
//抽象方法
public abstract void print();
public void plays(){
System.out.println("plays....");
}
}
//继承了抽象类的非抽象子类
public class Dog extends Pet {
@Override
public void print() {
System.out.println("dog print");
}
public void play(){
System.out.println("play...");
}
}
public class AbstractTest {
public static void main(String[] args) {
Pet dog = new Dog();
dog.print();
dog.plays();
}
}
接口
- interface修饰接口,接口是对行为的抽象,它是抽象方法的集合,接口中所有方法都是抽象方法,实现接口的子类通过关键字implements,并且要实现接口中的全部方法
- 接口中的所有方法的访问修饰权限都是public,不写并不是默认访问权限,而是public
- 子类可以实现多个接口
- 接口中的变量都是静态常量,如果变量没有使用static关键字修饰,它也表示静态常量,不用final修饰也是常量
- 接口中的方法和常量无论是否添加public修饰,默认的权限有且仅有一个,就是public
- 接口代表一种能力,将这些方法进行实现,就意味着具体了方法的能力,我们要关心实现类有何能力,而不关心实现细节,类实现了接口,类和接口是(has-a)的关系,而继承是(is-a)关系
- 接口实现了多继承,java不同于C++支持多继承,就是说java中一个类只能extends一个类,但是可以实现多个接口
- java SE 8中允许接口增加静态方法和默认方法,只是这点特性有违将接口作为抽象规范的初衷,静态方法和默认方法在子类中不必要覆写
//接口Door
public interface Door {
void openDoor();//系统默认加public abstract
public abstract void closeDoor();
}
//接口DoorBell
public interface DoorBell {
static void show(){
System.out.println("静态方法");
}
default void print(){
System.out.println("默认方法");
}
void photo();
}
//接口Lock
public interface Lock {
public static final int b = 200;
int a = 100;//默认加public static final
void openLock();
void closeLock();
}
//子类实现多个接口
public class LackDoor implements Lock,Door,DoorBell{
@Override
public void openDoor() {
}
@Override
public void openLock() {
}
@Override
public void closeDoor() {
}
@Override
public void closeLock() {
}
@Override
public void photo() {
System.out.println("拍照存档");
}
}
//测试类
public class TestLockDoor {
public static void main(String[] args) {
LackDoor lackDoor = new LackDoor();
lackDoor.openDoor();
lackDoor.openLock();
lackDoor.closeDoor();
lackDoor.closeLock();
System.out.println(LackDoor.a);
System.out.println(LackDoor.b);
//LackDoor.a = 200;报错不能更改final
lackDoor.print();
DoorBell.show();
}
}
抽象类和接口区别
- 抽象类中的方法可以有抽象方法,也可以有普通方法,但是接口中只能包含抽象方法
- 抽象类使用abstract关键字来修饰,接口使用interface关键字修饰
- 子类使用extends关键字来继承抽象类,使用implements来实现接
- 子类继承抽象类的时候必须要实现所有抽象方法,普通方法可以不重写,接口中所有方法必须要实现
- 抽象类中可以定义成员变量,而接口中只能定义静态常量
- 抽象类在子类实现的时候是单继承,而接口是多继承
- 抽象类和接口都不能实例化,但是抽象类中可以有构造方法,而接口中不能有构造方法
- 抽象类中可以实现接口,并且不实现接口中方法,而接口只能继承接口,不能实现接口
接口是抽象类的延伸,在 Java 8 之前,它可以看成是一个完全抽象的类,也就是说它不能有任何的方法实现。
从 Java 8 开始,接口也可以拥有默认的方法实现,这是因为不支持默认方法的接口的维护成本太高了。在 Java 8 之前,如果一个接口想要添加新的方法,那么要修改所有实现了该接口的类,让它们都实现新增的方法。接口的成员(字段 + 方法)默认都是 public 的,并且不允许定义为 private 或者 protected,接口的字段默认都是 static 和 final 的。
抽象类和接口应用场景
使用接口:
- 需要让不相关的类都实现一个方法,例如不相关的类都可以实现 Compareable 接口中的 compareTo() 方法;
- 需要使用多重继承。
使用抽象类:
- 需要在几个相关的类中共享代码。
- 需要能控制继承来的成员的访问权限,而不是都为 public。
- 需要继承非静态和非常量字段。
在很多情况下,接口优先于抽象类。因为接口没有抽象类严格的类层次结构要求,可以灵活地为一个类添加行为。并且从 Java 8 开始,接口也可以有默认的方法实现,使得修改接口的成本也变的很低。
Abstract Methods and Classes
深入理解 abstract class 和 interface
When to Use Abstract Class and Interface
参考GithubCyC2018/CS-Notes项目原文链接