Java接口内定义带实现静态方法的原因及与普通类的差异
为什么在接口里写带实现的静态方法
Java 8 开始支持接口中定义带实现的静态方法,你贴的Validator接口这么写,核心是把和「校验」这个契约绑定的通用工具逻辑,直接聚合在校验能力的定义处,不用额外拆分零散的工具类。
示例代码如下:
public interface Validator { static boolean checkEmptyOrNull(String string, ApiException apiException) { if (Objects.isNull(string) || string.trim().isEmpty()) { throw apiException; } return true; } static boolean checkEmptyOrNull(int value, ApiException apiException) { if (value < 1) { throw apiException; } return true; } }
这两个方法都是所有校验场景通用的无状态逻辑:不管你具体做什么业务的校验,字符串判空抛异常、整数小于1抛异常的规则都是统一的,不需要每个校验实现类重复写这段逻辑。
和普通类写校验工具的差异
很多人第一反应是“建个ValidatorUtils类写这些静态方法不行吗?”,两者确实能实现一样的功能,但有几个明确的区别:
- 少写防实例化的样板代码:普通工具类必须手动加私有构造方法,防止其他人new出工具类实例;接口本身就不允许直接实例化,天生符合工具类无实例的要求。
- 避免方法被继承混淆:普通类的静态方法可以被子类继承、甚至通过子类隐藏父类方法,容易出现调用逻辑和预期不符的问题;接口的静态方法只能通过接口名本身调用,比如
Validator.checkEmptyOrNull(xx, e),实现类不会继承到这些静态方法,完全不存在逻辑被篡改、被隐藏的可能。 - 内聚性更高:如果
Validator本身还定义了需要实现类自定义的抽象校验方法(比如不同业务场景自定义的校验规则),把通用基础校验逻辑和抽象契约放在同一个接口里,开发者找所有校验相关的能力只需要看这一个接口,不用在接口和配套的Utils类之间来回跳转。
要注意的是,这种写法不是让你把所有工具方法都硬塞进接口:如果你根本不需要定义「校验能力」这个抽象契约,只是零散的几个工具方法,那用普通工具类更合理。只有当你本身就要定义一类能力的接口,同时这类能力有通用的、不需要实现类定制的公共逻辑时,把公共逻辑写成接口静态方法才是更简洁的选择。
内容的提问来源于stack exchange,提问作者Palak Kharbanda
相关产品推荐
相关产品推荐

