interface关键字

47 篇文章 1 订阅

b站学习视频以及笔记-尚硅谷_Java零基础教程

java入门必备-适合初学者的全套完整版教程(宋红康主讲)

interface关键字:接口

一. 接口概述:

一方面,有时必须从几个类中派生出一个子类,继承它们所有的属性和方 法。

但是,Java不支持多重继承。有了接口,就可以得到多重继承的效果。

另一方面,有时必须从几个类中抽取出一些共同的行为特征,而它们之间又 没有is-a的关系,仅仅是具有相同的行为特征而已。例如:鼠标、键盘、打 印机、扫描仪、摄像头、充电器、MP3机、手机、数码相机、移动硬盘等都 支持USB连接。

接口就是规范,定义的是一组规则,体现了现实世界中“如果你是/要…则 必须能…”的思想。继承是一个"是不是"的关系,而接口实现则是 “能不能” 的关系。 接口的本质是契约,标准,规范,就像我们的法律一样。制定好后大家都 要遵守。

image-20201113163517531

image-20201113165502468

定义Java类的语法格式:先写extends,后写implements

class SubClass extends SuperClass implements InterfaceA{ }

一个类可以实现多个接口,接口也可以继承其它接口。

实现接口的类中必须提供接口中所有方法的具体实现内容,方可实 例化。否则,仍为抽象类。

接口的主要用途就是被实现类实现。(面向接口编程)

与继承关系类似,接口与实现类之间存在多态性

接口和类是并列关系,或者可以理解为一种特殊的类。

从本质上讲, 接口是一种特殊的抽象类,这种抽象类中只包含常量和方法的定义 (JDK7.0及之前),而没有变量和方法的实现。

二. 接口使用说明:

1. 接口使用interface来定义

2. Java中,接口和类是并列的两个结构

3. 如何定义接口:定义接口中的成员

​ 3.1 JDK7及以前:只能定义全局常量和抽象方法

​ 全局常量:public static final的.但是书写时,可以省略不写

​ 抽象方法:public abstract的

​ 3.2 JDK8:除了定义全局常量和抽象方法之外,还可以定义静态方法、默认方法

4. 接口中不能定义构造器的!意味着接口不可以实例化

5. Java开发中,接口通过让类去实现(implements)的方式来使用.

如果实现类覆盖了接口中的所抽象方法,则此实现类就可以实例化

如果实现类没覆盖接口中所的抽象方法,则此实现类仍为一个抽象类

interface Flyable{

    //全局常量
    public static final int MAX_SPEED = 7900;//第一宇宙速度
    int MIN_SPEED = 1;//省略了public static final

    //抽象方法
    public abstract void fly();
    //省略了public abstract
    void stop();


    //Interfaces cannot have constructors
    //	public Flyable(){
    //		
    //	}
}

interface Attackable{

    void attack();

}

class Plane implements Flyable{

    @Override
    public void fly() {
        System.out.println("通过引擎起飞");
    }

    @Override
    public void stop() {
        System.out.println("驾驶员减速停止");
    }

}

abstract class Kite implements Flyable{

    @Override
    public void fly() {

    }

}

class Bullet extends Object implements Flyable,Attackable,CC{

    @Override
    public void attack() {
        // TODO Auto-generated method stub

    }

    @Override
    public void fly() {
        // TODO Auto-generated method stub

    }

    @Override
    public void stop() {
        // TODO Auto-generated method stub

    }

    @Override
    public void method1() {
        // TODO Auto-generated method stub

    }

    @Override
    public void method2() {
        // TODO Auto-generated method stub

    }

}

6. Java类可以实现多个接口 —>弥补了Java单继承性的局限性

格式:class AA extends BB implements CC,DD,EE

7. 接口与接口之间可以继承,而且可以多继承


interface AA{
    void method1();
}
interface BB{

    void method2();
}

interface CC extends AA,BB{

}

8. 接口的具体使用,体现多态性

9. 接口,实际上可以看做是一种规范

三. 举例:

image-20201113200519027

public class USBTest {
    public static void main(String[] args) {

        Computer com = new Computer();
        //1.创建了接口的非匿名实现类的非匿名对象
        Flash flash = new Flash();
        com.transferData(flash);

        //2. 创建了接口的非匿名实现类的匿名对象
        com.transferData(new Printer());

        //3. 创建了接口的匿名实现类的非匿名对象
        USB phone = new USB(){

            @Override
            public void start() {
                System.out.println("手机开始工作");
            }

            @Override
            public void stop() {
                System.out.println("手机结束工作");
            }

        };
        com.transferData(phone);


        //4. 创建了接口的匿名实现类的匿名对象

        com.transferData(new USB(){
            @Override
            public void start() {
                System.out.println("mp3开始工作");
            }

            @Override
            public void stop() {
                System.out.println("mp3结束工作");
            }
        });
    }
}

class Computer{

    public void transferData(USB usb){//USB usb = new Flash();
        usb.start();

        System.out.println("具体传输数据的细节");

        usb.stop();
    }


}

interface USB{
    //常量:定义了长、宽、最大最小的传输速度等

