6.多态-final-抽象类-接口---黑马程序员

多态-final-抽象类-接口

多态

D:\code\黑马\code\oop-up-app02\src\com\polymorphism

多态的概念

  • 多态是在继承或实现的情况下的一种现象,分为对象多态和行为多态

    • 对象多态

    • 行为多态:

      • 编译看左边,运行看右边
      • people p2 = new Student(); p2.say();
      • 编译时只要左边people中有say方法就不会报错,但是运行时会在右边Student类中找重写后的say方法
      //父类
      public class people {
          public String name = "people";
      
          public void say(){
              System.out.println("I am a people");
          }
      }
      
      //子类1
      public class Student extends people{
          public String name = "Student";
      
          @Override
          public void say(){
              System.out.println("I am a Student");
          }
          
          public void study(){
              System.out.println("I am studying");
          }
      }
      
      //子类2
      public class Teacher extends people{
          public String name = "Teacher";
      
          @Override
          public void say(){
              System.out.println("I am a Teacher");
          }
      }
      
      
      public class Test {
          public static void main(String[] args) {
              //对象多态
              people p1 = new people();
              people p2 = new Student();
              people p3 = new Teacher();
      		
              //不存在属性多态
              System.out.println(p1.name);
              System.out.println(p2.name);
              System.out.println(p3.name);
      		
              //行为多态
              p1.say();//编译看左边,运行看右边
              p2.say();
              //p2.study();
              //会报错,因为p2是people类型,people没有study方法,所以无法调用study方法
              p3.say();
          }
      }
      /*
      result:
              people
              people
              people
              I am a people
              I am a Student
              I am a Teacher
      */
      

多态的前提

  • 有继承或实现关系
  • 存在父类引用子类对象
  • 存在方法重写

多态注意事项

  • 多态是指对象和行为的多态,而不谈属性的多态。
    • 调用属性时永远看左边,不看右边。即只能调用父类有的属性,且只能找到父类的属性,即使子类中有重名的属性,见上面对属性的调用
    • 调用方法时永远是编译看左边,运行看右边
    • 所能调用的方法只能是子类重写后的方法,子类特有的无法调用,见上面的study( )

多态的好处

  • 可以解耦合,使代码扩展性更强

  • 使用父类对象作为方法的形参,可以接收一切子类对象

    //子类与父类的代码见上文代码
    public class Test {
        public static void main(String[] args) {
            people p1 = new people();
            people p2 = new Student();
            people p3 = new Teacher();
            
            sayHello(p1);
            sayHello(p2);
            sayHello(p3);
        }
        
        public static void sayHello(people p){//可以接受父类和所有子类对象
            p.say();
        }
    }
    

多态的问题

  • 无法调用子类特有的方法,只能调用子类重写的方法,代码见上文多态的概念中的代码中的Test类

在这里插入图片描述

多态下的类型转换

用于解决多态无法调用子类特有的方法的问题

  • 自动类型转换:父类 变量名 = new 子类()
  • 强制类型转换:子类 变量名 = (子类)父类变量
注意事项
  • 存在继承或实现关系就可以在编译阶段进行强制类型转换,编译阶段不会报错

  • 运行时,如果发现对象的真实类型与强转后的类型不同,会报异常

        public static void main(String[] args) {
            people p = new Teacher();
            //Student s = (Student) p;
            // 会报ClassCastException,因为原来的p是Teacher类型,不能转换为Student类型
        }
    
  • 解决异常问题,在强转前使用instanceof关键字判断对象真实类型,再强转

    public class Test2 {
        public static void main(String[] args) {
            people p = new Teacher();
            hhh(p);
        }
    
        public static void hhh(people p){
            p.say();
            System.out.println(p instanceof Student);
            System.out.println(p instanceof Teacher);
            if (p instanceof Student) {
                Student s = (Student) p;
                s.study();
            } else if (p instanceof Teacher) {
                Teacher t = (Teacher) p;
                t.teach();
            }
        }
    }
    /*
    result:
            I am a Teacher
            false
            true
            I am teaching
    */
    

final

D:\code\黑马\code\oop-up-app02\src\com\finall

