首页 > 基础资料 博客日记

Java之接口详解【一篇搞定】

2024-09-17 21:00:07基础资料围观105

文章Java之接口详解【一篇搞定】分享给大家,欢迎收藏Java资料网,专注分享技术知识

interface

引用数据类型:类、数组、接口

1 接口概述

接口是对Java单继承的补充。Java只支持单继承(亲爹唯一),如果在开发过程中想额外增强类的功能,可以借助接口实现(可以拜师,拜多个师傅也可以)。

接口是Java中一种重要的抽象机制,它提供了一种定义行为规范和实现多态性的方式。通过合理使用接口,可以提高代码的可扩展性、可维护性和灵活性。

接口是除了类和数组之外,另外一种引用数据类型,需要使用 interface 关键字来定义,接口最终也会被编译成.class文件,但一定要明确接口并不是类,而是另外一种引用数据类型。

接口基础定义格式:

[修饰符] interface 接口名 {
    //数据成员,可以定义多个
    [public static final] 数据类型 数据成员 =;

    //抽象方法:可以定义多个
    [public abstract] 返回值类型 方法名(形参列表);
}

案例如下:

package com.briup.chap07.test;

//使用interface关键字来定义接口
interface IAction {
	//数据成员,下面2行效果一样
	//public static final int NUM = 10;
	int NUM = 10;

	//成员方法,下面2行效果一样
	//public abstract void start();
	void start();

	public abstract void end();
}

public class Test021_Basic {
	public static void main(String[] args) {
		//接口不可以实例化对象
        //IAction ac = new IAction(); error
        
        System.out.println(IAction.NUM);
        
        //接口中数据成员默认 public static final,故而下行编译报错
        //IAction.NUM = 20;
	}
}

注意1, 定义类使用关键字class,定义接口使用关键字interface

注意2,接口中的数据成员,默认public static final修饰,是常量,名称全大写(符合命名规范)

注意3,接口中的方法,默认public abstract修饰,是抽象方法

补充内容(后面章节具体讨论):

  • JDK8中,还允许在接口中编写静态方法默认方法

  • JDK9中,还允许在接口中编写私有方法

2 接口实现

Java中类和类之间的关系是继承,且只能是单继承

类和接口是实现关系,通过implements关键字表示,可以是单实现,也可以是多实现

子类还可以在继承一个父类的同时实现多个接口

接口的实现类书写格式:

//一个类可以同时实现多个接口
[修饰符] class 类名 implements 接口名1,接口名2,... {
	重写所有抽象方法
}

注意事项:

  • 接口属于引用数据类型的一种,它不是类,它没有构造方法
  • 接口的实现类(子类),可以是正常类(重写所有抽象方法),也可以是抽象类(包含抽象方法)
  • 接口不能创建对象,一般用接口引用指向实现类对象
  • 相同接口的多个实现类,体现的是like a的关系

基础案例:

​ 实现类实现单个接口案例。

​ 定义IAction的实现类,重写所有抽象方法,最后进行功能测试。

package com.briup.chap07.test;

interface IAction {
	int NUM = 10;

	void start();

	public abstract void end();
}

//定义接口的实现类
class ActionImpl implements IAction {
	@Override
	public void start() {
		System.out.println("start开始执行 ");
	}

	@Override
	public void end() {
		System.out.println("执行完成,end结束");
	}
}

public class Test021_Basic {
	public static void main(String[] args) {
		//1.接口不能实例化对象,下面一行编译报错
		//IAction ic = new IAction();
		
		//2.接口引用 指向实现类对象
		IAction ac = new ActionImpl();
		
		//3.接口数据成员访问测试
		System.out.println(IAction.NUM);
		System.out.println(ac.NUM);
		
		System.out.println("-------------");
		
		//4.通过接口引用 调用 重写方法(多态体现)
		ac.start();
		ac.end();
	}
}

注意事项:

​ 在类和接口的实现关系中,可以使用多态 ,因为类和接口的实现关系,可理解为继承的一种形式。

一个类可以同时实现多个接口 ,但需要把多个接口的抽象方法全部重写(后面案例中具体演示)。

3 接口继承

Java中,类和类之间是单继承关系,接口和接口之间是多继承

接口继承格式:

