java基础 -接口

接口的概述

java提供了一个关键字interface来定义接口。接口是一种纯粹的抽象类型,强调能做什么而非是什么。

//接口的定义
public interface A{ }

JDK8以前,接口中只能定义常量和抽象方法。与抽象类类似,接口不能创建对象。接口是用来被类实现(implements)的,一个类可以实现多个接口,实现接口的类必须重写所实现接口的全部抽象方法,否则得定义成抽象类,实现接口的类一般被称为实现类。

实现类的定义

public class B implements A{
    //重写的A接口内的抽象方法
    }

接口中的常量默认是public static final修饰,此前缀可以省略不写。接口中的抽象方法默认是public abstract修饰,同样在接口中此前缀可省略不写。下面是接口的一个案例:

package implementDemo1;
//JDK8之前,接口中只能定义常量和抽象方法
public interface A {
    //1、常量:接口中的常量默认是public static final修饰,可以不写
    String NAME="Code Blossom";
    //2、抽象方法:接口中的抽象方法默认是public abstract修饰,可以不写
    void run();
    void show();
    String go();
}
package implementDemo1;

public interface B {
    void paly();
}
package implementDemo1;

public class Text {
    public static void main(String[] args) {
        System.out.println(A.NAME);
        //接口不能创建对象
        //A a=new A() { };          //报错
        //接口是用来被类实现(implement)的,实现接口的类型被称为实现类,一个类可以实现多个接口
        //与抽象类相同,实现类要实现接口中的所有抽象方法
        C c=new C();
        c.run();
        c.show();
        c.paly();
        System.out.println(c.go());
    }
}

//C称为实现类,同时实现多个接口
//实现类实现多个接口,必须重写所有接口中的所有抽象方法,否则必须定义成抽象类
class C implements A,B{
    @Override
    public void run() {
        System.out.println("C run");
    }

    @Override
    public void show() {
        System.out.println("C show");
    }

    @Override
    public String go() {
        return "Code Blossom";
    }

    @Override
    public void paly() {
        System.out.println("C play");
    }
}

接口不同于类,只能被单继承,实现类可以实现多个接口,弥补了单继承的不足,使类的角色更多,功能更强大。例如,一个学生可以有多重身份,他可以是司机,也能是某个女生的男朋友,但类的单继承无疑无法简单实现这种复合身份,而使用接口可以简单解决。

package implementDemo2;

public class Text {
    public static void main(String[] args) {
        //目的:理解接口的好处
        //接口弥补了单继承的不足,一个类可以实现多个接口,使类的角色更多,功能更强大
        People p = new Student();
        BoyFriend bf = new Student();
        Driver d = new Student();
    }
}
//弥补了单继承的不足,一个类可以实现多个接口,使类的角色更多,功能更强大
//让程序可以面向接口编程,程序员可以灵活方便的切换各种业务实现(更有利于程序的解耦和)

interface Driver{ }
interface BoyFriend{ }

class People{ }

//继承People类,实现Driver和BoyFriend接口,使Student类功能更强大
class Student extends People implements Driver,BoyFriend{

}

上述代码的Student不仅继承了People类(即人的基本特性),还通过实现多个接口拥有了司机与男朋友的特性,使类的角色变多了,功能也随之变强。

JDK8以后,接口新增了三种方法,分别是默认方法,私有方法与静态方法。默认方法即为普通实例方法,区别在与接口中的默认方法需要在方法的返回类型前加上default修饰,说明这是默认方法。

私有方法用private修饰,若是需要调用私有方法需使用接口中的其他实例方法调用。静态方法与前面学习的相同,是用static修饰的方法,用类名.方法名访问,在接口中public可省略不写。

代码实例

package implementDemo4;

