13 接口、匿名内部类
lix_uan 610 1

接口

定义格式

  • JDK7:包含抽象方法
  • JDK8:增加了默认方法和静态方法
  • JDK9:增加了私有方法

示例

interface Flyable{
    //静态常量
    long MAX_SPEED = 7900000;//这里单位是毫米/秒,7.9千米/秒,超过这个速度,就变成卫星

    //抽象方法
    void fly();

    //默认方法
    public default void start(){
        System.out.println("开始");
    }
    public default void stop(){
        System.out.println("结束");
    }

    //静态方法
    public static void broken(){
        System.out.println("飞行中遇到物体就坏了");
    }
}

接口的实现

  • 接口不能创建对象,但是可以被实现(implements)

    class Bird implements Flyable{
    
        //重写/实现接口的抽象方法,【必选】
        public void fly() {
            System.out.println("展翅高飞");
        }
    
        //重写接口的默认方法,【可选】
        //重写默认方法时,default单词去掉
        public void start(){
            System.out.println("先扇两下翅膀,一蹬腿,开始飞");
        }
    }
    public class TestInteface {
        public static void main(String[] args) {
            //创建实现类对象
            Bird b = new Bird();
    
            //通过实现类对象调用重写的抽象方法,以及接口的默认方法,如果实现类重写了就执行重写的默认方法,如果没有重写,就执行接口中的默认方法
            b.start();
            b.fly();
            b.stop();
    
            //通过接口名调用接口的静态方法
            Flyable.broken();
        }
    }

接口的多实现

  • 接口中有多个抽象方法时,实现类必须重写所有抽象方法

  • 如果抽象方法有重名的,只需要重写一次

    【修饰符】 class 实现类  implements 接口1,接口2,接口3。。。{
        // 重写接口中所有抽象方法【必须】,当然如果实现类是抽象类,那么可以不重写
          // 重写接口中默认方法【可选】
    }
    
    【修饰符】 class 实现类 extends 父类 implements 接口1,接口2,接口3。。。{
        // 重写接口中所有抽象方法【必须】,当然如果实现类是抽象类,那么可以不重写
          // 重写接口中默认方法【可选】
    }

冲突问题

亲爹优先原则

  • 当一个类,既继承一个父类,又实现若干个接口时,父类的成员方法与接口中的抽象方法重名,子类就近选择执行父类的成员方法

必须做出选择

  • 一个类同时实现了多个接口,而多个接口中包含方法签名相同的默认方法时,必须保留一个,或者选择自己完全重写

    interface A{
        public default void d(){
            System.out.println("今晚7点-8点陪我吃饭看电影");
        }
    }
    interface B{
        public default void d(){
            System.out.println("今晚7点-8点陪我逛街吃饭");
        }
    }
    class C implements A,B{
        @Override
        public void d() {
            A.super.d();
        }
    }
    class D implements A,B{
        @Override
        public void d() {
            System.out.println("自己待着");
        }
    }

接口的多继承

  • 一个接口能继承另一个或者多个接口,接口的继承也使用extends关键字
  • 子接口重写默认方法时,default关键字可以保留
  • 子类重写默认方法时,default关键字不可以保留

其他特点

  • 接口中无法定义成员变量,但是可以定义常量,其值不可以改变2,默认使用public static final修饰
  • 接口中没有构造方法,不能创建对象
  • 接口中没有静态代码块

接口与实现类对象的多态引用

public class TestInterface {
    public static void main(String[] args) {
        Flyable b = new Bird();
        b.fly();

        Flyable k = new Kite();
        k.fly();
    }
}
interface Flyable{
    //抽象方法
    void fly();
}
class Bird implements Flyable{

    @Override
    public void fly() {
        System.out.println("展翅高飞");
    }

}
class Kite implements Flyable{

    @Override
    public void fly() {
        System.out.println("别拽我,我要飞");
    }    
}

经典接口介绍

java.lang.Comparable

public class TestComparable {
    public static void main(String[] args) {
        Student s1 = new Student(1,"张三",89);
        Student s2 = new Student(2,"李四",89);
        if(s1.compareTo(s2)>0){
            System.out.println("s1>s2");
        }else if(s1.compareTo(s2)<0){
            System.out.println("s1<s2");
        }else{
            System.out.println("s1 = s2");
        }
    }
}
class Student implements Comparable{
    private int id;
    private String name;
    private int score;

    //省略了构造器、get/set、toString等方法

    @Override
    public int compareTo(Object o) {
        //这些需要强制,将o对象向下转型为Student类型的变量,才能调用Student类中的属性
        Student stu = (Student) o;
        if(this.score != stu.score){
            return this.score - stu.score;
        }else{//成绩相同,按照学号比较大小
            return this.id - stu.id;
        }
    }    
}

java.util.Comparator

class StudentScoreCompare implements Comparator{

    @Override
    public int compare(Object o1, Object o2) {
        Student s1 = (Student) o1;
        Student s2 = (Student) o2;
        return s1.getScore() - s2.getScore();
    }    
}
import java.util.Comparator;

public class TestComparator {
    public static void main(String[] args) {
        Student stu1 = new Student("张三",89);
        Student stu2 = new Student("李四",78);

        StudentScoreCompare ssc = new StudentScoreCompare();
        if(ssc.compare(stu1, stu2)>0){
            System.out.println(stu1 + ">" + stu2);
        }else if(ssc.compare(stu1, stu2)<0){
            System.out.println(stu1 + "<" + stu2);
        }else{
            System.out.println(stu1 + "=" + stu2);
        }
    }
}

匿名内部类的使用

方式一:匿名内部类的对象直接调用方法

interface A{
    void a();
}
public class Test{
    public static void main(String[] args){
        new A(){
            @Override
            public void a() {
                System.out.println("aaaa");
            }
        }.a();
    }
}

方式二:通过父类或父接口的变量多态引用匿名内部类的对象

class B{
    public void b(){
        System.out.println("bbbb");
    }
}
public class Test{
    public static void main(String[] args){
        B obj = new B(){
            public void b(){
                System.out.println("ccccc");
            }
        };
        obj.b();
    }
}

方式三:匿名内部类的对象作为实参

interface A{
    void method();
}
public class Test{
    public static void test(A a){
        a.method();
    }

    public static void main(String[] args){
        test(new A(){

            @Override
            public void method() {
                System.out.println("aaaa");
            }            
        });
    }   
}
评论区

索引目录