《Java核心技术》接口、Lambda表达式与内部类

6 接口、 Lambda 表达式与内部类

1 接口

本节将讲解Java接口的定义与基础用法,同时梳理Java各版本迭代中,接口新增的功能与语法特性。

1.1 接口的概念

在Java语言中,接口并非类,而是一套约束类行为的标准。简单来说,服务提供方会设定规则:只要你的类遵循本接口规范,我就能为其提供配套服务。

举个典型实例:Arrays工具类的sort方法可以对任意对象数组排序,但有强制前提------数组内所有元素对应的类,必须实现Comparable可比较接口。

原始无泛型的Comparable接口源码如下:

接口内的compareTo属于抽象方法,没有方法体、无具体实现。所有实现该接口的类,都必须完整实现这个方法,保证入参为Object、返回值为整型;若未完成实现,该类会被标记为抽象类,无法实例化对象。

补充说明:自Java 5起,Comparable被改造为泛型接口,消除强制类型转换的冗余代码。

例如实现Comparable<Employee>的员工类,必须提供如下格式的方法:

你依旧可以使用不带泛型参数的原生Comparable,但调用方法时需要手动将入参强转为目标类型。本章前半段暂时使用原生写法,避免你同时学习泛型与接口两个新概念,降低理解门槛。

接口内所有方法默认访问修饰符均为public,因此声明接口方法时,无需额外写public关键字。

除此之外,接口存在一条语法无法强制约束的隐性规则:调用x.compareTo(y)时,方法需要完成两个对象的比对,并按规则返回数值:

  1. 若x小于y,返回负整数;

  2. 若二者相等,返回0;

  3. 若x大于y,返回正整数。

上述示例仅包含单个抽象方法,实际开发中一个接口可定义多个抽象方法,也能声明常量。但接口有明确限制:不能定义实例成员字段

Java 8之前,接口内所有方法只能是抽象方法;6.1.4、6.1.5小节会介绍新版接口新增的静态、私有、默认方法。这类新增方法同样无法访问实例字段,因为接口本身不存在实例字段。

下面我们实操演示:使用Arrays.sort对Employee员工对象数组排序,要求Employee类实现Comparable接口。

类实现接口分为两步固定操作:

  1. 使用implements关键字,声明当前类实现指定接口;

  2. 完整实现接口内全部抽象方法,补充方法体逻辑。

声明类实现接口的写法:

接着在Employee中实现compareTo,以员工薪资作为排序依据:

代码调用Double静态工具方法,自动根据两个浮点数值大小返回负数、0或正数,无需手动判断。

重要注意:接口方法默认是public,无需手动标注;但类重写接口方法时,必须显式添加 public。若省略public,方法会采用默认包访问权限,访问范围小于接口定义,编译器会直接抛出权限报错。

改用泛型Comparable优化代码,彻底消除强制类型转换:

开发技巧: compareTo 返回值简写规则

compareTo仅要求返回正负整数或0,不限制具体数值。针对整型字段排序时,可直接返回字段差值简化代码;比如按员工唯一工号排序,直接写id - other.id即可。

但该写法存在数值溢出风险:若整型数值区间过大,差值会超出整型存储范围,排序逻辑完全错乱。因此数值范围不可控时,优先使用Integer.compare静态方法。

差值简写不适用于浮点类型 :两个数值接近的浮点数做减法,极易因精度丢失结果归零,导致排序失效。浮点对比统一使用Double.compare(x, y)。