Java 接口常量反模式

勤奋不是嘴上说说而已,而是实际的行动,在勤奋的苦度中持之以恒,永不退却。业精于勤,荒于嬉;行成于思,毁于随。在人生的仕途上,我们毫不迟疑地选择勤奋,她是几乎于世界上一切成就的催产婆。只要我们拥着勤奋去思考,拥着勤奋的手去耕耘,用抱勤奋的心去对待工作,浪迹红尘而坚韧不拔,那么,我们的生命就会绽放火花,让人生的时光更加的闪亮而精彩。

导读:本篇文章讲解 Java 接口常量反模式,希望对大家有帮助,欢迎收藏,转发!站点地址:www.bmabk.com,来源:原文

缘起
在看项目代码或者部分框架的源码时,会看到有些人把常量定义在接口中,即类似于这种常量定义:

public interface Gender {
	final int MALE = 1;
	final int FEMALE = 0;
}

这样做的理由可能是接口不能实例化,而使用接口中定义的常量也不用附着在实例上。在JDK的API里也有这种例子,比如 ObjectStreamConstans,多是出现在 Enum 类型到来之前。

其实 Java 的接口常量是一种反模式(bad practice):

  1. 接口是不能阻止被实现或继承的,也就是说子接口或实现中是能够覆盖掉常量的定义(重名),这样通过父,子接口(或实现) 去引用常量是可能不一致的。
  2. 由于被实现或继承,造成在继承树中可以用大量的接口,类或实例去引用同一个常量,从而造成接口中定义的常量污染命名空间。(Java 编译器竟然允许使用实例去引用类变量)
  3. 接口是需被实现的,代表着一种类型,它的公有成员是要被暴露的 API。而在接口中定义的常量说不上是 API。
  4. Java 允许通过子类去引用父类中定义的常量,各级对像实例去引用父类的常量,所以这会造成相当的混乱不堪。定义的常量不能保证单一的引用方式。

实际上,《Effective java》第 19 条也指出:接口只用于定义类型。

既然接口中不适于定义常量,那常量该在哪里定义呢?
接口为 实现/继承 而生,如果放在类中,并且这个类是 final,且私有化构造方法就行:

public final class Gender {
	private Gender() {
	}
	public static final int MALE = 1;
	public static final int FEMALE = 0;
}

当然,一般在常量类里面可以定义多种类型的常量:int、String、boolean……
如果要定义的多个常量值是同质的,那么最好的定义常量的方式应该是枚举:

public enum Gender {
	MALE,
	FEMALE
}

Gender 实质就是一个继承 java.lang.Enum 的 final 类,获得 Enum 中有用方法,并且直接被编译器禁止被实例化,它有两个 Gender 型成员 MALE 和 FEMALE。

public final class Gender extends Enum {
	public static final Gender MALE;
	public static final Gender FEMALE;
}

其他资料:
wikipedia-Constant_interface
constant-interface-anti-pattern

版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 举报,一经查实,本站将立刻删除。

文章由极客之音整理,本文链接:https://www.bmabk.com/index.php/post/142315.html

(0)
飞熊的头像飞熊bm

相关推荐

发表回复

登录后才能评论
极客之音——专业性很强的中文编程技术网站,欢迎收藏到浏览器,订阅我们!