JavaSE进阶02:多态、抽象类、接口

本文详细介绍了Java SE进阶中的多态原理,包括多态的概念、成员访问特点、好处与局限性,以及抽象类和接口的定义、特点和应用实例。深入探讨了如何在实际项目中灵活运用这些概念来提升代码的灵活性和扩展性。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

系列文章目录

JavaSE进阶01:继承、修饰符
JavaSE进阶02:多态、抽象类、接口
JavaSE进阶03:内部类、Lambda表达式
JavaSE进阶04:API中常用工具类
JavaSE进阶05:包装类、递归、数组的高级操作、异常
JavaSE进阶06:Collection集合、迭代器、List、ArrayList、LinkedList
JavaSE进阶07:泛型、Set集合、TreeSet、二叉树、红黑树
JavaSE进阶08:HashSet、Map集合、HashMap、TreeMap、可变参数、不可变集合
JavaSE进阶09:Stream流、File类
JavaSE进阶10:IO流、字节流、字节缓冲流
JavaSE进阶11:字符流、字符缓冲流、转换流、对象操作流、Properties集合
JavaSE进阶12:多线程、线程同步、线程池
JavaSE进阶13:网络编程入门、UDP通信程序、TCP通信程序、日志、枚举
JavaSE进阶14:类加载器、反射
JavaSE进阶15:XML、注解、单元测试
JavaSE进阶扩充:JDK8 HashMap底层分析(了解)
JavaSE进阶扩充:JDK8 ArrayList线程安全问题和源码分析、集合常见面试题
Java进阶作业



1:多态

1.1 多态概述

  • 多态:指的是同一个对象,在不同时刻表现出来的多种形态

举例:猫
我们可以说猫是猫: cat = new ();
我们也可以说猫是动物:动物
animal = new** ();
这里猫在不同的时刻表现出来了多种形态,这就是多态。

多态的前提和体现:

  • 有继承/实现关系
  • 有方法重写
  • 有父类引用指向子类对象
    父类引用,指的是左边的内容;而子类对象,指的是右边的内容。

1.2 多态中成员访问特点

多态中成员方法特点:

  • 成员变量:编译看左边,执行看左边
  • 成员方法:编译看左边,执行看右边

为什么成员变量和成员方法的访问不一样呢?因为成员方法有重写,而成员变量没有

public class Animal {
    public int age = 40;
    public void eat() {
        System.out.println("动物吃东西");
    }
}
public class Cat extends Animal {
    public int age = 20;
    public int weight = 10;
    @Override
    public void eat() {
        System.out.println("猫吃鱼");
    }
    public void playGame() {
        System.out.println("猫捉迷藏");
    }
}
/*
    测试类
 */
public class AnimalDemo {
    public static void main(String[] args) {
        //有父类引用指向子类对象
        Animal a = new Cat();
        System.out.println(a.age);//40
        
//        System.out.println(a.weight);//报错,编译看左边,父类中没有此方法
        a.eat();//猫吃鱼
//        a.playGame();//报错,编译看左边,父类中没有此方法
    }
}

1.3 多态的好处和弊端

多态的最大的应用场景就是用在方法的参数上。
多态的好处:提高了程序的扩展性

  • 具体体现:定义方法的时候,使用父类型作为参数,将来在使用的时候,使用具体的子类型参与操作

多态的弊端:不能使用子类的特有功能(解决方法:向下转型)

public class Animal {
    public void eat() {
        System.out.println("动物吃东西");
    }
}
public class Cat extends Animal {
    @Override
    public void eat() {
        System.out.println("猫吃鱼");
    }
}
public class Dog extends Animal {
    @Override
    public void eat() {
        System.out.println("狗吃骨头");
    }
    public void lookDoor() {
        System.out.println("狗看门");
    }
}
public class Pig extends Animal {
    @Override
    public void eat() {
        System.out.println("猪吃白菜");
    }
}
/*
    动物操作类、工具类
 */
