Java基础深度总结:抽象类和接口
没有比人更高的山没有比脚更长的路。
1.抽象
抽象性和具体性都是相对的,不是绝对的。概念的内涵越小,则其抽象程度就越高,其外延也越大,反之亦然。比如“人”比“男人”抽象一点,而“生物”又比“人”更抽象一点,“物质”则比“生物”更抽象。
抽象的概念是由具体概念依其“共性”而产生的,把具体概念的诸多个性排除,集中描述其共性,就会产生一个抽象性的概念。在Java中,可以通过接口和抽象类来体现面向对象(OOP)的抽象。
2.抽象类
2.1 什么是抽象类
所有的对象都是通过类来描述的,但是并不是所有的类都是可以描述对象(对象 = 状态 + 行为)的。如果一个类没有足够的信息来描述一个具体的对象,那么我们就可以将这样的类设为抽象类。
比如一个动物Animal对象,动物一般都可以发出叫声,但是到底发出怎样的叫声我们是不知道的,所以Animal就是一个抽象类,需要一个具体的动物,如狗、猫来对它进行特定的描述,我们才知道它的叫声。
从中我们可以发现,将具体的事物通过不断地提取共性,就能达到抽象的目的。
抽象方法:抽象方法是一种特殊的方法:它被abstract修饰,只有声明而没有具体的实现(没有方法体)。
abstract void speak();
抽象类:被abstract修饰修饰的类就是抽象类。
public abstract class Animal {
public abstract void cry();
}
public class Cat extends Animal{
@Override
public void cry() {
System.out.println("猫叫:喵喵...");
}
}
public class Dog extends Animal{
@Override
public void cry() {
System.out.println("狗叫:汪汪...");
}
}
public class Test {
public static void main(String[] args) {
Animal a1 = new Cat();
Animal a2 = new Dog();
a1.cry(); //猫叫:喵喵...
a2.cry(); // 狗叫:汪汪...
}
}
2.2 抽象类的特点
- 具有抽象方法的类一定是抽象类,但是抽象类不一定有抽象方法。
- 抽象的概念在问题领域没有对应的具体概念,所以用以表征抽象概念的抽象类是不能实例化的。
- 抽象类中包含一系列相关类的共性,所以抽象类的出发点就是为了继承,否则它没有存在的任何意义。
- 抽象类的根本作用是为了继承,所以abstract不能与private、final、static、native并列修饰抽象方法,abstract也不能与final修饰类。
2.3 抽象类与普通类
public abstract class Animal{
private String name;
private String color;
public Animal(String name, String color) {
this.name = name;
this.color = color;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getColor() {
return color;
}
public void setColor(String color) {
this.color = color;
}
}
从上面的例子可以看出来,尽管Animal是抽象类,他依然具有成员变量、成员方法、构造方法。
Tip:
- 抽象类虽然不能被实例化,但依然可以有构造函数,且构造函数在子类构造函数之前执行,通常用于初始化字段,或者执行被子类重写的方法。
区别:
- 抽象类不对应具体的概念,不能实例化而普通类可以直接实例化。
- 普通类和抽象类都可以用于继承,但抽象类的子类必须重写抽象类中的所有抽象方法,否则抽象类的子类也必须是抽象类。
3.接口
3.1 什么是接口
接口(英文:Interface),在JAVA编程语言中是一个抽象类型,是抽象方法的集合,接口通常以interface来声明。接口并不是类,编写接口的方式和类很相似,但是它们属于不同的概念。类描述对象的属性和方法。接口则包含类要实现的方法。
interface USB{
public abstract void read();
public abstract void write();
}
3.2 接口成员
接口中可以包含成员变量和成员方法,不能有构造函数。
- 成员变量:必须是public static final的,可以缺省。
- 成员方法: 必须是public abstract的,也可以缺省。
接口中的成员变量被public static final修饰,因此接口中的成员变量是常量。
接口是用来建立类与类之间的协议,它所提供的只是一种形式,而没有具体的实现,因此接口中的成员方法都是抽象的。
Tip:
JDK 1.8 以后,接口里可以有静态方法和默认方法了。
- 默认方法
interface I1{
public default void print(){
System.out.println("print");
}
}
- 静态方法
interface I1{
public static void print(){
System.out.println("print");
}
}
JDK1.8支持默认方法是因为不支持默认方法的接口的维护成本太高了。在 Java 8 之前,如果一个接口想要添加新的方法,那么要修改所有实现了该接口的类,让它们都实现新增的方法。
JDK1.8支持静态方法,这样就可以通过InterfaceName直接调用静态方法,从而提高了接口的竞争力。
3.3 接口特点
- 接口成员的权限修饰符必须为public,不可更改,可以缺省。
- 接口成员变量必须是static、final的,不可更改,可以缺省。
- 一个类可以同时实现多个接口,一个接口也可以同时继承多个接口
interface I1{
}
interface I2{
}
interface I3 extends I1, I2 {
}
class MethodTest implements I1,I2{
}
- 实现接口的非抽象类必须要实现该接口的所有方法。抽象类可以不用实现。
- 接口不可实例化,但可以声明一个接口变量,该变量必须引用一个实现该接口的类的对象。
4.接口与抽象类的异同
相同点:
- 抽象类和接口都不可实例化。
- 接口的实现类和抽象类的子类只有全部实现了接口或者抽象类中的方法后才可以被实例化。
区别:
- 从设计层面上看,抽象类是对一种事物的抽象,即对类抽象,而接口是对行为的抽象。抽象类提供了一种 IS-A 关系,需要满足里式替换原则,即子类对象必须能够替换掉所有父类对象。而接口更像是一种 LIKE-A 关系,它只是提供一种方法实现契约,并不要求接口和实现接口的类具有 IS-A 关系。
- 从使用上来看,一个类可以实现多个接口,但是不能继承多个抽象类。
- 接口的字段只能是 static 和 final 类型的,而抽象类的字段没有这种限制。
- 接口的成员只能是 public 的,而抽象类的成员可以有多种访问权限。
5.使用选择
使用接口:
- 需要让不相关的类都实现一个方法,例如不相关的类都可以实现 Comparable 接口中的 compareTo() 方法;
- 需要使用多重继承。
使用抽象类:
- 需要在几个相关的类*享代码。
- 需要能控制继承来的成员的访问权限,而不是都为 public。
- 需要继承非静态和非常量字段。
在很多情况下,接口优先于抽象类。因为接口没有抽象类严格的类层次结构要求,可以灵活地为一个类添加行为。并且从 Java 8 开始,接口也可以有默认的方法实现,使得修改接口的成本也变的很低。
本文地址:https://blog.csdn.net/qq_42080839/article/details/107693096