细数jdk库的四宗罪

原创 2017年01月18日 11:55:57

写过java代码的编程人员都有这种感慨——jdk库非常庞大,并且有非常多精心设计的工具可以拿来用。另一方面,jdk版本的向下兼容性也做得非常好,升级版本对旧项目来说没多大困难。由于这两点原因,jdk不可避免地存在一些设计上的缺陷。为了保障旧项目开发团队的利益,这些设计缺陷只能随着众多版本被继承下来。

个人总结了一下,下面几点我们可以把它当作反面教材。


第一宗罪:破坏封装性,公有类直接暴露数据域

如果问一个程序员,为什么javabean不直接将属性设为public,而需要浪费那么多精力搞一堆getter/setter方法。很多人会回答——为了让代码看起来更加oop。

其实这个回答没有抓住重点。我们之所以要实现getter/setter方法,依我看来,至少有两点原因:1、允许我们在调用方法时作限制与记录,例如对setter的参数作边界的判断,在调用方法时增加日志或断点调试;2、可以保持对外开放接口不变的同时修改内部数据结构。

JDK库的几个类破坏了这种封闭性,比较典型的是awt包里的Dimension和Point两个类。从源代码可以看出,这两个类的属性域都直接是public修饰的。


第二宗罪:滥用继承

util包有一个工具类,明显是滥用继承的代表。没错,这个类就是鼎鼎大名的Stack类了。

我们知道Statck数据结构本身的特点就是“后进先出”。那么它理想就应该只有两个方法来操纵数据,一个是push()方法,另一个是pop()方法。但是由于继承了Vector,Stack从父亲那里继承了诸如add(),remove(),set()等违反游戏规则的方法。这简直无法直视!!


第三宗罪:值对象应该设计为不可变对象

不可变对象是指,实例属性经过初始化后在对象的整个生命周期内固定不变。例如jdk的String以及各种基本类型的包装类。

不可变对象易于设计,并且在并发环境下更加安全,无需额外的同步机制。

util包里的Date类属于值对象,类似于人民币一元,十元的概念,应该被设计为不可变对象。也就是说,不应该提供各种setter方法来修改对象的属性域。


第四宗罪:使用常量接口

常量接口是指没有任何方法,只包含表态final域的接口对象,每一个域都导出一个。实现该接口的类即可获得接口的所有常量属性,看起来非常方便!

然而,常量接口模式是对接口的不良使用。首先,常量的使用应属于内部实现细节,实现常量接口会把这样的细节暴露到导出的API中。其次,如果在后续升级中发现一个类不再需要以前的常量,这个类依然必须实现这个常量接口,以确保向下兼容性。

jdk平台io包里的ObjectStreamConstants就属于常量接口,不值得效仿。

那么,如果需要导出常量,最好的选择方案是jdk5引入的枚举类型(enum)。当然,如果某些常量跟某个类或接口联系非常紧密,也可以把这个常量绑定在该类,例如Integer.MAX__VALUE或Math.PI等。

然而,某些开发人员还是喜欢选择常量接口,因为枚举略显繁琐,而类又必须写一串长长的"public static final "修饰。但是他们的使用还是有底线的,当需要某个常量的,代码只会用XXConstants.XX的模式,而不会直接让类实现这个接口。这种使用算是一种折中方案。采用哪种方法,还是看项目规范吧。


考虑到jdk库的庞大以及兼容性,以上列出的几个“瑕疵”也就瑕不掩瑜,无可厚非了。jdk的源码还是非常值得我们好好学习与揣摩的。

版权声明:本文为博主原创文章,未经博主允许不得转载。

elasticsearch源码分析之Rest/RPC 接口解析(八)

一些基础知识 早先ES的HTTP协议支持还是依赖Jetty的,现在不管是Rest还是RPC都是直接基于Netty了。 另外值得一提的是,ES 是使用Google的Guice 进行模块管理,...

分布式搜索Elasticsearch源码分析之二------索引过程源码概要分析

elasticsearch的索引逻辑简单分析,这里只是理清主要的脉络,一些细节方面以后的文章或会阐述。 假如通过java api来调用es的索引接口,先是构造成一个json串(es里表示为X...

细数JDK里的设计模式(转)

结构型模式: 适配器模式: 用来把一个接口转化成另一个接口。 java.util.Arrays#asList()javax.swing.JTable(TableModel)java....

细数JDK里的设计模式

前面有些废话就不翻译了,直接切入正题吧~ 结构型模式 适配器模式 用来把一个接口转化成另一个接口。 java.util.Arrays#asList()javax.swing.JTabl...

【转】细数JDK里的设计模式

程老师原文:http://flychao88.iteye.com/blog/2030776原文出处: javacodegeeks   译文出处: deepinmind结构型模式:适配器模式:用来把一个...
  • bohu83
  • bohu83
  • 2016年04月11日 18:23
  • 184

SQL SERVER 四宗罪(三)

TempDB is not important; so I will keep it on my slow drive.TempDB 是不重要的,所以我把他丢到我较慢的驱动器上。 Personally...

隐患重重遭诟病 细数固态硬盘“七宗罪”

隐患重重遭诟病 细数固态硬盘“七宗罪” SSD固态硬盘凭借超高速的读写速度颇受广大玩家的亲睐,它可以大幅提升电脑性能,启动速度更是飞快。如日中天的SSD并非人们想象中那么美好,它在使用过程中暴露出来...

细数Windows 7 Build 7057 17大项改进

  • 2009年03月31日 14:42
  • 44KB
  • 下载

细数Java十宗罪

我在遇到问题时,找一些搞Java朋友求助,有能解决的,我想说的是不能解决的情况下,他们大多会说:“你怎么能这么弄呢?这么搞是不行的,你首先在思路上就错误了,我们从来就不这么做。”,比如“我们一般很少用...
内容举报
返回顶部
收藏助手
不良信息举报
您举报文章:细数jdk库的四宗罪
举报原因:
原因补充:

(最多只允许输入30个字)