    void start();

    void stop();

}

class Flash implements USB{

    @Override
    public void start() {
        System.out.println("U盘开启工作");
    }

    @Override
    public void stop() {
        System.out.println("U盘结束工作");
    }

}

class Printer implements USB{
    @Override
    public void start() {
        System.out.println("打印机开启工作");
    }

    @Override
    public void stop() {
        System.out.println("打印机结束工作");
    }

}

结果:

image-20201113200025837

体会:

  • 接口使用上也满足多态性
  • 接口,实际上就是定义了一种规范
  • 开发中,体会面向接口编程!

四. 体会面向接口编程的思想

image-20201113200534282

面向接口编程:我们在应用程序中,调用的结构都是JDBC中定义的接口,不会出现具体某一个
数据库厂商的API。

五. 练习

定义一个接口用来实现两个对象的比较。

Interface CompareObject{ 
    public int compareTo(Object o); 
    //若返回值是 0 , 代表相等; 若为正数,代表当 前对象大;负数代表当前对象小 
} 
定义一个Circle类,声明redius属性,提供getter和setter方法
定义一个ComparableCircle类,继承Circle类并且实现CompareObject接口。
在 ComparableCircle类中给出接口中方法compareTo的实现体,用来比较两个圆的半径大小。
定义一个测试类InterfaceTest,创建两个ComparableCircle对象,调用compareTo 方法比较两个类的半径大小。
public class InterfaceTest {

    /**  
	 * @MethodName: main
	 * @Description: TODO
	 * @author Tao
	 * @param args void
	 * @date 2020年11月13日 
	 */

    public static void main(String[] args) {
        // TODO Auto-generated method stub
        ComparableCircle c1 = new ComparableCircle(2.3);
        ComparableCircle c2 = new ComparableCircle(2.2);
        int value = c1.compareTo(c2);
        System.out.println(value);//1
        int value1 = c1.compareTo("哈哈");
        System.out.println(value1);//报异常,是我自己写的异常处理,传入的数值不匹配。
    }

}

interface CompareObject{
    public int compareTo(Object o); 
    //若返回值是 0 , 代表相等; 若为正数,代表当前对象大;负数代表当前对象小
}

class Circle {
    private Double radius;



    /**  
	 * @Constructor: Circle
	 * @Description: Circle构造函数
	 * @author Tao
	 * @date 2020年11月13日 
	 */ 

    public Circle(Double radius) {
        super();
        this.radius = radius;
    }

    public Double getRadius() {
        return radius;
    }

    public void setRadius(Double radius) {
        this.radius = radius;
    }

}

class ComparableCircle extends Circle implements CompareObject{


    /**  
	 * @Constructor: ComparableCircle
	 * @Description: ComparableCircle构造函数
	 * @author Tao
	 * @date 2020年11月13日 
	 */ 

    public ComparableCircle(double radius) {
        super(radius);
        // TODO Auto-generated constructor stub
    }

    /**  
	 * @MethodName: compareTo
	 * @Description: TODO
	 * @author Tao
	 * @param o
	 * @return
	 * @see com.jiekou.cn.CompareObject#compareTo(java.lang.Object)
	 * @date 2020年11月13日 
	 */  


    @Override
    public int compareTo(Object o) {
        if (this == o){
            return 0;
        }if(o instanceof ComparableCircle){
            ComparableCircle cle = (ComparableCircle) o;
            //			错误方法,当2.5-2.3时,强制转换损失精度成为0,本该返回1,却返回0
            //			return (int)(this.getRadius()-cle.getRadius());
            //正确方式一:
            //			if (this.getRadius()-cle.getRadius()== 0) {
            //				return 0;	
            //			}else
            //			return this.getRadius()-cle.getRadius()>0? 1:-1;
            //正确方式二:将circle类中radius属性改为包装类,可以调用包装类的方法compareTo()
            return this.getRadius().compareTo(cle.getRadius());

        }else {
            //			return 0;
            throw new RuntimeException("传入的数据类型不匹配");
        }
    }

}

六. 笔试题

interface A {
    int x = 0;
    int x2 = 3;
}

class B {
    int x = 1;
    int x3 = 4;
}

class C extends B implements A {
    public void pX() {
        //编译不通过。因为x是不明确的
        // System.out.println(x);
        System.out.println(super.x);//1,调用父类的x
        System.out.println(A.x);//0,调用接口的x
        System.out.println(x2);//3,接口
        System.out.println(x3);//4,父类

    }

    public static void main(String[] args) {
        new C().pX();
    }
}



public class JieKouTest {
    public static void main(String[] args) {
        Ball ball = new Ball("haha");
        ball.play();//PingPang
    }

}

interface Playable {
    void play();
}

interface Bounceable {
    void play();
}

interface Rollable extends Playable, Bounceable {
    Ball ball = new Ball("PingPang");
}

class Ball implements Rollable {
    private String name;

    public String getName() {
        return name;
    }

    public Ball(String name) {
        this.name = name;
    }

    public void play() {
        //	ball = new Ball("Football");编译出错,因为Rollable接口中ball是一个静态常量(static final),是不能再修改的
        System.out.println(ball.getName());
    }
}