public class AnimalOperator {
    /*
    //参数只需要是Animal,使用多态
    public void useAnimal(Cat c) { //Cat c = new Cat();
        c.eat();
    }
    public void useAnimal(Dog d) { //Dog d = new Dog();
        d.eat();
    }
    */
    public void useAnimal(Animal a) {
        //Animal a = new Cat();
        //Animal a = new Dog();
        a.eat();//编译看左边,运行看右边
//        a.lookDoor();//不能使用子类的特有功能
    }  
}
/*
    测试类
 */
public class AnimalDemo {
    public static void main(String[] args) {
        //创建动物操作类的对象,调用方法
        AnimalOperator ao = new AnimalOperator();
        Cat c = new Cat();
        ao.useAnimal(c);
        Dog d = new Dog();
        ao.useAnimal(d);
        Pig p = new Pig();
        ao.useAnimal(p);
    }
}

1.4 多态中的转型

多态的弊端是不能访问子类的特有功能。而通过转型就可以访问子类特有功能了。

多态中的转型分为如下两种情况:

  • 向上转型
    • 从子到父
    • 父类引用指向子类对象
  • 向下转型
    • 从父到子
    • 父类引用转为子类对象

虽然我们通过向下转型解决了多态中的访问弊端,但是一般来说,我们使用多态的时候,主要还是使用父类中定义的通用功能。

public class Animal {
    public void eat() {
        System.out.println("动物吃东西");
    }
}
public class Cat extends Animal {
    @Override
    public void eat() {
        System.out.println("猫吃鱼");
    }
    public void playGame() {
        System.out.println("猫捉迷藏");
    }
}
/*
    向上转型
        从子到父
        父类引用指向子类对象

    向下转型
        从父到子
        父类引用转为子类对象
 */
public class AnimalDemo {
    public static void main(String[] args) {
        //多态
        Animal a = new Cat(); //向上转型
        a.eat();
//        a.playGame();//报错:多态中编译看左边,左边无playGame()

        /*
        //创建Cat类的对象
        Cat c = new Cat();
        c.eat();
        c.playGame();
        */

        //向下转型
        Cat c = (Cat)a;//类似强制类型转换
        c.eat();
        c.playGame();
    }
}

1.5 多态转型内存图解

在这里插入图片描述

最后,我们自己编写代码验证一下:

public class Animal {
    public void eat() {
        System.out.println("动物吃东西");
    }
}
public class Cat extends Animal {
    @Override
    public void eat() {
        System.out.println("猫吃鱼");
    }
    public void playGame() {
        System.out.println("猫捉迷藏");
    }

}
public class Dog extends Animal {
    @Override
    public void eat() {
        System.out.println("狗吃骨头");
    }
}
/*
    测试类
 */
public class AnimalDemo {
    public static void main(String[] args) {
        //向上转型
        Animal a = new Cat();
        a.eat();

        //向下转型
        Cat c = (Cat) a;
        c.eat();
        c.playGame();

        //向上转型
        a = new Dog();
        a.eat();

        //向下转型
        //ClassCastException 类型转换异常
//        Cat cc = (Cat) a;//指狗为猫不允许
//        cc.eat();
//        cc.playGame();

        //为了避免类型转换异常,在做向下转型的时候,一般我们会进行类型的判断。这里就用到了一个新的关键字:instanceof
        if (a instanceof Cat) {
            Cat cc = (Cat) a;
            cc.eat();
            cc.playGame();
        }
    }
}

instanceof关键字:会判断左边的对象是否是右边的类型,返回boolean类型

1.6 案例:猫和狗(多态版)

思路:
① 定义动物类(Animal)

  • 成员变量:姓名,年龄
  • 构造方法:无参,带参
  • 成员方法:get/set,吃(){}

② 定义猫类(Cat),继承动物类,重写吃的方法

  • 构造方法:无参,带参
  • 成员方法:吃(){}

③ 定义狗类(Dog),继承动物类,重写吃的方法

  • 构造方法:无参,带参
  • 成员方法:吃(){}

④ 定义测试类(AnimalDemo),写代码测试