public interface A {
    //1、默认方法(普通实例方法):必须加default修饰
    //接口中的普通方法,默认是public的,可以省略public
    //如何调用? 使用接口的实现类的对象来调用
    default void print(){
        System.out.println("A.print()");
    }
    //2、私有方法,JDK9开始支持,用private修饰
    //如何调用? 使用接口中的其他实例方法调用
    private void print2(){
        System.out.println("A.print2()");
    }
    default void print1(){
        print2();
        System.out.println("A.print1()");
    }
    //3、静态方法
    //静态方法,默认是public的,可以省略public
    //如何调用? 只能使用接口名来调用
    static void print3(){
        System.out.println("A.print3()");
    }
}
package implementDemo4;


//JDK8开始,接口新增的三种方法
public class Text {
    public static void main(String[] args) {
        A a = new AImpl();
        a.print();
        //a.print3();       接口中的静态方法不能用对象调用,此处报错
        A.print3();
        a.print1();
    }
}


class AImpl implements A {

}

与类不同的是,接口中的静态方法无法用对象进行访问,若是用对象名.方法名会报错。

接口的注意事项:

接口与接口间可以多继承

一个类支持多个接口,但如果多个接口中存在方法签名冲突,则此时不支持多继承,也不支持多实现
一个类实现了多个接口,如果多个接口中存在同名的方法,可以不冲突,这个类重写这个方法就行。

package implementDemo5;

public class Text {
    //目标:理解接口的几个注意事项
    //一个类支持多个接口,但如果多个接口中存在方法签名冲突,则此时不支持多继承,也不支持多实现
    //一个类继承了父类,又同时实现了接口,如果父类和接口中有同名方法,实现类会优先使用父类的方法
    //一个类实现了多个接口,如果多个接口中存在同名的方法,可以不冲突,这个类重写这个方法就行
    public static void main(String[] args) {

    }
}

interface A1{
    void show1();
}
interface B1{
    String show1();
}
//此时报错
//interface C1 extends A1,B1 {
//    void show3();
//}

如上述代码,接口A1与接口B1中show1方法的返回类型不同,此时用接口C1继承接口A1与接口B1就会报错,因为两个方法的签名不同。

一个类继承了父类,又同时实现了接口,如果父类和接口(default定义的实例方法)中有同名方法,实现类会优先使用父类的方法。若是需要使用接口的方法,需要在类中创建一个中转方法,用接口名(必须是本类直接实现的接口).super.方法名

package implementDemo5;

public class Text {
    //目标:理解接口的几个注意事项
    //一个类支持多个接口,但如果多个接口中存在方法签名冲突,则此时不支持多继承,也不支持多实现
    //一个类继承了父类,又同时实现了接口,如果父类和接口中有同名方法,实现类会优先使用父类的方法
    //一个类实现了多个接口,如果多个接口中存在同名的方法,可以不冲突,这个类重写这个方法就行
    public static void main(String[] args) {
        D d=new D();
        d.print();
    }
}

interface A1{
    void show1();
}
interface B1{
    String show1();
}
//此时报错
//interface C1 extends A1,B1 {
//    void show3();
//}


//接口与接口可以多继承,一个接口可以同时继承多个接口
//类与类,单继承,一个类只能有一个直接父亲
//类与接口,多实现,一个类可以实现多个接口
interface A {
    void show1();
    default void show4(){
        System.out.println("接口的show4");
    }
}
class  Animal{
    public void show4(){
        System.out.println("父类的show4");
    }
        }
interface B {
    void show2();
}

interface C extends A,B {
    void show3();
}
//接口C继承了接口A与接口B,所以此时想实现接口A,B,C只需要implements C即可
//但需要重写所有接口中的抽象方法
class D extends Animal implements C {
    @Override
    public void show1() {
        System.out.println("show1");
    }

    @Override
    public void show2() {
        System.out.println("show2");
    }

    @Override
    public void show3() {
        System.out.println("show3");
    }
    public void print(){
        show4();//此时会调用父类的show4
        //若是想要调用接口的show4,则需要使用接口名.super.show4()
        C.super.show4();//此时会调用接口的show4
    }
}

最后,进行一个项目实战,体现接口在业务处理方面的优势

任务:设计一个班级学生的信息管理模块,学生数据有性别,姓名,成绩
业务一、打印出全班学生的信息,打印全班成绩的平均分
业务二、打印出班级全部学生的信息(包含男女人数),打印出平均成绩(去掉一个最高分和一个最低分)