[修饰符] interface 子接口 extends 父接口1,父接口2... {
    //新增成员或抽象方法
}

例如:

interface Runable {
	void run();	
}

interface Flyable {
	void fly();
}

//接口多继承
interface Action extends Runable,Flyable {
	void sing();
}

4 综合案例

案例描述:

​ 定义一个抽象父类Animal2,再定义两个接口IJumpAble跳火圈、ICycleAble骑自行车,最后定义一个猴子类Monkey,去继承Animal2,同时实现IJumpAble、ICycleAble,进行功能测试。

复杂实现类定义格式:

[修饰符] class 实现类 extends 父类 implements 接口名1, 接口名2, ... {  
    重写所有方法; 
}

案例描述:

package com.briup.chap07.test;

//定义抽象父类
abstract class Animal2 {
	private String color;
	private int age;

	public Animal2() {}
	public Animal2(String color, int age) {
		this.color = color;
		this.age = age;
	}

	// 抽象方法
	public abstract void eat();
	public abstract void sleep();
}

//定义跳火圈接口
interface IJumpAble {
    //默认修饰符为:public abstract
	void jump();
}

//定义骑自行车接口 
interface ICycleAble {
	public abstract void cycle();
}

// 定义猴子类: 继承Animal类,同时实现ICycleAble、IJumpAble接口
class Monkey extends Animal2 implements ICycleAble, IJumpAble {
	private String name;

    //自定义构造方法
	public Monkey() {}
    
	public Monkey(String color, int age, String name) {
		super(color, age);
		this.name = name;
	}

	//重写从父类继承的方法
	@Override
	public void eat() {
		System.out.println("猴子" + name + " 喜欢吃大桃子");
	}
	@Override
	public void sleep() {
		System.out.println("猴子" + name + " 喜欢在树上睡觉");
	}

	// 重写从接口获取的抽象方法
	@Override
	public void cycle() {
		System.out.println("猴子 " + name + " 能够骑自行车");
	}
	@Override
	public void jump() {
		System.out.println(name + " 能够跳火圈");
	}
}

//测试类
public class Test024_Monkey {
	// 基本测试
	public static void main(String[] args) {
        //1.抽象类不能实例化对象,但可以定义引用指向子类对象
		Animal2 a = new Monkey("yellow", 2, "小悟空");

        //2.借助抽象类引用,只能访问抽象类中具有的方法
		a.eat();
		a.sleep();
        
        //下面两行编译报错【多态:编译看左边,运行看右边】
        //a.jump();
        //a.cycle();
		
        System.out.println("****************");

		//3.用接口引用指向实现类对象
		ICycleAble c = new Monkey("yellow", 5, "马戏团小猴");
		
        //4.借助接口引用调用接口中重写方法
		c.cycle();
        
        //注意:接口引用类型 只能调用 接口中具备的方法【多态:编译看左边,运行看右边】
		//下面三行编译报错
        //c.eat(); 	error
		//c.sleep(); 	error
        //c.jump();		error
        
        System.out.println("****************");
        
        //5.如果想要调用父类方法或其他接口方法,可以借助类型转换实现
        //注意,一定要借助instanceof额外判断引用指向对象的类型
		if (c instanceof Monkey) {
			Monkey m = (Monkey) c;
			m.eat();
			m.sleep();
		}
        
        System.out.println("****************");
        
		if (c instanceof IJumpAble) {
			IJumpAble j = (IJumpAble) c;
			j.jump();
		}
	}
}

运行效果:

注意事项:

​ **接口多态应用时,编译看左边,运行看右边 **

​ **即接口引用只能调用接口中包含的方法,成功调用的是重写以后的方法 **

5 类接口关系

  • 类与类的关系

    继承关系,只能单继承,但是可以多层继承

  • 类与接口的关系

    实现关系,可以单实现,也可以多实现,还可以在继承一个类的同时实现多个接口

  • 接口与接口的关系

    继承关系,可以单继承,也可以多继承

2.6 接口新特性

1)JDK8新特性:接口可以包含静态方法和默认方法

案例如下:

package com.briup.chap07.test;

//JDK8中接口 可以添加默认方法和static方法
interface JDK8Action {
	// 接口中静态常量
	String OPS_MODE = "auto";

