接口——基于Java SE8

1.接口的概念

    在Java程序设计语言中,接口不是类,而是对类的一组需求描述,这些类要遵从接口描述的统一格式定义。

    接口中所有的方法自动地属于public,接口可能包含多个方法;接口中还可以定义常量,接口中的域自动地被设为public static final。虽然很多人喜欢写全修饰符,便于理解,但是Java语言规范并不推荐写全多余的关键字。

    然而,更重要的是要知道接口不能提供哪些功能。接口绝不能含有实例域,在Java SE8之前,也不能在接口中实现方法。提供实例域和方法实现的任务应该由实现接口的那个类完成。

    实现接口需要2个步骤:
        1)用implements关键字声明类实现接口
        2)必须对接口所有抽象方法进行定义重写

package 接口;

public class Employee implements Comparable<Employee>{
	private String name;
	private double salary;
	
	public Employee(String name, double salary) {
		this.name = name;
		this.salary = salary;
	}

	public String getName() {
		return name;
	}

	public double getSalary() {
		return salary;
	}

	@Override
	public int compareTo(Employee other) {
		return Double.compare(salary, other.salary);
	}
}
2.接口的特性

    接口不是类,尤其不能使用new运算实例化一个接口:
        x = new Comparable(...); //ERROR

    然而,尽管不能构造接口的对象,却能声明接口的变量:
        Comparable x; //OK

    一个类只能有一个父类,但却可以实现多个接口

3.静态方法

    目前为止,通常的做法都是将静态方法放在伴随类中。在标准库中,你会看到成对出现的接口和实用工具类,如Collection/CollectionsPath/Paths。不过从Java SE8之后,可以直接将静态方法写在接口中,不需要再添加一个伴随类。

4.默认方法

    在Java SE8之前,接口里面的方法只能是抽象方法,这样有一个问题,比如下面这个接口:

public interface Chess{
	void forward();
	void back();
	void left();
	void right();
}

    如果棋子“卒”实现了这个接口,虽然它只能前进,向左或者向右,但是出于接口的特性,它在实现这些方法的同时还必须实现back方法,这就很尴尬了,明明“卒”没有后退功能,却还得去实现方法,不符合实际。

    在Java SE8中,可以为接口方法提供一个默认实现。必须用default修饰符标记这样一个方法。大多数情况下,实现一个接口只是关注其中的某一些方法,这个时候把方法全部声明为默认方法,这些默认方法什么也不做,在类中重写你需要的方法。

``` public interface Chess{ default void forward(){}; default void back(){}; default void left(){}; default void right(){}; } ```

    默认方法还有一个好处是“源代码兼容”,比如Student类已经实现People接口,重写了其中的study方法,这时候,又要新建个Teacher类,也要实现Human接口,Teacher类要新增teach方法,如果直接在Human中添加以前那样的抽象方法,Student类也得跟着改,而如果添加为default方法,则以前的代码完全不用动,只要关注新增的Teacher类即可。

5.默认方法解决冲突的规则

    1)超类优先。如果超类提供了一个具体的方法,接口中同方法签名的默认方法将被忽略。

//接口
public interface Name {
	default String getName(){
		return "影流之主";
	}
}
//超类
public class People {
	public String getName(){
		return "疾风剑豪";
	};
}
//子类继承超类实现接口
public class Employee extends People implements Name{
	public static void main(String[] args) {
		Employee e = new Employee();
		String name =e.getName();
		System.out.println(name); //疾风剑豪
	}
}

    当然,子类重写了一定执行的是子类重写的方法,类优先规则确保了与Java SE7的兼容性。

    2)接口冲突。如果一个接口提供了一个默认方法,另一个接口提供了一个同方法签名的默认方法,必须重写来解决冲突。

public class Employee implements Name,Human{
	
	public static void main(String[] args) {
		Employee e = new Employee();
		String name =e.getName();
		System.out.println(name); //无极剑圣
	}
	//这里不重写会报错,无法编译
	@Override
	public String getName() {
		return "无极剑圣";
	}
}
  • 2
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值