Java基础知识回顾之接口

本文深入解析Java接口的概念,探讨其在程序设计中的作用,包括降低模块间耦合度、提升系统可扩展性和可维护性。文章详细阐述接口的定义、使用原则及其实现方式,包括多接口继承和抽象类继承接口的情况。

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

简介

如果一个类之中只是由抽象方法和全局常量所组成的,那么在这种情况下会将其定义为一个抽象类(因为抽象类中含有构造方法),而只会定义为接口,所以所谓的接口严格来讲就属于一个特殊的类,而且这个类中只有抽象方法与全局常量(是没有构造方法的)。

要定义一个接口使用 interface 关键字完成。

接口的重要性

Java 接口体现的是一种规范和分离的程序设计原则,充分利用接口可以降低程序各个模块之间的耦合度,从而提高系统的可扩展性和可维护性。包括我们现在最火的 Spring 框架都是“面向接口”编程。

按照组件的开发模型(3C),面向对象、面向过程和接口各司一面,缺一不可。具体如下:

  • 面向对象是指在考虑问题时,以对象为单位,考虑它的属性以及方法。
  • 面向过程是指在考虑问题时,以一个具体的流程(事务过程)为单位来考虑它的实现
  • 接口设计与非接口设是针对复用技术而言,它与面对对象(过程)并不是同一个问题。

接口的定义

接口的定义语法

public interface 接口名 {
	常量
	抽象方法
}

接口定义的实例

interface A {
	public static final String MSG = "Hello";	// 全局常量
	public abstract void print();	// 抽象方法
}

相关说明如下:

  • public : 接口的修饰符只能是 public。 只有这样,接口才能被任何包中的接口或类访问。
  • interface:接口的关键字。声明接口必须要使用此关键字。
  • 常量:接口中不能声明变量,因为接口需要具备三个特征,即公共性、静态性和最终性。
  • 方法:必须是 public abstract 修饰的。

接口的使用

由于接口里面存在有抽象方法,所有接口对象不能使用关键字 new 来实例化操作。
接口的使用原则如下:

  • 接口必须要有子类,但是此时一个子类可以使用 implements 关键字实现多个接口;
  • 接口的子类(如果不是抽象类),必须要覆写接口中的全部抽象方法。
  • 接口的对象可以利用子类对象的向上转型来进行实例化操作。

代码实例

接口的子类使用 implements 实现多个接口,以及向上转型的示例

interface A{	// 定义一个接口
	public abstract void print();	// 接口的抽象方法
}

interface B{	// 定义一个接口
	public abstract void get();		// 接口的抽象方法
}

class X implements A, B{

	@Override
	public void get() {
		System.out.println("B接口的中的 get方法");
	}

	@Override
	public void print() {
		System.out.println("A接口的中的 print方法");
	}
	
}

public class TestDemo {
	public static void main(String[] args) {
		X x = new X();
		x.get();		// B接口的中的 get方法
		x.print();		// A接口的中的 print方法
		
		// 向上转型
		A a = x;
		B b = x;
		
		a.print();	//  A接口的中的 print方法
		b.get();	//  B接口的中的 get方法
	}
}

基于上面的代码,看一个问题:


...省略接口的定义(同上面的代码一致)

public class TestDemo {
	public static void main(String[] args) {
		A a = new X();
		B b = (B) a;
		b.get();
	}
}

执行之后,输出的结果为:B接口的中的 get方法。

在定义结构上面来看 A 和 B 接口没有任何的直接联系,但是这两个接口有一个共同的子类 X,此时我们不能被类型和名称迷糊了。虽然说 A a = new X() 执行了之后,实例化的是 a 接口对象,但是骨子里还是 X,此时的 X 也还是 B 的子类。所以是可以正确执行的。

抽象类继承接口的情况

interface A{	// 定义一个接口
	public abstract void print();	// 接口的抽象方法
}

// 抽象类是可以直接继承于接口
abstract class C implements A{	// 定义一个抽象类去实现 A 接口
	// 由于是抽象类,所以可以不用覆写 A 类中的抽象方法
	public abstract void show();	//抽象类中的抽象方法
}

// 不同类继承于抽象类(此时的抽象类是实现了接口)
class G extends C{
	@Override
	public void print() {
		System.out.println("G类-来自接口中的方法");
	}

	@Override
	public void show() {
		System.out.println("G类-来自抽象类中的方法");
	}
}

public class TestDemo {
	public static void main(String[] args) {
		G g = new G();
		g.print();		// G类-来自接口中的方法
		g.show();		// G类-来自抽象类中的方法

		C c = new G();
		c.print();		// G类-来自接口中的方法
		c.show();		// G类-来自抽象类中的方法
		
		A a = new G();
		a.print();		// G类-来自接口中的方法
		// a.show();	这行代码编译报错
		
	}
}

通过上面的代码测试我们可以看到:

  1. 抽象类在实现接口时,可以不用覆写接口的抽象方法
  2. 抽象类实现了接口,然后使用子类向上转型实例化该抽象类时,是可以调用覆写了之后的接口方法以及该抽象类中的方法。
  3. 接口在通过向上转型实例化时,只能调用自己本身的抽象方法。

一个重要概念

对于接口而言,里面的组成就是抽象方法和全局常量,所以在 Java 中为了省略,可以不用写上 abstract 或者 public static final ,并且在方法上面是否编写 public 结果都是一样的,接口里面的方法只能定义为 public 访问权限

根据省略的概念来改造上面的代码

普通类继承抽象类并且实现接口 A

interface A{	// 定义一个接口
	void print();	// 接口的抽象方法
}

abstract class C {	// 定义一个抽象类去实现 A 接口
	public abstract void show();	//抽象类中的抽象方法
}

// 普通类G 继承抽象类并且实现接口 A
class G extends C implements A{
	@Override
	public void print() {
		System.out.println("G类-来自接口中的方法");
	}

	@Override
	public void show() {
		System.out.println("G类-来自抽象类中的方法");
	}
}

public class TestDemo {
	public static void main(String[] args) {
		G g = new G();
		g.print();		// G类-来自接口中的方法
		g.show();		// G类-来自抽象类中的方法

		C c = new G();
		// c.print();		// 这行代码编译报错
		c.show();		// G类-来自抽象类中的方法
		
		A a = new G();
		a.print();		// G类-来自接口中的方法
		// a.show();	这行代码编译报错
	}
}

接口的多继承

一个抽象类可以去继承一个抽象类,但是反过来,一个接口却可以使用 extends 继承多个接口(接口不能继承抽象类)。

interface A{
	public void funA();
}

interface B{
	public void funB();
}

// c接口同时继承了A和B两个父接口
interface C extends A,B{	// 此处使用的是 extends
	public void funC();
}

// 一个普通内实现 C,此时需要覆写所有的接口的方法
class X implements C{
	@Override
	public void funA() {
		// TODO Auto-generated method stub
	}

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

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

接口中定义抽象类

接口里面可以定义普通内部类、抽象内部类、内部接口。

定义内部抽象类

interface A{
	public void funA();
	
	abstract class B{
		public abstract void funB();
	}
}

class X implements A{

	@Override
	public void funA() {
		System.out.println("+++++++++++");
	}
}

定义内部接口

interface A{
	public void funA();
	static interface B{
		public void funB();
	}
}

class X implements A.B{
	@Override
	public void funB() {
		System.out.println("+++++++++++");
	}
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Wayfreem

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值