	// 接口中抽象方法
	void start();
	void stop();
  
    //下面是JDK8新特性
	//默认方法
	public default void dFun() {
		System.out.println("in default fun() ...");
	}
  
	//静态方法
	public static void sFun() {
		System.out.println("in static fun() ...");
	}
}

class Demo01 implements JDK8Action {
	@Override
	public void start() {
		System.out.println("重写start() ...");
	}
	@Override
	public void stop() {
		System.out.println("重写stop() ...");
	}
}

public class Test026_JDK8 {
	public static void main(String[] args) {
		//1.接口引用指向实现类对象
		JDK8Action a = new Demo01();
		
		//2.调用实现类重写方法
		a.start();
		a.stop();
		
		//3.调用default方法
		a.dFun();
		
		//4.JDK8中接口可以定义static方法,只能通过接口名调用,但不能通过接口引用调用,也不能通过实现类名调用
		//a.sFun();	编译报错
        //Demo01.sFun(); 编译报错
		JDK8Action.sFun();
	}
}

注意事项:JDK8接口可以定义static方法,只能通过接口名调用

2)JDK9新特性:接口可以包含私有方法

案例如下:

package com.briup.chap07.test;

//使用interface关键字来定义接口
interface JDK9Action {
	// 接口中的静态常量
	String OPS_MODE = "auto";

	// 接口中的抽象方法
	void start();
	
    //私有方法 jdk9以下报错
	private void run() {
    	System.out.println("private run() ...");
    }
}

class Demo02 implements JDK8Action {
	@Override
	public void start() {
		System.out.println("重写start() ...");
	}
}

//测试类
public class Test026_JDK9 {
	public static void main(String[] args) {
    	//1.接口引用指向实现类对象
		JDK9Action a = new Demo02();
        
        //2.调用实现类重写的抽象方法
        a.start();
        
        //3.调用接口private方法
        a.run();
    }
}

注意:测试上述案例需要用合适的JDK版本

7 常见面试题

接口和抽象类有什么区别?如何选择?

语法上两者区别:

  1. 定义方式:抽象类通过使用 abstract 关键字来定义,而接口使用 interface 关键字来定义
  2. 数据成员:抽象类可以包含普通数据成员和static数据成员,而接口只能包含 static final 修饰的数据成员
  3. 成员方法:抽象类可以包含具体的方法实现,而接口只能包含抽象方法,即没有方法体的方法声明
  4. 构造函数:抽象类可以有构造函数,而接口不能有构造函数
  5. 实现方式:一个类可以继承(extends)一个抽象类,而一个类可以实现(implements)多个接口
  6. 多继承:Java不支持多继承,一个类只能继承一个抽象类,但可以实现多个接口

设计理念区别:

  • 同一个接口的不同的实现类之间,体现的是 like a 的关系 ,接口更加强调行为规范的定义,适用于多个类具有相同行为规范的情况。

    例如:飞机具备飞翔的行为,鸟也具备飞翔的行为,此时我们就可以定义接口包含抽象方法fly(),然后让飞机和鸟分别去实现该接口。飞机 like a 鸟,因为它们都会fly()。

  • 子类和抽象父类体现的是 is a 的关系 ,抽象类归根到底还是类,它比较特殊,不能被实例化,只能被继承。抽象类用于定义一种通用的模板或者规范,其中可包含了一些具体数据成员、方法实现和抽象方法声明。

    例如:前面案例中的形状类Shape,它里面包含方法getArea(),但该方法功能不确定,所以定义成抽象方法,而包含了抽象方法的类Shape也必须被声明为抽象类。定义子类圆形类,其getArea()方法功能是明确的,则子类中重写方法。

结论:

  • 如果仅仅要额外扩展已存在类的功能,则选择定义接口,让类去实现接口;
  • 如果需要创建一组相关的类,且这些类之间有一些共同的行为和属性,那么可以定义一个类作为这些类的父类。如果不想实例化父类对象,则可以把这个父类设置为抽象类。

文章来源:https://blog.csdn.net/u012135697/article/details/140491707
本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:jacktools123@163.com进行投诉反馈,一经查实,立即删除!

标签:

相关文章

本站推荐

标签云