七. Java8中关于接口的新规范

Java 8中,你可以为接口添加静态方法默认方法。从技术角度来说,这是完全合法的,只是它看起来违反了接口作为一个抽象定义的理念。

静态方法: 使用 static 关键字修饰。可以通过接口直接调用静态方法,并执行 其方法体。我们经常在相互一起使

用的类中使用静态方法。你可以在标准库中 找到像Collection/Collections或者Path/Paths这样成对的接口和类。

默认方法: 默认方法使用 default 关键字修饰。可以通过实现类对象来调用。 我们在已有的接口中提供新方法的

同时,还保持了与旧版本代码的兼容性。 比如:java 8 API中对Collection、List、Comparator等接口提供了丰富的默认方法。

/*
 * JDK8:除了定义全局常量和抽象方法之外,还可以定义静态方法、默认方法
 */
public interface CompareA {

    //静态方法
    public static void method1(){
        System.out.println("CompareA:北京");
    }
    //默认方法
    public default void method2(){
        System.out.println("CompareA:上海");
    }

    default void method3(){
        System.out.println("CompareA:湖北");
    }
}

public interface CompareB {
	
	default void method3(){
		System.out.println("CompareB:上海");
	}
	
}

public class SuperClass {
	
	public void method3(){
		System.out.println("SuperClass:咸宁");
	}
	
}



class SubClass extends SuperClass implements CompareA,CompareB{
	
    //重写
	public void method2(){
		System.out.println("SubClass:上海");
	}
	
	public void method3(){
		System.out.println("SubClass:深圳");
	}
	
	//知识点5:如何在子类(或实现类)的方法中调用父类、接口中被重写的方法
	public void myMethod(){
		method3();//调用自己定义的重写的方法
		super.method3();//调用的是父类中声明的
		//调用接口中的默认方法
		CompareA.super.method3();
		CompareB.super.method3();
	}
}

public class SubClassTest {
	
	public static void main(String[] args) {
		SubClass s = new SubClass();
		
//		s.method1();报错
//		SubClass.method1();
		//知识点1:接口中定义的静态方法,只能通过接口来调用。
		CompareA.method1();//CompareA:北京
		//知识点2:通过实现类的对象,可以调用接口中的默认方法。
		//如果实现类重写了接口中的默认方法,调用时,仍然调用的是重写以后的方法
		s.method2();//SubClass:上海
		//知识点3:如果子类(或实现类)继承的父类和实现的接口中声明了同名同参数的默认方法,
		//那么子类在没有重写此方法的情况下,默认调用的是父类中的同名同参数的方法。-->类优先原则
		//知识点4:如果实现类实现了多个接口,而这多个接口中定义了同名同参数的默认方法,
		//那么在实现类没有重写此方法的情况下,报错。-->接口冲突。
		//这就需要我们必须在实现类中重写此方法
		s.method3();//SubClass:深圳
		
	}
	
}


  • 知识点1:接口中定义的静态方法,只能通过接口来调用。

  • 知识点2:通过实现类的对象,可以调用接口中的默认方法。如果实现类重写了接口中的默认方法,调用时,仍然调用的是重写以后的方法

  • 知识点3:如果子类(或实现类)继承的父类和实现的接口中声明了同名同参数的默认方法,那么子类在没重写此方法的情况下,默认调用的是父类中的同名同参数的方法。–>类优先原则

  • 知识点4:如果实现类实现了多个接口,而这多个接口中定义了同名同参数的默认方法,那么在实现类没重写此方法的情况下,报错。–>接口冲突。这就需要我们必须在实现类中重写此方法

  • 知识点5:如何在子类(或实现类)的方法中调用父类、接口中被重写的方法

    public void myMethod(){
        method3();//调用自己定义的重写的方法
        super.method3();//调用的是父类中声明的
        //调用接口中的默认方法
        CompareA.super.method3();
        CompareB.super.method3();
    }
    
    
    interface Filial {// 孝顺的
    	default void help() {
    		System.out.println("老妈,我来救你了");
    	}
    }
    
    interface Spoony {// 痴情的
    	default void help() {
    		System.out.println("媳妇,别怕,我来了");
    	}
    }
    
    class Father{
    	public void help(){
    		System.out.println("儿子,救我媳妇!");
    	}
    }
    
    class Man extends Father implements Filial, Spoony {
    
    	public static void main(String[] args) {
            //方法二:继承父类同名方法
    		new Man().help();//儿子,救我媳妇!
    	}
    //	@Override方法一:重写
    //	public void help() {
    //		System.out.println("我该就谁呢?");
    //		Filial.super.help();//老妈,我来救你了
    //		Spoony.super.help();//儿子,救我媳妇!
    //	}
    	
    }
    
    

八. 面试题:

抽象类和接口的异同?

image-20201114004549951

相同点:不能实例化;都可以包含抽象方法的。
不同点:
1)把抽象类和接口(java7,java8,java9)的定义、内部结构解释说明
2)类:单继承性 接口:多继承
类与接口:多实现

  • 1
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值