final关键字可以修饰类、方法和变量

  • 修饰类:该类被称为最终类,特点是不能被继承了。

    • 一般在工具类中使用
  • 修饰方法:该方法被称为最终方法,特点是不能被重写了。

  • 修饰变量:该变量只能被赋值一次。(必须在初始化时赋值)

    • final可以用来修饰局部变量和成员变量(实例成员变量和静态成员变量)

    • final修饰基本类型变量时,变量存储的数据不能被改变

    • final修饰引用类型的变量时,变量存储的地址不能变,但是地址指向的对象的内容可以改变

      //final修饰局部变量的两种情况
      public class Test {
          public static void main(String[] args) {
              final int a = 10;
              // a = 20; // 会报错,因为a是final类型,不能再次赋值
          }
          public static void hhh(final int a){
              // a = 20; // 会报错,因为a是final类型,不能再次赋值
          }
      }
      
      //final修饰成员变量
      public class Test1 {
          static final int a = 10;
          final int b = 20;
          public static void main(String[] args) {
      // 		  会报错,因为静态成员变量a是final类型,不能再次赋值
      //         a = 20; 
      //         会报错,因为实例成员变量b是final型,不能再次赋值   
      //         b = 30;     
          }
      }
      
      //final修饰基本类型和引用类型的区别
      public class Test2 {
          public static void main(String[] args) {
              final int a = 10;
              final int[] list = {1,2,3};
              
      //        a = 11;// 会报错,因为a是final修饰的基本数据类型的int变量,不能再次赋值
              list[0] = 10;//不会报错,因为引用类型可以修改地址指向的内容的值
      //        list = null//会报错,因为final修饰的引用类型的变量所存储的地址不能再次赋值
          }
      }
      

常量

  • 概念
    • 使用static final修饰的已经初始化的成员变量
  • 作用
    • 通常用于记录系统的配置信息
  • 命名规范
    • 使用大写英文单词,多个单词使用下划线连接起来
  • 使用常量记录系统配置信息的优势
    • 代码可读性更好
    • 可维护性更好
  • 执行原理
    • 程序编译后,常量会被“宏替换”:出现常量的地方全部会被替换成其记住的字面量,这样可以保证使用常量和直接用字面量的性能是一样的。也就是说不会影响性能,这些常量不会在运行时才找值,而是在编译后就将所有常量直接替换成需要的字面量

      //.java文件
      public class Test3 {
          public static final String MY_NAME = "LMH";
      
          public static void main(String[] args) {
              System.out.println(MY_NAME);
              System.out.println(MY_NAME);
              System.out.println(MY_NAME);
              System.out.println(MY_NAME);
          }
      }
      
      //编译后的.class文件
      package com.finall;
      
      public class Test3 {
          public static final String MY_NAME = "LMH";
      
          public Test3() {
          }
      
          public static void main(String[] args) {
              System.out.println("LMH");//对常量进行了自动赋值
              System.out.println("LMH");
              System.out.println("LMH");
              System.out.println("LMH");
          }
      }
      

抽象类abstract

D:\code\黑马\code\oop-up-app02\src\com\abstract_

  • 抽象类

    • abstract修饰的类
  • 抽象方法

    • abstract修饰的方法
    • 抽象方法中不能有方法体,只能由方法签名
  • 抽象类注意事项

    • 抽象类中不一定有抽象方法,有抽象方法的类一定为抽象类

      //将方法注释掉不会报错,因为抽象类中不一定有抽象方法
      //如果去掉类中的abstract会报错,因为有抽象方法的类一定为抽象类
      public abstract class Test {
          public abstract void test();
      }
      
      
    • 类该有的成员(成员变量,方法,构造器)抽象类都可以有,也就是说抽象类中既可以有抽象方法,也可以有实例方法,只要类中有一个抽象方法则该类就是抽象类

      //如果去掉类中的abstract会报错,因为类中有一个抽象方法
      public abstract class Test {
          public String name;//抽象类中可以有成员变量
      
          public Test() {//抽象类中可以有构造方法
              System.out.println("抽象类中可以有构造方法");
          }
      
          public String getName() {//抽象类中可以有普通方法
              return name;
          }
      
          public void setName(String name) {//抽象类中可以有普通方法
              this.name = name;
          }
      
          public abstract void test();//抽象类中可以有抽象方法
      }
      
    • 一个类继承抽象类,必须重写该类所有的抽象方法,否则必须将当前类也定义为抽象类

      //抽象类
      public abstract class Test{
          public abstract  void a();
          public abstract void b();
      }
      
      //重写了所有方法
      public class test1 extends Test{
          @Override
          public void a() {
              System.out.println("a");
          }
      
          @Override
          public void b() {
              System.out.println("b");
      
          }
      }
      
      //由于只重写了一个方法会报错,除了重写所有方法会在类名前添加abstract
      public class test2 extends Test{
          @Override
          public void a() {
              System.out.println("a");
          }
      }
      
  • 抽象类特点

    • 抽象类不允许创建对象,仅作为一种特殊的父类,让子类继承并实现
  • 抽象类的好处

    • 父类知道每个子类都要做某个行为,但每个子类要做的情况不一样,父类就定义成抽象方法,交给子类去重写实现,我们设计这样的抽象类是为了更好的支持多态。
  • 案例