public class Animal {
    private String name;
    private int age;
    public Animal() {
    }
    public Animal(String name, int age) {
        this.name = name;
        this.age = age;
    }
    public String getName() {
        return name;
    }
    public void setName(String name) {
        this.name = name;
    }
    public int getAge() {
        return age;
    }
    public void setAge(int age) {
        this.age = age;
    }
    public void eat() {
        System.out.println("动物吃东西");
    }
}
public class Cat extends Animal {
    public Cat() {
    }
    public Cat(String name, int age) {
        super(name, age);
    }
    @Override
    public void eat() {
        System.out.println("猫吃鱼");
    }
}
public class Dog extends Animal {
    public Dog() {
    }
    public Dog(String name, int age) {
        super(name, age);
    }
    @Override
    public void eat() {
        System.out.println("狗吃骨头");
    }
```java
/*
    测试类
 */
public class AnimalDemo {
    public static void main(String[] args) {
        //按照多态的方式创建对象并进行测试
        Animal a = new Cat();
        a.setName("加菲");
        a.setAge(5);
        System.out.println(a.getName() + "," + a.getAge());
        a.eat();

        a = new Cat("加菲", 5);
        System.out.println(a.getName() + "," + a.getAge());
        a.eat();

    }
}

创建狗类的对象进行测试留给大家自己

2:抽象类

2.1 抽象类概述

动物本身并不是一个具体的事物,而是一个抽象的事物。只有真正的猫,狗才是具体的动物。

在Java中,一个没有方法体的方法应该定义为抽象方法,而类中如果有抽象方法,该类必须定义为抽象类

2.2 抽象类特点

抽象类的特点:

  • 抽象类和抽象方法必须使用 abstract 关键字修饰
    • public abstract class 类名 {}
    • public abstract void eat();
  • 抽象类中不一定有抽象方法有抽象方法的类一定是抽象类
  • 抽象类自身不能实例化,参照多态的方式,通过子类对象实例化,这叫抽象类多态。
  • 抽象类的子类,要么重写抽象类中的所有抽象方法, 要么是抽象类。

1.抽象类中能不能有成员变量?能
2.抽象类中能不能有非抽象方法?能
3.抽象类中能不能有构造方法?能
4.抽象类能不能直接创建对象?不能
5.抽象类的子类一定要实现所有的抽象方法吗?不一定,因为还可以把自己也变为抽象类。

/*
    抽象类
 */
public abstract class Animal {
    //抽象方法
    public abstract void eat();
    public void sleep() {
        System.out.println("睡觉");
    }
}
public class Cat extends Animal {
    @Override
    public void eat() {//重写抽象方法
        System.out.println("猫吃鱼");
    }
}
public abstract class Dog extends Animal {//不重写所有抽象方法,变为抽象类
}
/*
    测试类
 */
public class AnimalDemo {
    public static void main(String[] args) {
//        Animal a = new Animal();
        Animal a = new Cat();
        a.eat();//猫吃鱼
        a.sleep();//睡觉
    }
}

2.3 抽象类的成员特点

抽象类的成员特点:

  • 成员变量
    • 可以是变量
    • 也可以是常量
  • 构造方法
    • 有构造方法,但是不能实例化
    • 那么,构造方法的作用是什么呢?用于子类访问父类数据的初始化
  • 成员方法
    • 可以有抽象方法:限定子类必须完成某些动作
    • 也可以有非抽象方法:提高代码复用性
/*
    抽象类
 */
public abstract class Animal {
    private int age = 20;
    private final String name = "动物";
    public Animal() {
    }
    public Animal(int age) {
        this.age = age;
    }
    public void show() {
        age = 40;
        System.out.println(age);
//        name = "老虎";
        System.out.println(name);
    }
    public abstract void eat();
}
public class Cat extends Animal {
    @Override
    public void eat() {
        System.out.println("猫吃鱼");
    }
}
/*
    测试类
 */
public class AnimalDemo {
    public static void main(String[] args) {
        Animal a = new Cat();
        a.eat();
        a.show();
    }
}

2.4 抽象类和非抽象类的区别

非抽象类所有的内容,抽象类都可以拥有。除此之外,抽象类还多了一个抽象方法。

抽象类不能直接创建对象,但是可以使用多态的写法创建对象。

如果一个抽象类中全部都是抽象方法,那么这个抽象类更应该定义为接口,可以更规范。

2.5 案例:猫和狗(抽象类版)

思路:

① 定义动物类(Animal)

  • 成员变量:姓名,年龄
  • 构造方法:无参,带参
  • 成员方法:get/set,吃();

② 定义猫类(Cat),继承动物类,重写吃的方法

  • 构造方法:无参,带参
  • 成员方法:吃(){…}

③ 定义狗类(Dog),继承动物类,重写吃的方法

  • 构造方法:无参,带参
  • 成员方法:吃(){…}

④ 定义测试类(AnimalDemo),写代码测试

有了思路之后,下面我们一起到IDEA中去实现一下:

public abstract class Animal {
    private String name;
    private int age;
    public Animal() {
    }
    public Animal(String name, int age) {
        this.name = name;
        this.age = age;
    }
    public String getName() {
        return name;
    }
    public void setName(String name) {
        this.name = name;
    }
    public int getAge() {
        return age;
    }
    public void setAge(int age) {
        this.age = age;
    }
    public abstract void eat();
}
public class Cat extends Animal {

    public Cat() {
    }
    public Cat(String name, int age) {
        super(name, age);
    }
    @Override
    public void eat() {
        System.out.println("猫吃鱼");
    }
}
public class Dog extends Animal {

    public Dog() {
    }
    public Dog(String name, int age) {
        super(name, age);
    }
    @Override
    public void eat() {
        System.out.println("狗吃骨头");
    }
}
/*
    测试类
 */
public class AnimalDemo {
    public static void main(String[] args) {
        //创建对象,按照多态的方式
        Animal a = new Cat();
        a.setName("加菲");
        a.setAge(5);
        System.out.println(a.getName()+","+a.getAge());
        a.eat();
        System.out.println("--------");

        a = new Cat("加菲",5);
        System.out.println(a.getName()+","+a.getAge());
        a.eat();
    }
}

3:接口

3.1 接口概述

在这里插入图片描述
左边这个是公牛的,右边这个是西门子的。为什么不同厂商生成的插线面板装到你家里,你都可以使用呢?原因很简单,因为这些面板是这些厂商遵循同样的规范生产的。
生活当中的,其实与计算机相关的接口也随处可见:
在这里插入图片描述
这些产品是由不同的厂商生产的,但是它们却都可以通过这个USB插口接到这个电脑上,这是为什么呢?原因很简单,因为它们参照的是同样的USB插口规范来实现的。无论是尺寸,厚度等都是有标准参数的。所以,虽然它们是不同的厂商生产的,但是却可以通过这个USB插口来使用。

总结:

  • 接口就是一种公共的规范标准,只要符合规范标准,大家都可以通用
  • Java中的接口更多的体现在对行为的抽象
  • 接口就是规范,我们可以使用接口来定义一些规范(比如要求某个方法的方法名必须叫什么,方法的参数列表必须是什么,方法的返回值类型必须是什么)

3.2 接口特点

接口的特点:

  • 接口用关键字interface修饰
    • public interface 接口名 {}
  • 类实现接口用implements表示
    • public class 类名 implements 接口名 {}
  • 接口不能实例化
    • 接口如何实例化呢?参照多态的方式,通过实现类对象实例化,这叫接口多态
    • 多态的形式:具体类多态,抽象类多态,接口多态
    • 多态的前提:有继承或者实现关系;有方法重写;有父(类/接口)引用指向(子/实现)类对象
  • 接口的实现类
    • 要么重写接口中的所有抽象方法
    • 要么是抽象类
  • 接口中必须全部都是抽象方法。抽象类中可以没有抽象方法,但是接口只能是抽象方法。
/*
    定义了一个接口
 */
public interface Inter {
    public abstract void show();
}

public class InterImpl implements Inter {
    @Override
    public void show() {
        System.out.println("show...");
    }
}
public abstract class InterImpl2 implements Inter{
}
/*
    测试类
 */
public class InterDemo {
    public static void main(String[] args) {
//        Inter i = new Inter();
        Inter i = new InterImpl();
        i.show();
    }
}

3.3 接口的成员特点

接口的成员特点:

  • 成员变量
    • 只能是常量
    • 默认修饰符:public static final
  • 构造方法
    • 没有,因为接口主要是扩展功能的,而没有具体存在
    • 一个类如果没有父类,默认继承自Object类
  • 成员方法
    • 只能是抽象方法
    • 默认修饰符:public abstract
    • 关于接口中的方法,JDK8和JDK9中有一些新特性,后面再讲解
public interface Inter {
    public int num = 10;
    public final int num2 = 20;
//    public static final int num3 = 30;
    int num3 = 30;//等价于上一行: public static final 可以省略,默认修饰符

//    public Inter() {} //接口没有构造方法
//    public void show() {}//报错:接口中的方法体必须是抽象的
    public abstract void method();
    void show();//默认修饰符有 public abstract 

}
//public class InterImpl implements Inter {
//下行与上行等价,如果一个类没有父类,默认父类为Object类
public class InterImpl extends Object implements Inter {
    public InterImpl() {
        super();
    }
    @Override
    public void method() {
        System.out.println("method");
    }
    @Override
    public void show() {
        System.out.println("show");
    }
}
/*
    测试类
 */
public class InterfaceDemo {
    public static void main(String[] args) {
        Inter i = new InterImpl();
//        i.num = 20;//报错:num是常量
        System.out.println(i.num);
//        i.num2 = 40;//报错:num2是常量
        System.out.println(i.num2);
        System.out.println(Inter.num);
    }
}

3.4 类和接口的关系

  • 类和类的关系
    • 继承关系(extends ),只能单继承,但是可以多层继承
  • 类和接口的关系
    • 实现关系(implements ),可以单实现,也可以多实现,还可以在继承一个类的同时实现多个接口
  • 接口和接口的关系
    • 继承关系(extends ),可以单继承,也可以多继承
public interface Inter1 {
}
public interface Inter2 {
}
public interface Inter3 extends Inter1,Inter2 {//接口的多继承
}
public class InterImpl extends Object implements Inter1,Inter2,Inter3 {//类的单继承和多实现
}

注意:实现类要重写所有抽象类和接口的抽象方法,若重名,重写靠前的1个即可。

public interface Inter1 {
	public abstract void show();
}
public interface Inter2 {
	public abstract void show();
}
public class InterImpl implements Inter2,Inter1 {
    @Override
    public void show() {  		 
    	//因为两个接口抽象方法一样,所以重写1个便可,谁在前重写谁,此时重写的Inter2     
    }
}

3.5 抽象类和接口的区别

  • 成员区别
    • 抽象类 变量,常量;有构造方法;有抽象方法,也有非抽象方法
    • 接口 常量;抽象方法
  • 关系区别
    • 类与类 继承,单继承
    • 类与接口 实现,可以单实现,也可以多实现
    • 接口与接口 继承,单继承,多继承
  • 设计理念区别
    • 抽象类 对类抽象,包括属性、行为
    • 接口 对行为抽象,主要是行为

抽象类是对一种事物的抽象,即对类抽象,而接口是对行为的抽象。
抽象类是对整个类整体进行抽象,包括属性、行为,但是接口却是对类局部(行为)进行抽象。


门和警报的例子
门:都有open()和close()两个动作,这个时候,我们可以分别使用抽象类和接口来定义这个抽象概念
在这里插入图片描述
随着时代的发展,我们的门具备了报警(alarm())的功能,又该如何实现呢?

这里我们给出两种思路:

第一种方案:将这三个功能都放在抽象类里面,但是这样一来所有继承于这个抽象类的子类都具备了报警功能,但是有的门并不一定具备报警功能,所以,这种设计不好

第二种方案:将这三个功能都放在接口里面,需要用到报警功能的类就需要实现这个接口中的open( )和close( ),也许这个类根本就不具备open( )和close( )这两个功能,比如火灾报警器。
在这里插入图片描述
由此可见,这两种设计都不好,那该如何设计呢?

我们一起来说一下:Door的open() 、close()和alarm()根本就属于两个不同范畴内的行为,open()和close()属于门本身固有的行为特性,而alarm()属于延伸的附加行为。

因此最好的解决办法是单独将报警设计为一个接口,包含alarm()行为,Door设计为单独的一个抽象类,包含open和close两种行为。再设计一个报警门继承Door类和实现Alarm接口。
在这里插入图片描述

3.6 案例:

乒乓球运动员和篮球运动员

需求:我们现在有乒乓球运动员和篮球运动员、乒乓球教练和篮球教练。为了出国交流,乒乓球相关的人员需要学习英语。
在这里插入图片描述

/* 学习接口 */
public interface Study {
    public abstract void study();
}
/* 教接口 */
public interface Teach {
    public abstract void teach();
}
/* 说英语接口 */
public interface SpeakEnglish {
    public abstract void english();
}
/* 人抽象类 */
public abstract class Person {
    private String name;
    private int age;
    public abstract void eat();
    public Person() {
    }
    public Person(String name, int age) {
        this.name = name;
        this.age = age;
    }
    public String getName() {
        return name;
    }
    public void setName(String name) {
        this.name = name;
    }
    public int getAge() {
        return age;
    }
    public void setAge(int age) {
        this.age = age;
    }
}
/* 乒乓运动员实现类 */
public class PingPangPlayer extends Person implements Study,SpeakEnglish {
    @Override
    public void eat() {
        System.out.println("乒乓球运动员吃大白菜,和小米粥");
    }
    @Override
    public void english() {
        System.out.println("乒乓球远动员说英语");
    }
    @Override
    public void study() {
        System.out.println("乒乓球远动员学习如何发球和接球");
    }
}
/* 乒乓教练实现类 */
public class PingPangCoach extends Person implements SpeakEnglish,Teach {
    @Override
    public void eat() {
        System.out.println("乒乓球教练吃小白菜,喝大米粥");
    }
    @Override
    public void english() {
        System.out.println("乒乓球教练说英语");
    }
    @Override
    public void teach() {
        System.out.println("乒乓球教练教如何发球和接球");
    }
}
/* 篮球运动员实现类 */
public class BasketballPlayer extends Person implements Study{
    @Override
    public void eat() {
        System.out.println("篮球运动员吃牛肉,和牛奶");
    }
    @Override
    public void study() {
        System.out.println("篮球运动员学习如何运球和投篮");
    }
}
/* 篮球教练实现类 */
public class BasketballCoach extends Person implements Teach {
    @Override
    public void eat() {
        System.out.println("篮球教练吃羊肉,喝羊奶");
    }
    @Override
    public void teach() {
        System.out.println("篮球教练教如何运球和投篮");
    }
}
/* 测试类 */
public class Test05 {
    public static void main(String[] args) {
        PingPangPlayer pingPangPlayer = new PingPangPlayer();
        pingPangPlayer.eat();
        pingPangPlayer.english();
        pingPangPlayer.study();

        BasketballCoach basketballCoach = new BasketballCoach();
        basketballCoach.eat();
        basketballCoach.teach();
    }
}
木门和电动报警门

需求:请采用面向对象的思想实现木门和电动报警门的案例,并在测试类中进行测试
在这里插入图片描述
分析:
①木门

  • 成员变量:宽,高,品牌
  • 成员方法:开门,关门
    ②电动报警门:
  • 成员变量:宽,高,品牌
  • 成员方法:开门,关门,报警
    思路:
    ①定义报警 (Alarm)接口
  • 成员方法:报警
    ②定义门 (Door)抽象类
  • 成员变量:宽,高,品牌
  • 构造方法:无参,带参
  • 成员方法:get/set方法,开门,关门
    ③定义木门类(WoodDoor),继承门类
  • 构造方法:无参,带参
  • 成员方法:开门,关门
    ④定义电动报警门类(ElectricAlarmDoor),继承门类,实现报警接口
  • 构造方法:无参,带参
  • 成员方法:开门,关门,报警
    ⑤定义测试类(DoorDemo),创建对象进行测试
/* 报警接口 */
public interface Alarm {
    void alarm();
}
/* 抽象门类 */
public abstract class Door {
    //宽
    private double width;
    //高
    private double height;
    //品牌
    private String brand;
    public Door() {
    }
    public Door(double width, double height, String brand) {
        this.width = width;
        this.height = height;
        this.brand = brand;
    }
    public double getWidth() {
        return width;
    }
    public void setWidth(double width) {
        this.width = width;
    }
    public double getHeight() {
        return height;
    }
    public void setHeight(double height) {
        this.height = height;
    }
    public String getBrand() {
        return brand;
    }
    public void setBrand(String brand) {
        this.brand = brand;
    }
    //开门
    public abstract void open();
    //关门
    public abstract void close();
}
/* 木门实现类 */
public class WoodDoor extends Door {
    public WoodDoor() {
    }
    public WoodDoor(double width, double height, String brand) {
        super(width, height, brand);
    }
    @Override
    public void open() {
        System.out.println("手动开门");
    }
    @Override
    public void close() {
        System.out.println("手动关门");
    }
}
/* 电动报警门实现类 */
public class ElectricAlarmDoor extends Door implements Alarm {
    public ElectricAlarmDoor() {
    }
    public ElectricAlarmDoor(double width, double height, String brand) {
        super(width, height, brand);
    }
    @Override
    public void open() {
        System.out.println("自动开门");
    }
    @Override
    public void close() {
        System.out.println("自动关门");
    }
    @Override
    public void alarm() {
        System.out.println("具有报警功能");
    }
}
/* 测试类 */
public class DoorDemo {
    public static void main(String[] args) {
        //木门
        WoodDoor wd = new WoodDoor();
        wd.open();
        wd.close();
//        wd.alarm();//报错:木门没有报警功能
        System.out.println("--------");
        //电动报警门
        ElectricAlarmDoor ed = new ElectricAlarmDoor();
        ed.open();
        ed.close();
        ed.alarm();
        System.out.println("--------");
        //多态用法
        Door d = new WoodDoor();
        d.open();
        d.close();
        System.out.println("--------");
        d = new ElectricAlarmDoor();
        d.open();
        d.close();
//        d.alarm();//报错:抽象类门没有报警功能
        System.out.println("--------");
        Alarm a = new ElectricAlarmDoor();//接口多态
//        a.open();//报错:接口没有开门
//        a.close();//报错:接口没有关门
        a.alarm();
    }
}

3.7 接口新增的方法

接口组成:

  • 常量
    • public static final
  • 抽象方法
    • public abstract
  • 默认方法(Java 8):如果实现该接口的类不显示地提供该方法的具体实现,就会从接口中默认继承该默认方法
  • 静态方法(Java 8)
  • 私有方法(Java 9)

看到这,先给大家强调一下,这里新增的3类方法我们自己在开发中很少使用,通常是Java源码中涉及到,对我们来说,能够识别语法,知道调用关系即可。


接口中默认方法的定义格式:

  • 格式:public default 返回值类型 方法名(参数列表) { }
  • 范例:public default void show1() { }

接口中默认方法的注意事项:

  • public可以省略,default不能省略

接口中静态方法的定义格式:

  • 格式:public static 返回值类型 方法名(参数列表) { }
  • 范例:public static void show2() { }

接口中静态方法的注意事项:

  • 静态方法只能通过接口名调用,不能通过实现类名或者对象名调用
  • public可以省略,static不能省略

接口中私有方法的定义格式:

  • 格式1:private 返回值类型 方法名(参数列表) { }
  • 范例1:private void show3() { }
  • 格式2:private static 返回值类型 方法名(参数列表) { }
  • 范例2:private static void show4() { }

接口中私有方法的注意事项:

  • 默认方法可以调用私有的静态方法和非静态方法
  • 静态方法只能调用私有的静态方法

public interface Inter {
//    public default void show1() {
//        System.out.println("默认方法被调用");
//    }
    default void show1() {//跟上行一样,public可以省略
        System.out.println("默认方法被调用");
        show3();
        show4();
    }
//    public static void show2() {
//        System.out.println("静态方法被调用");
//    }
    static void show2() {//public可以省略
        System.out.println("静态方法被调用");
//        show3();//报错:静态方法只能调用私有的静态方法
        show4();
    }
    private void show3() {
        System.out.println("私有方法");
    }
    private static void show4() {
        System.out.println("静态私有方法");
    }
}
public class InterImpl implements Inter {
}
/*
    测试类
 */
public class InterDemo {
    public static void main(String[] args) {
        Inter i = new InterImpl();
        i.show1();
//        i.show2();//静态方法不能通过实现类名调用
//        InterImpl.show2();//静态方法不能通过对象名调用
        Inter.show2();
    }
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值