package implementDemo3;

public interface Operator {
    void print_student();
    void print_averagescore();
}
package implementDemo3;

import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;

@AllArgsConstructor
@NoArgsConstructor
@Data
public class Student {
    private String name;
    private char sex;
    private int score;
}

 

package implementDemo3;

public class Operator1 implements Operator{

    private Student[] students;
    public Operator1(Student[] students)
    {
        this.students=students;
    }
    public Operator1(){ }
    public void GetStudent(Student[] sutdents)
    {
        this.students=students;
    }
    @Override
    public void print_student() {
        for(int i=0;i<students.length;i++)
        {
            System.out.println(students[i].getName()+" "+students[i].getSex()+" "+students[i].getScore());
        }
    }

    @Override
    public void print_averagescore() {
        int sum=0;
        for(int i=0;i<students.length;i++)
        {
            sum+=students[i].getScore();
        }
        System.out.println(sum/students.length);
    }
}
package implementDemo3;

public class Operator2 implements Operator{

    Student[] students;
    public Operator2(Student[] students) {
        this.students = students;
    }
    public Operator2(){ }
    public void GetStudent(Student[] sutdents)
    {
        this.students=sutdents;
    }

    @Override
    public void print_student() {
        int malecount=0;
        for(int i=0;i<students.length;i++)
        {
            System.out.println(students[i].getName()+" "+students[i].getSex()+" "+students[i].getScore());
            if(students[i].getSex()=='男')
                malecount++;
        }
        System.out.println("男学生人数为:"+malecount);
        System.out.println("女学生人数为:"+(students.length-malecount));
    }

    @Override
    public void print_averagescore() {
        int sum=students[0].getScore();
        int max=students[0].getScore();
        int min=students[0].getScore();
        for(int i=1;i<students.length;i++)
        {
            sum+=students[i].getScore();
            if(students[i].getScore()>max)
                max=students[i].getScore();
            if(students[i].getScore()<min)
                min=students[i].getScore();
        }
        System.out.println((sum-max-min)/(students.length-2));

    }
}
package implementDemo3;
//任务:设计一个班级学生的信息管理模块,学生数据有性别,姓名,成绩
//业务一、打印出全班学生的信息,打印全班成绩的平均分
//业务二、打印出班级全部学生的信息(包含男女人数),打印出平均成绩(去掉一个最高分和一个最低分)

public class Text {
    public static void main(String[] args) {
        Student[] students = new Student[5];
        students[0] = new Student("张三", '男', 90);
        students[1] = new Student("李四", '女', 80);
        students[2] = new Student("王五", '男', 70);
        students[3] = new Student("赵六", '女', 60);
        students[4] = new Student("钱七", '男', 50);
        Operator operatoruser = new Operator2(students);
        //当需要切换业务时,仅需在右边的new修改即可,利用多态实现了解耦合思想。
        operatoruser.print_student();
        operatoruser.print_averagescore();
    }
}

如上述代码,当想要切换业务时,仅需将Text定义业务对象的右边的Operator2修改成Operator1即可完成业务1、2自由切换。

抽象类与接口的相同点与不同点

相同点:

1、都可以有抽象方法,都不能创建对象

2、都是为子类接收他们的特性创建的,抽象类被子类继承,接口被子类实现。

3、一个类若是不设置为抽象类,想要继承抽象类或是实现接口,都需要重写其抽象方法,否则报错。

4、都支持多态,都能实现解耦合。

不同点:

1、抽象类可以定义类中的全部普通成员,接口只能定义常量,抽象方法(与JDK8后新增的三种方式)。

2、一个类继承了抽象类就不能继承其他类,一个类实现了接口还能实现其他接口或继承其他类。

3、抽象类只能被单继承,接口可以被多实现。

4、接口更适合用于代码的解耦合(可以被多实现),解耦合功能更强相比于抽象类。

5、抽象类体现模版思想,更适合作父类,实现代码复用。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值