在这里插入图片描述

public abstract class Animal {
    private String name;
    public abstract void action();

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }
}
public class dog extends Animal{
    @Override
    public void action() {
        System.out.println("狗汪汪汪的叫");
    }
}
public class cat extends Animal{
    @Override
    public void action() {
        System.out.println("猫喵喵喵的叫");
    }
}
public class test {
    public static void main(String[] args) {
        Animal d = new dog();
        d.setName("小狗");
        d.action();
        Animal c = new cat();
        c.setName("小猫");
        c.action();
    }
}
/*
result:
		狗汪汪汪的叫
		猫喵喵喵的叫
*/
  • 抽象类常见应用场景

    • 模板方法设计模式
      • 解决方法中存在部分重复代码的问题
    • 写法
      • 定义一个抽象类
      • 在类中写两个方法
        • 一个为模板方法:将相同代码放入
          • 最好使用final来修饰模板方法
        • 一个为抽象方法:将具体实现交给子类

在这里插入图片描述

public abstract class Person {
    private String name;
    private int age;

    public Person() {
    }

    public Person(String name, int age) {
        this.name = name;
        this.age = age;
    }
    //模板方法,用final修饰,放入相同代码
    public final void commonintroduce(){
        System.out.println("我的名字是:"+name+" 年龄:"+age + selfintroduce());
    }
    //抽象方法
    public abstract String selfintroduce();
}
public class Teacher extends Person{
    private String Skill;

    public Teacher() {
    }
    public Teacher(String name, int age ,String skill) {
        super(name, age);
        this.Skill = skill;
    }
    //实现抽象方法
    @Override
    public String selfintroduce() {
        return " 我的技能是:"+Skill+"。";
    }
}
public class Consult extends Person{
    private int num;

    public Consult() {
    }

    public Consult(String name, int age,int num) {
        super(name, age);
        this.num = num;
    }
	//实现抽象方法
    @Override
    public String selfintroduce() {
        return " 我的咨询人数是:"+num+"人。";
    }
}
public class Test {
    public static void main(String[] args) {
        Person p1 = new Teacher("张三", 20, "java");
        Person p2 = new Consult("李四", 30, 100);
        p1.commonintroduce();
        p2.commonintroduce();
    }
}
/*
result:
        我的名字是:张三 年龄:20 我的技能是:java。
        我的名字是:李四 年龄:30 我的咨询人数是:100人。
*/

接口

D:\code\黑马\code\oop-up-app02\src\com\interface_

初识接口

  • 使用interface定义接口

  • 接口不能创建对象

  • 接口中只能由属性和抽象方法

    • 属性默认为常量,默认使用public static final修饰
    • 方法默认是抽象方法,默认使用public abstract修饰
  • 接口需要被类使用implements实现,实现接口的类叫实现类

  • 一个实现类可以实现多个接口,但是必须要重写所有接口的抽象方法,否则要将实现类定义为抽象类

    //接口1
    public interface A {
        // 接口中的属性都是常量,默认使用public static final修饰
        String MY_NAME = "A";
        // 接口中的方法都是抽象方法,默认使用public abstract修饰
        void sayA();
    }
    
    //接口2
    public interface B {
        String MY_NAME = "B";
    
        void sayB();
    }
    
    //实现类
    public class C implements A,B{
    //必须同时实现所有的接口中的抽象方法
        @Override
        public void sayA() {
            System.out.println("sayA");
        }
    
        @Override
        public void sayB() {
            System.out.println("sayB");
        }
    }
    
    //测试类
    public class Test {
        public static void main(String[] args) {
            // 接口不能被实例化
            // A a = new A();
            // B b = new B();
            // 前两个为多态,后一个为普通对象
            A a = new C();
            B b = new C();
            C c = new C();
            // 接口中的属性都是常量,默认使用public static final修饰
            System.out.println(A.MY_NAME);
            System.out.println(B.MY_NAME);
    //        System.out.println(C.MY_NAME);//会报错,因为C中并没有常量MY_NAME
            // 接口中的方法都是抽象方法,默认使用public abstract修饰
            a.sayA();//a中只有sayA()方法,没有sayB()
            b.sayB();//b中只有sayB()方法,没有sayA()
            c.sayA();//c中既有sayA()方法,也有sayB()
        }
    }
    /*
    result:
            A
            B
            sayA
            sayB
            sayA
            sayB
    */
    

