Java之路:接口

接口

接口(interface)是Java所提供的另一种重要技术,是一种特殊的类,它的结构和抽象类非常相似,也具有数据成员与抽象方法,但它与抽象类又有不同,并且Java 8中又添加了新特性。

1、接口的定义与使用

(1)接口中的变量会被隐式地指定为public static final变量(并且只能是public static final变量,用private修饰会报编译错误)。接口里的数据成员必须初始化,常见的是全局变量。

(2)接口中的方法会被隐式地指定为public abstract方法且只能是public abstract方法(用其他关键字,比如private、protected、static、 final等修饰会报编译错误)。也就是说,接口不能像抽象类一样定义一般的方法,需定义“抽象方法”。

(3) 另,Java8中为避免在接口中添加新方法后要修改所有实现类,允许定义默认方法,即default方法,也可以称为Defender方法,或者虚拟扩展方法(Virtual extension methods)。

Default方法是指,在接口内部包含了一些默认的方法实现(也就是接口中可以包含方法体,这打破了Java之前版本对接口的语法限制),从而使得接口在进行扩展的时候,不会破坏与接口相关的实现类代码。

(4)接口中不能含有静态代码块以及静态方法(抽象类中可以有静态代码块和静态方法)。

(5)在Java中使用interface关键字来定义一个接口。

接口定义的语法如下:

interface 接口名称 {
	final 数据类型 成员名 = 常量;	// 数据成员必须赋初值
	abstract 返回值的数据类型 方法名(参数...);	// 抽象方法
	default 返回值的数据类型 方法名(参数...) {	// 默认方法,包含方法体
		// ...  方法体
	}
}

定义一个接口实例:

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

带默认方法的接口定义实例:

interface A {
	public static final String INFP = "Hello,world!";	// 全局常量
	public abstract void print();	// 抽象方法
	default public void otherPrint(){
		System.out.println("default methods!");
	}
}

虽然有了接口,可是定义的接口A和接口B因里面存在抽象方法,都不能被用户直接使用。

(6)接口必须有子类,子类依靠implements关键字可以同时实现多个接口。

(7)接口的子类(如果不是抽象类)则必须覆写接口之中的全部抽象方法。

(8)接口可以利用对象多态性,利用子类实现对象的实例化。

(9)接口与一般类一样,本身也具有数据成员与方法,但数据成员一定要赋初值,且此值不能再更改,方法也必须是“抽象方法”或default方法。

也正因为接口中的方法除default方法外必须是抽象方法,而没有一般的方法,所以接口定义格式中,抽象方法声明的关键字abstract是可以省略的。
同理,接口的数据成员身上,因数据成员必须赋初值,且此值不能再被更改,所以声明数据成员的关键字final也可省略。

例:

interface A {
	public static String INFP = "Hello,world!";	// 全局常量,省略final
	public void print();	// 抽象方法,省略abstract
	default public void otherPrint(){
		System.out.println("default methods!");
	}
}

(10)在Java中接口是用于实现多继承的一种机制,也是Java设计中最重要的一个环节,每一个由接口实现的类必须在类内部覆写接口中的抽象方法,且可自由地使用接口中的常量。

既然接口里只有抽象方法,它只需声明而不用定义处理方式,于是自然可以联想到接口没有办法像一般类一样,再用它来创建对象。利用接口创建新类的过程,称之为接口的实现(implementation)。

接口实现的语法:

class 类名 implements 接口A,接口B... {
	...
}

带default方法接口的实现:

interface InterfaceA {
	public static String INFO = "static final";	// 全局常量,省略final
	public void print();	// 抽象方法,省略abstract
	default public void otherPrint() {
		System.out.print("Print default1 method InterfaceA!");
	}
}

class InterfaceAB implements InterfaceA {
	@Override
	public void print() {
		System.out.print("Print abstract methods InterfaceA!");
		System.out.print(INFO);
	}
}
public class InterfaceDefault {
	public static void main(String[] args) {
		InterfaceAB ab = new InterfaceAB();
		ab.print();	// 调用覆写过的抽象方法
		ab.otherPrint();	// 调用接口中的默认方法
		System.out.print(InterfaceA.INFO);	// 输出接口中的常量
	}
}

【结果】
在这里插入图片描述

(11)Java 8 中允许接口中只定义默认方法,无抽象方法。

