接口
特性
- 接口不是类,接口是对类的一组需求描述。
- 除非实现接口的类是抽象类,否则该类要实现接口中的所有方法。
- 接口中不含实例域,但是可以包含常量,提供实例域和方法实现的任务由实现接口的那个类来完成。
- 接口中的方法是隐式抽象的,接口中的方法会被隐式指定为 public abstract(只能是 public abstract,其他修饰符都会报错)。
- 在接口中定义的变量会被隐式的指定为 public static final 变量(由于带有 final 关键字,自然也可以理解为常量)。
- 接口中的方法不含方法体(static,default 修饰的方法除外)。
通过继承扩展接口
接口也可以通过继承来扩展
public interface Animal {
void walk();
}
public interface Person extends Animal {
void eat();
}
// 实现Person接口需要同时实现Person继承的接口中的方法
public class Student implements Person {
@Override
public void eat() {
System.out.println("Student eat");
}
@Override
public void walk() {
System.out.println("Student walk");
}
}
接口的默认方法
特性
- 接口的默认方法使用 default 关键字修饰。
- 接口中的默认方法必须有方法体。
默认方法冲突
在实现多个接口时,这些接口中可能会存在同名的默认方法。
- 父类优先:若父类中提供的方法和接口中的默认方法方法名相同,则接口中的默认方法将会被忽略。
- 接口冲突:手动选择其中一个接口的默认方法,或者重写冲突的方法。
// 1. 父类优先
public abstract class Animal {
public void work() {
System.out.println("我是父类 Animal 中的方法:work()");
}
}
public interface Person {
default void work() {
System.out.println("我是 Person 接口的默认方法:work()");
}
}
public class Pupil extends Animal implements Person {
public static void main(String[] args) {
// 接口中的默认方法会被忽略,调用的是父类 Animal 中的方法
new Pupil().work();
}
}
/****************************************************************************/
// 2. 接口冲突
public interface Person {
default void work() {
System.out.println("我是 Person 接口的默认方法:work()");
}
}
public interface Student {
default void work() {
System.out.println("我是 Student 接口的默认方法:work()");
}
}
public class Pupil implements Student, Person {
@Override
public void work() {
Person.super.work(); // 手动选择 Person 接口中的 work() 方法
}
/* 或者选择重写冲突的默认方法 work()
@Override
public void work() {
System.out.println("我重写了冲突的默认方法");
}
*/
public static void main(String[] args) {
new Pupil().work();
}
}
抽象类
抽象类除了不能被实例化之外,其他功能和一个普通类一样。
抽象方法
- 抽象方法不含方法体,他的具体实现将交给子类完成。
- 如果一个类包含抽象方法,则该类必须是抽象类。
- 任何子类必须重写父类的抽象方法,或者声明自身为抽象类。
- 构造方法,静态方法不能声明为抽象方法。
抽象类和接口的区别
接口 | 抽象类 | |
---|---|---|
方法体(已经实现的具体方法) | 不能有方法体。(JDK1.8 后可以有方法体) | 可以有方法体 |
成员变量 | 类型必须是 public static final | 可以是各种类型 |
多继承 | 可以实现多个接口 | 只能实现一个抽象类 |
静态代码块 | 不能有静态代码块(JDK1.8 后可以有静态代码块) | 可以有静态代码块 |