接口的好处

  • 弥补了类单继承的不足,一个类同时可以实现多个接口。

  • 让程序可以面向接口编程,这样程序员就可以灵活方便的切换各种业务实现。

    //抽象父类
    abstract class people{
        public String name;
        public int age;
    
        public people(String name, int age) {
            this.name = name;
            this.age = age;
        }
        public abstract void say();
    }
    
    //driver接口
    interface Driver{
        void drive();
    }
    
    //cooker接口
    interface Cooker{
        void cook();
    }
    
    //实现
    class Student extends people implements Driver, Cooker{
    
        public Student(String name, int age) {
            super(name, age);
        }
    
        @Override
        public void say() {
            System.out.println("我叫" + super.name + ",今年" + super.age + "岁,学生");
        }
    
        @Override
        public void drive() {
            System.out.println("我叫" + super.name + ",今年" + super.age + "岁,司机");
        }
    
        @Override
        public void cook() {
            System.out.println("我叫" + super.name + ",今年" + super.age + "岁,厨师");
        }
    }
    
    
    //测试
    public class Test {
        public static void main(String[] args) {
            Student student = new Student("张三", 18);
            student.say();
            student.drive();
            student.cook();
            //使用接口来接受对象,可以更有效的标识对象,当前对象就是个司机,无法调用学生和厨师的方法
            Driver driver = new Student("李四", 20);
            driver.drive();
    //        driver.say();//会报错,因为是Driver类型,没有say方法
            Cooker cooker = new Student("王五", 22);
            cooker.cook();
        }
    }
    /*
    result:
            我叫张三,今年18岁,学生
            我叫张三,今年18岁,司机
            我叫张三,今年18岁,厨师
            我叫李四,今年20岁,司机
            我叫王五,今年22岁,厨师
    */
    

案例

在这里插入图片描述

//实体类
public class Student {
    private String name;
    private char sex;
    private double score;

    public Student() {
    }
    public Student(String name, char sex, double score) {

        this.name = name;
        this.sex = sex;
        this.score = score;
    }
    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public int getSex() {
        return sex;
    }

    public void setSex(char sex) {
        this.sex = sex;
    }

    public double getScore() {
        return score;
    }

    public void setScore(double score) {
        this.score = score;
    }

    @Override
    public String toString() {
        return "name='" + name + '\'' +
                ", sex=" + sex +
                ", score=" + score;
    }
}
//接口
public interface Studentoper {
    void printInfo(ArrayList<Student> students);
    void printAverageScore(ArrayList<Student> students);
}
//实现一,完成方案一
public class StudentoperImpl1 implements Studentoper{

    @Override
    public void printInfo(ArrayList<Student> students) {
        for (Student student : students) {
            System.out.println(student);
        }
    }

    @Override
    public void printAverageScore(ArrayList<Student> students) {
        double sum = 0;
        for (Student student : students) {
            sum += student.getScore();
        }
        System.out.println("平均分为:" + sum / students.size());
    }
}
//实现二,完成方案二
public class StudentoperImpl2 implements Studentoper{

    @Override
    public void printInfo(ArrayList<Student> students) {
        int countMan = 0;
        int countWoman = 0;
        for (Student student : students) {
            if (student.getSex() == '男')
                countMan++;
            else
                countWoman++;
            System.out.println(student);
        }
        System.out.println("男生人数:" + countMan);
        System.out.println("女生人数:" + countWoman);
    }