interface InterfaceA {
	default public void otherPrint() {
		System.out.print("Print default1 method InterfaceA!");
	}
}

class InterfaceAB implements InterfaceA {}

public class InterfaceDefault {
	public static void main(String[] args) {
		InterfaceAB ab = new InterfaceAB();
		ab.otherPrint();	// 调用接口中的默认方法
	}
}

【结果】
在这里插入图片描述
上例中定义了仅有一个默认方法的接口,无抽象方法,继承接口的子类因不需覆写抽象方法,内容为空。
接口与抽象类相比,最大的区别就在于子类上,子类可以同时实现多个接口。

例:

interface A {
	public static String INFO = "Hello,world!";
	public void print();
}

interface B {
	public void get();
}

class X implements A,B {
	public void print() {
		System.out.println(INFO);
	}
	public void get() {
		System.out.println("你好!");
	}
}
public class InterfaceDemo {
	public static void main(String[] args) {
		X x = new X();	// 实例化子类对象
		A a = x;	// 为父接口实例化
		B b = x;	// 为父接口实例化
		a.print();
		b.get();
	}
}

【结果】
在这里插入图片描述

(12)一个类实现多个接口时,若接口中有默认方法,不能出现同名默认方法。

但在Java8中,如果一个类实现两个或多个接口,即多继承,但是若其中两个接口中都包含一个名字相同的default方法,如下例中的InterfaceA,InterfaceB,有同名的默认方法DefaultMethod(),但方法体不同。

interface A {
	public void someMethod();
	default public void defaultMethod() {
		System.out.println("Default method implementation in the interface A");
	}
}

interface B {
	default public void defaultMethod() {
		System.out.println("Default method implementation in the interface B");
	}
}

class X implements A,B {
	public void someMethod() {
		System.out.println("Some methods implementation in the class!");
	}
}
public class InterfaceDemo {
	public static void main(String[] args) {
		X x = new X();	// 实例化子类对象
		x.someMethod();
		x.defaultMethod();	 // 错误,

	}
}

【结果】
在这里插入图片描述

如果编译以上的代码,编译器会报错,因为编译器不知道应该在两个同名的default方法中选择哪一个,因此产生了二义性。

(13)多继承中,如果说在一个子类即要实现接口又要继承抽象类,则应该采用先继承后实现的顺序完成。

interface A {
	String INFO = "Hello,world!";
	public void print();
}

interface B {
	public void get();
}

abstract class C {
	public abstract void fun();
}

class X extends C implements A,B {	// 先继承,后实现
	public void print() {
		System.out.println(INFO);
	}
	public void get() {
		System.out.println("你好!");
	}
	public void fun() {
		System.out.println("你好!JAVA");
	}
}
public class InterfaceDemo {
	public static void main(String[] args) {
		X x = new X();	// 实例化子类对象
		A a = x;	// 为父接口实例化
		B b = x;	// 为父接口实例化
		C c = x;	// 为抽象类实例化
		a.print();
		b.get();
		c.fun();
	}
}

【结果】
在这里插入图片描述

(14)接口使用过程中,一个抽象类可以继承多个接口,但是反过来讲,一个接口却不能够继承抽象类,但一个接口却可以使用extends关键字继承多个接口,也可以同时继承多个接口的抽象方法与常量。

interface A {
	String INFO = "Hello,world!";
	public void print();
}

interface B {
	public void get();
}

abstract class C implements A,B {
	public abstract void fun();
}

interface D extends A,B {	// 同时继承两个接口
	public void printD();
}

class X extends C implements D {	// 先继承,后实现
	public void print() {
		System.out.println(INFO);
	}
	public void get() {
		System.out.println("你好!");
	}
	public void fun() {
		System.out.println("抽象类C实现接口A,B!");
	}
	public void printD() {
		System.out.println("抽象类D继承两个接口A,B!");
	}
}
public class InterfaceDemo {
	public static void main(String[] args) {
		X x = new X();	// 实例化子类对象
		A a = x;	// 为父接口实例化
		B b = x;	// 为父接口实例化
		C c = x;	// 为抽象类实例化
		D d = x;	// 为父接口实例化
		a.print();
		b.get();
		c.fun();
		d.printD();
	}
}

【结果】
在这里插入图片描述

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值