首页 > 作文

详细聊聊JDK中的反模式接口常量

更新时间:2023-04-04 10:47:35 阅读: 评论:0

目录
前言常量接口类接口枚举类型结束语

前言

在实际开发过程中,经常会需要定义一个文件,用于存储一些常量,这些常量设计为静态公共常量(使用public static final修饰)。这个时候就出现两种选择:不负韶华下一句是什么

在接口中定义常量,比如 jdk 1.1 中的java.io.objectstreamconstans接口;

在类中定义常量,比如 jdk 1.7 中的java.nio.char英雄联盟瑟庄妮t.standardcharts

这两种方式都能够达到要求:存储常量、无需实例化。下面分情况讨论下两种方式孰优孰劣。

常量接口

首先从代码的角度分析,接口中定义的变量都必须是常量,即默认使用public static final修饰。也就是说,在写代码的时候直接写成下面这样:

publicinterfaceobjectstreamconstants{shortstream_magic=(short)0xaced;shortstream_version=5;}

但是在类中就必须乖乖的写成下面这种样子:

publicfinalclassobjectstreamconstants{publicstaticfinalshortstream_magic=(short)0xaced;publicstaticfinalshortstream_version=5;}

从直观的感受,接口写起来方便多了。第二个问题:因为类中写的字符比接口多,所以编译之后文件大小也是类文件比接口文件大。第三个问题:在jvm加载过程中,接口没有类提供的额外特种(如重载、方法的动态绑定等),所以接口加载比类快。分析到此,似乎没有什么理由不用接口定义常量了。但是,but,这种做法却是一种严重的反模式行为。引用《effective java》中的一段描述:

the constant interface pattern is a poor u of interfaces. that a class us some constants internally is an implementation detail. implementing a constant interface caus this implementation detail to leak into the class’s exported api. it is of no conquence to the urs of a class that the class implements a constant interface. in fact, it may even confu them. wor, it reprents a commitment: if in a future relea the class is modified so that it no longer needs to u the constants, it still 西门子官网首页中国must implement the interface to ensure binary compatibility. if a nonfinal class implements a constant interface, all of its subclass will have their namespaces polluted by the constants in the interface.

翻译出来就是:

常量接口模式是对接口的不良使用。类在内部使用某些常量,这纯粹是实现细节。实现常量接口会导致把这样的实现细节泄露到该类的导出api中。类实现常量接口,这对于类的用户来讲并没有什么价值。实际上,这样做反而会使他们更加糊涂。更糟糕的是,它代表了一种承诺:如果在将来的发行版本中,这个类被修改了,它不再需要使用这些常量了,它依然必须实现这个接口,以确保兼容性。如果非final类实现了常量接口,它的所有子类的命名空间也会被接口中的常量所“污染”。

这样说来就很明白透彻了:

接口是不能阻止被实现或继承的,也就是说子接口或实现中是能够覆盖掉常量的定义,这样通过父、子接口(或实现) 去引用常量是可能不一致的;

同样的,由于被实现或继承,造成在继承树中可以用大量的接口、类或实例去引用同一个常量,从而造成接口中定义的常量污染了命名空间;

接口暗含的意思是:它是需mother s day被实现的,代表着一种类型,它的公有成员是要被暴露的api,但是在接口中定义的常量还算不上api。

综上所述:使用接口定义常量,是一种不可取的行为。jdk中定义的接口常量(例如java.io.objectstreamconstans)应该算是反面教材。

类接口

既然使用接口第一常量不可取,那就只能通过类定义常量了。虽然在java中类不能够多继承,但是子类也能够“污染”父类定义常量的命名空间。所以为了常量不可变,需要将常量类定义为final的,然后再彻底点就是再定义个private的构造函数。就像java.nio.chart.standardcharts一样:

publicfinalclassstandardcharts{privatestandardcharts(){thrownewasrtionerror("nojava.nio.chart.standardchartsinstancesforyou!");}publicstaticfinalchartus_ascii=chart.forname("us-ascii");publicstaticfinalchartiso_8859_1=chart.forname("iso-8859-1");publicstaticfinalchartutf_8=chart.forname("utf-8");}

java.nio.chart.standardcharts中,为了阻止各种形式的实例化,甚至在构造函数中抛出错误,也是做个够彻底的了。

枚举类型

但是,but,还有一种情况,比如常量中定义性别:男、女,使用上面的类常量,需要写成:

publicfinalclassgender{privategender(){thrownewasrtionerror("nox.y.z.genderinstancesforyou!");}publicstaticfinalintmale=1;publicstaticfinalintfemale=0;}

因为定义的性别类型实际是int,如果手贱写成m.tgender(3)也是没有错误的,那3又是什么鬼?是不是还要有4567?那这种常量定义就失去价值了。对于这种可以归类的常量,最好的常量定义方法应该就是枚举了:

publicenumgender{ma形容秋天的成语le,female}

根据编辑的字节码,gender实际是:

publicfinalclassgenderextendsjava.lang.enum{publicstaticfinalgendermale;publicstaticfinalgenderfemale;}

这样对于接受 gender 类型参数的方法就只能传入 male 或 female 了,不再有其他选项,这就是枚举的意义。在后来的jdk中,也出现了像java.nio.file.standardopenoption等的枚举定义。而且枚举的定义也不只局限于这种,还有很多其他复杂定义,可以适用各种情况,以后再慢慢讨论。

结束语

定义常量不要使用接口常量,要在类中定义,最好是final类,并且定义private的构造方法,如果常量可以进行归类,最好使用枚举定义:枚举 > 类 > 接口。

到此这篇关于jdk中反模式接口常量的文章就介绍到这了,更多相关jdk反模式接口常量内容请搜索www.887551.com以前的文章或继续浏览下面的相关文章希望大家以后多多支持www.887551.com!

本文发布于:2023-04-04 10:47:33,感谢您对本站的认可!

本文链接:https://www.wtabcd.cn/fanwen/zuowen/8df9a44ba62e6b473dd63506a23d662e.html

版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系,我们将在24小时内删除。

本文word下载地址:详细聊聊JDK中的反模式接口常量.doc

本文 PDF 下载地址:详细聊聊JDK中的反模式接口常量.pdf

标签:常量   接口   定义   类型
相关文章
留言与评论(共有 0 条评论)
   
验证码:
Copyright ©2019-2022 Comsenz Inc.Powered by © 专利检索| 网站地图