    @Override
    public void printAverageScore(ArrayList<Student> students) {
        double max = students.get(0).getScore();
        double min = students.get(0).getScore();
        double sum = 0;
        for (Student student : students) {
            if (student.getScore() > max)
                max = student.getScore();
            if (student.getScore() < min)
                min = student.getScore();
            sum += student.getScore();
        }
        double sum1 = sum - max - min;
        double avg = sum1/ (students.size() - 2);
        System.out.println("平均分为:" + avg);
    }
}
//操作类
public class ClassOper {
    private final ArrayList<Student> students = new ArrayList<>();
    //使用多态完成方案一
    private final Studentoper studentoper1 = new StudentoperImpl1();
    //使用多态完成方案二
    private final Studentoper studentoper2 = new StudentoperImpl2();
    //添加学生
    public ClassOper() {
        students.add(new Student("张三",'男' , 100));
        students.add(new Student("李四", '女', 99));
        students.add(new Student("王五",'男' , 98));
        students.add(new Student("赵六", '女', 97));
        students.add(new Student("田七",'女' , 96));
        students.add(new Student("周八", '女', 95));
    }

    public void printInfo(boolean flag) {
        System.out.println("---------------"+flag+"----------------");
        if (flag)
            studentoper1.printInfo(students);
        else
            studentoper2.printInfo(students);
    }

    public void printAverageScore(boolean flag) {
        if (flag)
            studentoper1.printAverageScore(students);
        else
            studentoper2.printAverageScore(students);
    }
}

//测试类
public class Test {
    public static void main(String[] args) {
        ClassOper classOper = new ClassOper();
        boolean flag = true;//如果更改为false,则使用StudentoperImpl2的实现
        classOper.printInfo(flag);
        classOper.printAverageScore(flag);
    }
}
/*
result:
        ---------------true----------------
        name='张三', sex=男, score=100.0
        name='李四', sex=女, score=99.0
        name='王五', sex=男, score=98.0
        name='赵六', sex=女, score=97.0
        name='田七', sex=女, score=96.0
        name='周八', sex=女, score=95.0
        平均分为:97.5、
        ---------------false----------------
        name='张三', sex=男, score=100.0
        name='李四', sex=女, score=99.0
        name='王五', sex=男, score=98.0
        name='赵六', sex=女, score=97.0
        name='田七', sex=女, score=96.0
        name='周八', sex=女, score=95.0
        男生人数:2
        女生人数:4
        平均分为:97.5
*/

接口的其他细节

JDK8之后接口中新增的三种方法
  • 默认方法,使用default修饰,可以被重写,但没必要
  • 私有方法,使用private修饰,只能在接口内部调用
  • 静态方法:使用static修饰
//接口
public interface A {
    /*
    * 接口中的默认方法(实例方法)
    * 1. 必须使用default关键字修饰,默认被public修饰
    * 2. 接口中的默认方法,可以通过接口的实现类对象,直接调用
    * 3. 接口中的默认方法,也可以被接口的实现类进行覆盖重写
    */
    default void method1(){
        System.out.println("A接口的默认方法");
        method2();
    }

    /*
    * 接口中的私有方法(实例方法)
    * 1. 必须使用private关键字修饰
    * 2. 只能在接口中被调用
    * 3. JDK9之后才有私有方法,可以被接口中的默认方法或者静态方法调用
    */
    private void method2() {
        System.out.println("A接口的私有方法");
    }

    /*
    * 接口中的静态方法(类方法)
    * 1. 必须使用static关键字修饰,默认被public修饰
    * 2. 接口中的静态方法,可以通过接口名直接调用
    */
    static void method3(){
        System.out.println("A接口的静态方法");
    }
}
//实现类
public class B implements A{
}
//测试类
public class Test {
    public static void main(String[] args) {
        A a = new B();
        a.method1();
        A.method3();
    }
}
/*
result:
        A接口的默认方法
        A接口的私有方法
        A接口的静态方法
*/
新增的三种方法的好处
  • 增加了接口的能力,更便于项目的扩展和使用
    • 在实际开发中,如果有100个类实现了某一个接口,那么当该接口需要新增一个功能时,对应的100个实现类都需要重写该新增的方法,那么工作量会很大,而现在只要使用新增的三种方法则只需要操作接口即可,实现类会自动继承新增的默认方法,也可通过接口直接调用新增的静态方法
接口的多继承

概念

  • 一个接口可以继承多个接口

