接口
1. 认识接口
Java 提供了一个关键字 interface ,用这个关键字我们可以定义出一个特殊的结构:接口
- 在接口中定义的变量,默认都是常量
- 在接口中定义的方法,默认都是抽象方法
interface A {
// 成员变量(默认就是常量)
String NAME = "Jack";
// 成员方法(默认就是抽象方法)
void goToA();
}
interface B {
int AGE = 15;
void goToB();
}
// Car类一旦接入了接口,意味着,它要么必须重写抽象方法,要么它变成抽象类
class Car implements A, B {
@Override
public void goToA() {
}
@Override
public void goToB() {
}
}
public class Test {
public static void main(String[] args) {
Car c = new Car();
c.goToA();
c.goToB();
}
}
2. 接口的好处
- 弥补了类单继承的不足,一个类同时可以实现多个接口
- 让程序可以面向接口编程,这样程序员就可以灵活方便的切换各种业务实现
public class Test {
public static void main(String[] args) {
Student s1 = new Child();
Singer s2 = new Child();
dancer s3 = new Child();
s1.study();
s2.sing();
s3.dance();
}
}
class Child extends Student implements Singer, dancer {
@Override
public void sing() {
}
@Override
public void dance() {
}
}
class Student {
public void study() {
}
}
interface Singer {
void sing();
}
interface dancer {
void dance();
}
3. 感受接口的魅力
import java.util.ArrayList;
// 员工类
class Staff {
private String name;
private double salary;
public Staff() {
}
public Staff(String name, double salary) {
this.name = name;
this.salary = salary;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public double getSalary() {
return salary;
}
public void setSalary(double salary) {
this.salary = salary;
}
}
// 员工管理类
class StaffManager {
private ArrayList<Staff> list = new ArrayList<>();
private functionInterface obj = new Operator1(); // 这行是整个代码的核心,让我们解耦合的使用接口!
// private functionInterface obj = new Operator2(); // 想要改变业务模式,只需改变new Operator1()中的1
public StaffManager() {
list.add(new Staff("张三", 8000));
list.add(new Staff("李明", 9500));
list.add(new Staff("王刚", 7200));
list.add(new Staff("小强", 8800));
}
// 输出全部员工的信息
public void printInfo() {
obj.printInfo(list);
}
// 输出全部员工的平均薪资
public void printAverage() {
obj.printAverage(list);
}
}
// 接口: 定义业务要求
interface functionInterface {
void printInfo(ArrayList<Staff> list);
void printAverage(ArrayList<Staff> list);
}
// 操作: 实现接口的具体业务要求
// 操作1: 以xxx模式实现要求
class Operator1 implements functionInterface {
@Override
public void printInfo(ArrayList<Staff> list) {
System.out.println("-------------员工信息-------------");
for (int i = 0; i < list.size(); i++) {
Staff s = list.get(i);
System.out.println("姓名:" + s.getName() + " , 薪资:" + s.getSalary());
}
System.out.println("---------------------------------");
}
@Override
public void printAverage(ArrayList<Staff> list) {
double total = 0.0;
for (int i = 0; i < list.size(); i++) {
Staff s = list.get(i);
total += s.getSalary();
}
double average = total / list.size();
System.out.println("平均薪资:" + total);
}
}
// 操作2: 以yyy模式实现要求
class Operator2 implements functionInterface {
@Override
public void printInfo(ArrayList<Staff> list) {
System.out.println("-------------员工信息-------------");
for (int i = 0; i < list.size(); i++) {
Staff s = list.get(i);
if (s.getSalary() > 8000) {
System.out.println("姓名:" + s.getName() + "薪资8000+");
} else {
System.out.println("姓名:" + s.getName() + "薪资8000-");
}
}
System.out.println("---------------------------------");
}
@Override
public void printAverage(ArrayList<Staff> list) {
double total = 0.0;
for (int i = 0; i < list.size(); i++) {
Staff s = list.get(i);
total += s.getSalary();
}
double average = total / list.size();
System.out.println("平均薪资:" + total);
for (int i = 0; i < list.size(); i++) {
Staff s = list.get(i);
if (s.getSalary() > average) {
System.out.println(" " + s.getName() + "已达平均薪资");
} else {
System.out.println(" " + s.getName() + "未达到平均薪资");
}
}
}
}
public class Test {
// 程序入口
public static void main(String[] args) {
StaffManager m = new StaffManager();
m.printInfo();
m.printAverage();
}
}
4. 接口的细节
新增方法
- 之前学习的接口是传统的接口,从 JDK8 开始,接口中新增了三种方法
- 新增方法的目的是,增强接口的能力,便于项目的扩展和维护
public class Test {
public static void main(String[] args) {
B b = new B();
b.test1(); // ===默认方法===
A.test3(); // ===静态方法===
}
}
interface A {
// 0. 接口 interface 里面的方法,默认都会被 public 修饰
// 原因很简单,因为接口写出来就是为了让别人使用的呀!
// 所以下面介绍到的所有方法,除了特殊说明外,默认都是被 public 修饰了的
// 1. 默认方法:必须使用 default 修饰
// 它属于实例方法(对象的方法),必须使用"实现类"的对象来访问
default void test1() {
System.out.println("===默认方法===");
test2(); // 私有方法只能通过内部去调用了
}
// 2. 私有方法:必须使用 private 修饰(JDK 9才开始支持的)
private void test2() {
System.out.println("===私有方法===");
}
// 3. 静态方法:必须使用 static 修饰
static void test3() {
System.out.println("===静态方法===");
}
}
// 定义一个"实现类",用于实现A接口的方法
class B implements A {
}
接口的多继承
- 接口的多继承:一个接口可以同时继承多个接口
- 好处与作用:便于"实现类"去实现
interface A{
void test1();
}
interface B{
void test2();
}
interface C{}
// 接口的多继承
interface D extends A,B,C{
}
// D接口的"实现类"
class E implements D{
@Override
public void test1() {
}
@Override
public void test2() {
}
}
接口的其他注意事项(了解)
- 一个接口继承多个接口,如果多个接口中存在方法签名冲突,则此时不支持多继承
- 一个类实现多个接口,如果多个接口中存在方法签名冲突,则此时不支持多实现
- 一个类继承了父类,又同时实现了接口,父类中和接口中有同名的默认方法,实现类会优先用父类的
- 一个类实现了多个接口,多个接口中存在同名的默认方法,可以不冲突,这个类重写该方法即可