[置顶] 学习JDK源码:可进一步优化的代码
1、参数化类型的构造函数比较啰嗦
new HashMap<String, List<String>>()
如果你调用参数化类的构造函数,那么很不幸,你必须要指定类型参数,即便上下文中已明确了类型参数。这通常要求你连续两次提供类型参数:
Map<String, List<String>> m = new HashMap<String, List<String>>();
而
假设HashMap提供了如下静态工厂:
public static <K, V> HashMap<K, V> newInstance(){
return new HashMap<K, V>();
}
然后你就可以讲上文冗长的声明替换为如下这种简洁的形式:
Map<String, List<String>> m = HashMap.newInstance();
——com.google.common.collect.Lists则解决了这个问题:
List<String> l = Lists.newArrayList();
2、违反“避免创建不必要的对象”
Boolean(String)
Boolean(String)有点多余,因为已经有静态工厂方法:Boolean.valueOf(String)。
它几乎总是比构造函数Boolean(String)更可取。构造函数每次被调用时都会创建一个新对象,而静态工厂方法则从来不要求这样做,实际上也不会这么做。
3、避免使用finalize
FileInputStream.finalize()
要避免用finalize来释放资源,而应该提供一个显式的终止方法。例如FileInputStream.close();
finalizer的作用之一是,可以充当“安全网”,以防对象所有者忘记调用显式的终止方法。虽然不能保证finalizer会被及时调用,但当客户端没有调用显式终止方法时,迟一点释放资源总比不释放好。不过如果finalizer发现有未被终止的资源,则必须打印一条警告,表明客户端代码有bug,需要修复。
有四个类(FileInputStream、FileOutputStream、Timer、Connection)使用了finalizer作为安全网,以防显式终止方法未被调用。不幸的是,这些finalizer都没有打印警告。当API发布后,这种警告一般就不能添加到API了,因为可能破坏已有的客户端代码。
protected void finalize() throws IOException {
if (fd != null) {
if (fd != fd.in) {
close();
}
}
}
4、equals的实现违反约定
URL.equals()
java.net.URL的equals方法依赖于对URL中主机的IP地址的比较,而将主机名转译成IP地址需要访问网络,随着时间推移,并不保证能范围相同的结果。——违反一致性。这就会导致URL的equals方法违反约定,并且已经在实践中引起问题了。
不幸的是,由于兼容性需求,这一行为无法改变。除了少数例外情况,equals方法必须对驻留在内存中的对象进行确定性计算。
Timestamp.euals()
ava.sql.Timestamp扩展了java.util.Date类并增加了nanoseconds域。Timestamp的equals方法就违反了对称性,如果Timestamp和Date被用于同一个集合中,或以其他什么方式混在一起使用,则会引起错误的行为。
——无法在扩展可实例化类的时候,增加一个值组件,同时又保证equals约定。
Timestamp有一个免责声明,提醒程序员不要混用Date和Timestamp。虽然只要不混用他们就不会有麻烦,但是谁都不能阻止你混用他们,而结果导致的错误将会很难调试。Timestamp的这种行为是个错误,不值得效仿。
/**
* Note: This method is not symmetric with respect to the
* <code>equals(Object)</code> method in the base class.
*/
public boolean equals(java.lang.Object ts) {
if (ts instanceof Timestamp) {
return this.equals((Timestamp)ts);
} else {
return false;
}
}
5、接口设计问题
Cloneable接口
Cloneable接口的目的是作为对象的一个mixin接口,表明对象允许克隆;但这个目的没有达到。
其主要缺点是,Cloneable缺少一个clone()方法,而Object.clone()是受保护的。
通常,实现接口是为了表明类可以为它的客户做些什么;而Cloneable却是改变了超类中受保护方法的行为。
——区别java.rmi.Remote接口,其中也不具有任何方法,它是一个记号接口。
6、compareTo与equals不一致
BigDecimal.compareTo
compareTo方法的等同性测试必须与equals方法的结果相同。如果遵守了这一条,则称compareTo方法所施加的顺序与equals一致;反之则称为与equals不一致。当然与equals不一致的compareTo方法仍然是可以工作的,但是,如果一个有序集合包含了该类的元素,则这个集合可能就不能遵守相应集合接口(Collection、Set、Map)的通用约定。这是因为这些接口的通用约定是基于equals方法的,但是有序集合却使用了compareTo而非equals来执行等同性测试。尽管出现这种情况并不会造成灾难性后果,但是应该注意这种情况。
【例】例如BigDecimal类的compareTo方法与equals不一致。如果创建一个HashSet实例,并添加两个元素new BigDecimal("1.0")和new BigDecimal("1.00"),则集合会包含两个元素,因为这两个实例通过equals检测并不相等;然而,如果使用TreeSet而非HashSet,则集合中会只包含一个元素,因为这两个实例通过compareTo检测是相等的。
7、public类不应暴露其内部字段
如果一个类可以被包外访问,那么就要提供访问方法,以便可以灵活地改变类的内部表示。如果public类暴露了其数据域,则要想在将来改变内部表示是不可能的
Point
public class Point extends Point2D implements java.io.Serializable {
public int x;
public int y;
Dimension
public class Dimension extends Dimension2D implements java.io.Serializable {
public int width;
public int height;
其他
唯一声称保证finalizer()会被执行的方法是System.runFinalizersOnExit,以及Runtime.runFinalizersOnExit。——但这两个方法都有致命缺陷并且都已弃用。
未完待续。。。
[置顶] 学习JDK源码:可进一步优化的代码的更多相关文章
- [置顶] 学习JDK源码:编程习惯和设计模式
编程习惯 1.用工厂方法替代构造函数 Boolean.valueOf() 通过一个boolean简单类型,构造Boolean对象引用. 优点:无需每次被调用时都创建一个新对象.同时使得类可以严格控制在 ...
- 深入学习JDK源码系列之、ArrayList
前言 JDK源码解析系列文章,都是基于JDK8分析的,虽然JDK15马上要出来了,但是JDK8我还不会,我... 类图 实现了RandomAccess接口,可以随机访问 实现了Cloneable接口, ...
- 学习JDK源码(二):Integer
最近没有好好保持学习的好习惯,该打. 天天忙,感觉都不知道在干嘛.真的厌倦了普通的Java代码,还是想学点新技术. 用了这么久的Java,最常用的数据类型肯定是Int了,而他的包装类Integer用的 ...
- 学习JDK源码(一):String
用了好久的Java了,从来没有看过jdk的源码,趁着今天有点时间,拿出了jdk的源码看了下,今天先看了关于String的,毕竟开发中String类型使用最广泛.在我们下载安装jdk的时候,部分源码也已 ...
- [置顶] Cocos2d-x 实例源码分析之二 小实例的主框架
这篇文章是分析第一个小实例ActionTest的源码.其实所有实例程序的结构都是一样的,只有特定方法里的代码不同,大的框架都是一样的.也就是说看完这篇文章你就可以自己开始分析其他源码了. 废话不多说, ...
- JDK源码学习笔记——String
1.学习jdk源码,从以下几个方面入手: 类定义(继承,实现接口等) 全局变量 方法 内部类 2.hashCode private int hash; public int hashCode() { ...
- JDK源码系列总索引
一 目标 记录学习jdk源码的一些笔记和心得,jdk版本使用11.0.1,工具idea Class后面序号为优先级1-4,优先级递减 目录转载自博客: https://blog.csdn.net/qq ...
- 关于JDK源码:我想聊聊如何更高效地阅读
简介 大家好,我是彤哥,今天我想和大家再聊聊JDK源码的几个问题: 为什么要看JDK源码 JDK源码的阅读顺序 JDK源码的阅读方法 为什么要看JDK源码 一,JDK源码是其它所有源码的基础,看懂了J ...
- JDK源码学习系列04----ArrayList
JDK源码学习系列04----ArrayList 1. ...
随机推荐
- 找呀志_使用SQLiteDatabase增删改提供的搜索方法和事务
知识具体解释:http://blog.csdn.net/zhaoyazhi2129/article/details/9026093 MainActivity.java,User.java,BaseDa ...
- TS流文件
简单介绍编辑 随着从HDTV录制的高清节目在网上的流传,烧友们对TS这个名词大概已经不陌生了.但随之而来就是怎样播放.怎样加入字幕等等的一系列问题.本文将重点介绍一下这方面的应用操作. 先来简要介绍一 ...
- Mac在结构quick cocos2d-x编译环境
关于 Quick 很多其它的使用说明可參考安装文件夹下的 README 文件. Quick-Coco2d-x开发工具 普通情况下,我们通常都会採用Cocos Code IDE作为开发工具来高速开发游戏 ...
- js 利用iframe和location.hash跨域解决的方法,java图片上传回调JS函数跨域
奶奶的:折腾了我二天,最终攻克了!网上有非常多样例. 但跟我的都不太一样,费话不多说了,上图 上代码: IE ,firefix,chrome 測试通过 js :这个主页面,部分代码, functi ...
- 关于Java的对象、数组、String类的具体用法
对象的行为: 1.内存分配(栈和堆的区别) 栈:保存局部变量的值(用来保存基本数据类型的值:保存类的实例的引用) 对:用来存放动态产生的数据,比如new出来的对象 2.调用方法 方法返回一个值.方法不 ...
- signalR例子
不用找了,比较全的signalR例子已经为你准备好了. 这几天想着将一个winform的工具上线到web上,因为对时时性的要求比较高,找朋友咨询了一下推荐了SignlarR 框架,比较强大.昨天才 ...
- 移动客户端与服务端Session那点秘密
众所周知,做过Web开发的小伙伴可能知道,在浏览器向服务器发一个请求,服务器端会为当前的访问者创建一个session会话,随着浏览器的关闭而会话结束.但是移动客户端咋整呢(IOS/Android啥的) ...
- Installshield脚本拷贝文件常见问题汇总
原文:Installshield脚本拷贝文件常见问题汇总 很多朋友经常来问:为什么我用CopyFile/XCopyFile函数拷贝文件无效?引起这种情况的原因有很多,今天略微总结了一下,欢迎各位朋友跟 ...
- sql点滴41—MyISAM 和 InnoDB 讲解
原文:sql点滴41-MyISAM 和 InnoDB 讲解 InnoDB和MyISAM是许多人在使用MySQL时最常用的两个表类型,这两个表类型各有优劣,视具体应用而定.基本的差别为:MyISAM类型 ...
- C语言字符串操作函数集
1)字符串操作 strcpy(p, p1) 复制字符串 strncpy(p, p1, n) 复制指定长度字符串 strcat(p, p1) 附加字符串 strncat(p, p1, n) 附加指定长度 ...