好处

  • 便于实现类去实现接口

    • 比如A接口继承了B和C接口,那么实现类只需要实现A接口,就可以实现A,B,C三个接口,此时实现类必须重写A,B,C三个接口中的全部方法

      interface B{
          void m1();
      }
      interface C{
          void m2();
      }
      interface A extends B,C{
          void m3();
      }
      //只有同时实现A,B,C三个接口中的方法,才不会报错
      public class Test implements A{
          @Override
          public void m1() {
          }
      
          @Override
          public void m2() {
          }
      
          @Override
          public void m3() {
          }
      }
      
接口其他注意事项(了解)
  • 一个接口继承多个接口,如果多个接口中存在方法签名不一致,则此时不支持多继承。

    • 此时当前接口不知道应该继承哪个方法
  • 一个接口继承多个接口,如果多个接口中存在方法签名一致,则此时只需要重写一次即可,支持多继承

    //一个接口继承多个接口,如果多个接口中存在方法签名不一致,则此时不支持多继承。
    interface D{
        void test();
    }
    interface E{
        String test();
    }
    //会报错,无法继承
    interface F extends D,E{
    }
    
    //一个接口继承多个接口,如果多个接口中存在方法签名一致,则此时只需要重写一次即可,支持多继承
    public class Test1 implements C{
        @Override
        public void test() {
            System.out.println("test");
        }
        
    }
    interface A{
        void test();
    }
    interface B{
        void test();
    }
    interface C extends A,B{
    
    }
    
  • 一个类实现多个接口,如果多个接口中存在方法签名冲突,则此时不支持多实现。

    //一个类实现多个接口,如果多个接口中存在方法签名冲突,则此时不支持多实现。
    public class Test2 implements A1,B1{
    
    }
    //会报错
    interface A1{
        void m1();
    }
    interface B1{
        void m1(String s);
    }
    
  • 一个类继承了父类,又同时实现了接口,父类中和接口中有同名的默认方法,实现类会优先用父类的。

    //一个类继承了父类,又同时实现了接口,父类中和接口中有同名的默认方法,实现类会优先用父类的。
    public class Test3 {
        public static void main(String[] args) {
            T3 t3 = new T3();
            t3.m1();//没有重写的情况下,优先使用父类的方法
        }
    }
    
    class T1 {
        public void m1() {
            System.out.println("T1.m1");
        }
    }
    interface T2 {
        default void m1() {
            System.out.println("T2.m1");
        }
    }
    class T3 extends T1 implements T2 {
    }
    /*
    result:
    		T1.m1	
    */
    
  • 一个类实现了多个接口,多个接口中存在同名的默认方法,可以不冲突,这个类重写该方法即可。

    //一个类实现了多个接口,多个接口中存在同名的默认方法,可以不冲突,这个类重写该方法即可。
    public class Test4 {
        public static void main(String[] args) {
            C3 c3 = new C3();
            c3.hi();
        }
    }
    interface C1{
        void hi();
    }
    interface C2{
        void hi();
    }
    class C3 implements C1,C2{
        @Override
        public void hi() {
            System.out.println("hi");
        }
    }
    

}
//会报错
interface A1{
void m1();
}
interface B1{
void m1(String s);
}


- 一个类继承了父类,又同时实现了接口,父类中和接口中有同名的默认方法,实现类会优先用父类的。

```java
//一个类继承了父类,又同时实现了接口,父类中和接口中有同名的默认方法,实现类会优先用父类的。
public class Test3 {
    public static void main(String[] args) {
        T3 t3 = new T3();
        t3.m1();//没有重写的情况下,优先使用父类的方法
    }
}

class T1 {
    public void m1() {
        System.out.println("T1.m1");
    }
}
interface T2 {
    default void m1() {
        System.out.println("T2.m1");
    }
}
class T3 extends T1 implements T2 {
}
/*
result:
		T1.m1	
*/
  • 一个类实现了多个接口,多个接口中存在同名的默认方法,可以不冲突,这个类重写该方法即可。

    //一个类实现了多个接口,多个接口中存在同名的默认方法,可以不冲突,这个类重写该方法即可。
    public class Test4 {
        public static void main(String[] args) {
            C3 c3 = new C3();
            c3.hi();
        }
    }
    interface C1{
        void hi();
    }
    interface C2{
        void hi();
    }
    class C3 implements C1,C2{
        @Override
        public void hi() {
            System.out.println("hi");
        }
    }
    
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值