细数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的源码还是非常值得我们好好学习与揣摩的。

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

相关文章推荐

手游服务端框架之消息线程模型

玩家的消息请求如果放在mina的io线程池进行处理,当业务处理非常耗时,会严重影响io的吞吐量。所以,我们应该另起用于处理业务逻辑的线程池,采用生产者消费者模型,异步处理玩家请求。

手游服务端框架之GM金手指的设计

游戏开发需要一些命令,能够像金山游侠这种软件一样,修改游戏里的玩家或公共服务的数据。在游戏项目里,这些命令统称为GM命令。本文将介绍实现gm系统的一种方式。

手游服务端框架之使用事件驱动模型解决业务高耦合

游戏里经常有这样的业务,当玩家触发某个动作时,有若干与之关联的业务也要一起执行。诸如这样场景,我们选择引入事件驱动模型来帮助我们解决业务代码耦合的问题。本文实现一个工具库,来解决监听器与事件多对多的关...

游戏开发的艰辛历程与升级展望

从第一款游戏《贪吃蛇》开始,到《水果忍者》、《时空猎人》,再到如今风靡全国的《王者荣耀》,手机游戏迎来了百花齐放的繁华时代。怀着对游戏行业的热爱,一批一批游戏开发大军加入了队伍。即使从业道路很艰辛,我...

再见百田,你好三七

在百田愉快工作了五个月,项目却遭遇了解散。虽然留下遗憾,但未来还有路要走。国庆后,我就要在三七继续奋斗我的青春与汗水。

自定义orm框架解决玩家数据持久化问题

使用持久化框架诸如Hibernate过于重量级,使用原生jdbc又显得非常啰嗦。本文通过几百行代码,演示一个轻量级的持久化框架。可以用于游戏服务端的数据持久化方案。

手游服务端框架之使用Guava构建缓存系统

缓存,在项目中的应用非常之广泛。诸如这样的场景,某些对象计算或者获取的代码比较昂贵,并且在程序里你不止一次要用到这些对象,那么,你就应该使用缓存。缓存,在项目中的应用非常之广泛。诸如这样的场景,某些对...

手游服务端框架之模仿SpringMvc处理玩家请求

经典web开发项目通常采用三层架构来组织代码。典型的,第一层为表现层,通常使用MVC模式;第二层为业务逻辑层,该层主要是各种service业务操作类;第三层则为数据访问层。类似的,我们的游戏项目也可以...

Netty网络聊天室之会话管理

浏览器第一次与服务器建立连接的时候,服务器就会自动为之分配一个Session。在我们的聊天室,也可以使用Session来判断用户是否经过登录验证,保存用户的各种信息,向客户端发送消息。这极大方便了程序...
内容举报
返回顶部
收藏助手
不良信息举报
您举报文章:深度学习:神经网络中的前向传播和反向传播算法推导
举报原因:
原因补充:

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