Java 接口中的静态方法,用户希望为接口添加一个类级别(class level)的工具方法和相应的实现,将接口方法声明为 static
,并以常规方式添加实现。Java 类的静态成员是类级别的。换言之,静态成员与整个类相关联,而不是与特定的实例相关联。但从设计的角度看,静态成员在接口中的使用是有问题的。
Java 接口中的静态方法 问题描述
用户希望为接口添加一个类级别(class level)的工具方法和相应的实现。
Java 接口中的静态方法 解决方案
将接口方法声明为 static
,并以常规方式添加实现。
Java 接口中的静态方法 具体实例
Java 类的静态成员是类级别的。换言之,静态成员与整个类相关联,而不是与特定的实例相关联。但从设计的角度看,静态成员在接口中的使用是有问题的,举例如下。
- 当多个不同的类实现接口时,类级别成员指的是什么?
- 类是否需要通过实现接口来使用静态方法?
- 类中的静态方法是通过类名访问的。如果类实现了一个接口,那么静态方法是通过类名还是接口名来调用呢?
为解决这些问题,Java 开发团队尝试了几种不同的方案。
在 Java 8 之前,接口完全不支持使用静态成员,不过这导致了工具类的产生,这是一种只包含静态方法的类。java.util.Collections
就是一种典型的工具类,它不仅包括用于排序和搜索的方法,也定义了采用同步或不可修改的类型包装集合的方法。在 NIO
包中,另一种工具类是 java.nio.file.Paths
,它只包括从字符串或 URI 中解析 Path
实例的两个静态方法。
而在 Java 8 中,我们可以随时为接口添加静态方法,步骤如下。
- 为方法添加
static
关键字。 - 提供一种无法被重写的实现。此时,静态方法类似于默认方法,包含在 Javadoc 的 Default Methods(默认标签)中。
- 通过接口名访问方法。类不需要通过实现接口来使用静态方法。
java.util.Comparator
接口定义的 comparing
方法就是一种实用的静态方法,它包括 comparingInt
、comparingLong
、comparingDouble
等三种基本变体。此外,Comparator
接口还包括 naturalOrder
和 reverseOrder
两种静态方法。例 1-28 给出了这些方法的用法。
例 1-28 字符串排序
List<String> bonds = Arrays.asList("Connery", "Lazenby", "Moore",
"Dalton", "Brosnan", "Craig");
List<String> sorted = bonds.stream()
.sorted(Comparator.naturalOrder()) ➊
.collect(Collectors.toList());
// [Brosnan, Connery, Craig, Dalton, Lazenby, Moore]
sorted = bonds.stream()
.sorted(Comparator.reverseOrder()) ➋
.collect(Collectors.toList());
// [Moore, Lazenby, Dalton, Craig, Connery, Brosnan]
sorted = bonds.stream()
.sorted(Comparator.comparing(String::toLowerCase)) ➌
.collect(Collectors.toList());
// [Brosnan, Connery, Craig, Dalton, Lazenby, Moore]
sorted = bonds.stream()
.sorted(Comparator.comparingInt(String::length)) ➍
.collect(Collectors.toList());
// [Moore, Craig, Dalton, Connery, Lazenby, Brosnan]
sorted = bonds.stream()
.sorted(Comparator.comparingInt(String::length) ➎
.thenComparing(Comparator.naturalOrder()))
.collect(Collectors.toList());
// [Craig, Moore, Dalton, Brosnan, Connery, Lazenby]
❶ 自然顺序(字典序)
❷ 反向顺序(字典序)
❸ 按小写名称排序
❹ 按姓名长度排序
❺ 按姓名长度排序,如果长度相同则按字典序排序
本例显示了如何利用 Comparator
接口提供的静态方法对一份演员名单进行排序,名单中出现的演员是这些年来詹姆斯 • 邦德的扮演者。有关比较器的详细讨论,请参见范例 利用比较器实现排序 。
由于接口中有静态方法,我们不必创建单独的工具类。但需要的话,仍然可以创建工具类。
请注意以下几点:
- 静态方法必须有一个实现
- 无法重写静态方法
- 通过接口名调用静态方法
- 无须实现接口以使用静态方法