OpenJDK源码研究笔记(十五):吐槽JDK中的10个富有争议的设计
前14篇文章,分享了JDK中值得学习和借鉴的编码和设计方法。
每个硬币都是有两面的。Every coin has two sides。
当然,JDK中也有很多值得改进或者说富有争议的设计。
本篇,就来详细吐槽下JDK中的10个富有争议的设计。
网友指出
1.求和抛异常,错误提示不合理。
在OpenJDK源码研究笔记(一)-参数检查&抛出带关键错误提示信息的异常这篇文章中,有个网友指出:“第三个if的提示信息有点问题。前两个if说明了position和size都不可能为负,求和通常不可能为负,只有一种情况是 求和 溢出了吧,此时异常信息再这样抛,反而是信息不明确”
protected FileLock(AsynchronousFileChannel channel, long position,
long size, boolean shared) {
if (position < 0)
throw new IllegalArgumentException("Negative position");
if (size < 0)
throw new IllegalArgumentException("Negative size");
if (position + size < 0)
throw new IllegalArgumentException("Negative position + size");
this.channel = channel;
this.position = position;
this.size = size;
this.shared = shared;
}
2.标记接口可以用注解替代。
在OpenJDK源码研究笔记(三)-RandomAccess等标记接口的作用这篇文章中,有个网友指出:“空接口,比如 Serializable 之类的,都只是一个记号, 其实用annotation 更合适。”
比如ArrayList的定义是 class ArrayList implements Serialiable{}。
可以修改为@Serialize
class ArrayList{}
几个观点
a.注解是JDK1.5才有的。之前的API当然还是应该支持。
注解的话,我觉得也是可以的。可能看起来不够简洁。
实现一个空的接口,用instanceof挺方便的。
b.实现接口也好,用注解也好。最终,都是一种设计的2种不同实现。
实现接口用Instance of,用注解 调用方法。
用接口能够更好地兼容以前的代码。
c.从兼容的角度看,确实是的。
但是从设计目的来看,注解更好。
而且不影响对象继承结构,就是加了个标记。
方法定义
3.重复定义方法。
public interface List<E> extends Collection<E>{ int size();
boolean isEmpty(); }
既然继承了父接口Collection,为何还要 重复去定义父类中已经存在的接口??
public interface Set<E> extends Collection<E>等接口的定义 也是如此。
4.双端队列同一种操作有2种类似的实现。
java.util.Deque<E>
/**
* 查询队列中的第1个元素。
* 当队列为空时,返回null。 */
E peekFirst(); /**
* 查询队列中的第1个元素。
* 与peekFirst方法不同的是,当队列为空时,抛出异常。
* @throws NoSuchElementException if this deque is empty
*/
E getFirst();
为什么要定义2套API呢?显得有些重复,容易让人产生疑惑。
5.集合接口Set的返回值不同。
java.util.Set public abstract E get(int index);
public E set(int index, E element); public boolean add(E e);
为什么就这个方法没有返回值呢?
public void add(int index, E element) ;
上面的3个方法都是有返回值的,同样是add(E e)也是有boolean返回值。
设计问题
6.List生成子列表后,就不能再操作原列表。
List<E> subList(int fromIndex, int toIndex);
List<String> list = new ArrayList<String>(); list.add("A"); list.add("B"); List<String> subList = list.subList(0,2); subList.add("C");
以上代码会抛出java.util.ConcurrentModificationException
有的时候,我们确实有这个需求。
既然JDK这样设计,我们只能尽可能避开上述用法。
7.不可变集合的实现方式。
java.util.Collections.unmodifiableList(list);
这种方法的实现,其实返回一个“不可变”的List实现。
static class UnmodifiableList<E> extends UnmodifiableCollection<E>
implements List<E> {
private static final long serialVersionUID = -283967356065247728L;
final List<? extends E> list; UnmodifiableList(List<? extends E> list) {
super(list);
this.list = list;
} public E get(int index) {
return list.get(index);
} public E set(int index, E element) {
throw new UnsupportedOperationException();
} public void add(int index, E element) {
throw new UnsupportedOperationException();
} public E remove(int index) {
throw new UnsupportedOperationException();
} }
把那些会修改List的方法,以抛出异常的方式实现。
在看源码之前,我总觉得有其它方法实现。
看到源码是这种方式实现的,我有点失望。
看来是我想多了。
8.参数检查不合理。
java.util.logging.Handler.setFormatter(Formatter) public void setFormatter(Formatter newFormatter) throws SecurityException {
checkAccess();
// Check for a null pointer:
newFormatter.getClass();
formatter = newFormatter;
}
就是简单地调用一个类的方法newFormatter.getClass();来检查该类是否为null。
这种方式是否更好呢?
if(newFormatter==null){
throw new NullPointerException("");
}
编码习惯
9.一条If语句的括号问题。
大部分的只有一条语句的if语句是这么写的。
public E getFirst() {
final Node<E> f = first;
if (f == null)
throw new NoSuchElementException();
return f.item;
}
我比较习惯以下写法,防止“看走眼”。
if (f == null){
throw new NoSuchElementException();
}
另外,我经常会写下面这样的注释,
if (f == null)
//抛出异常,或者加一条打印语句
throw new NoSuchElementException();
这种写法,很容易看错。
这种类似的代码有很多,如果if语句再嵌套一层,就更容易看错了。
public ScriptEngineManager() {
ClassLoader ctxtLoader = Thread.currentThread().getContextClassLoader();
if (canCallerAccessLoader(ctxtLoader)) {
if (DEBUG)
System.out.println("using " + ctxtLoader);
init(ctxtLoader);
} else {
if (DEBUG)
System.out.println("using bootstrap loader");
init(null);
}
}
10.没有用的变量。
java.util.logging.LogManager中有如下变量定义。
private final static Handler[] emptyHandlers = {};
上面的代码是没有用到的。
Eclipse会有警告,黄色的感叹号还是比较烦人的。
相关阅读
OpenJDK源码研究过程中整理的学习笔记。 OpenJDK是GPL许可(GPL-licensed)的Java平台的开源实现。
原文参见:http://FansUnion.cn/articles/3174(小雷网-FansUnion.cn)
OpenJDK源码研究笔记(十五):吐槽JDK中的10个富有争议的设计的更多相关文章
- OpenJDK源码研究笔记(十六):在Java中使用JavaScript脚本语言
友情提示 本文主要参考了51CTO上的一篇文章,代码经过自己的模仿和整理,还算凑合. 本文中的代码注释比较多,不再过多解释. 更多用法,还是得看JDK的API或者看原文http://developer ...
- OpenJDK源码研究笔记(十):枚举的高级用法,枚举实现接口,竟是别有洞天
在研究OpenJDK,Java编译器javac源码的过程中,发现以下代码. 顿时发现枚举类竟然也有如此"高端大气上档次"的用法. 沙场点兵(用法源码) com.sun.tools. ...
- OpenJDK源码研究笔记(十二):JDBC中的元数据,数据库元数据(DatabaseMetaData),参数元数据(ParameterMetaData),结果集元数据(ResultSetMetaDa
元数据最本质.最抽象的定义为:data about data (关于数据的数据).它是一种广泛存在的现象,在许多领域有其具体的定义和应用. JDBC中的元数据,有数据库元数据(DatabaseMeta ...
- OpenJDK源码研究笔记(十三):Javac编译过程中的上下文容器(Context)、单例(Singleton)和延迟创建(LazyCreation)3种模式
在阅读Javac源码的过程中,发现一个上下文对象Context. 这个对象用来确保一次编译过程中的用到的类都只有一个实例,即实现我们经常提到的"单例模式". 今天,特意对这个上下文 ...
- OpenJDK源码研究笔记(十四):三种经典的设计方法,接口,接口-抽象类-具体实现类,接口-具体实现类
在研究OpenJDK源码过程中,我发现常用的设计方法就是2种:接口,接口-抽象类-具体实现类 . 在一些其它开源框架和业务开发中,经常存在着第3种设计,接口-具体实现类. 1.只有接口,没有实现类. ...
- ABP源码分析十五:ABP中的实用扩展方法
类名 扩展的类型 方法名 参数 作用 XmlNodeExtensions XmlNode GetAttributeValueOrNull attributeName Gets an attribu ...
- OpenJDK源码研究笔记(五)-缓存Integer等类型的频繁使用的数据和对象,大幅度提升性能(一道经典的Java笔试题)
摘要 本文先给出一个看似很简单实则有深意的Java笔试面试题,引出JDK内部的缓存. JDK内部的缓存,主要是为了提高Java程序的性能. 你能答对这道"看似简单,实则有深意"的J ...
- [置顶] OpenJDK源码研究笔记(九)-可恨却又可亲的的异常(NullPointerException)
可恨的异常 程序开发过程中,最讨厌异常了. 异常代表着程序出了问题,一旦出现,控制台会出现一屏又一屏的堆栈错误信息. 看着就让人心烦. 对于一个新人来讲,遇到异常经常会压力大,手忙脚乱,心生畏惧. 可 ...
- OpenJDK源码研究笔记(四)-编写和组织可复用的工具类和方法
本篇主要讲解java.util.Arrays这个针对数组的工具类. 1.可复用的工具类和方法. 这个工具类里,包含很多针对数组的工具方法,如 排序.交换.二分查找.比较.填充.复制.hashcode ...
随机推荐
- 【通信框架】Google的开源通信框架protobuf概述
在阅读的过程中有不论什么问题,欢迎一起交流 邮箱:1494713801@qq.com QQ:1494713801 一.作用 protobuf(Protocol Buffers)是Google内部 ...
- ip反查域名的详细信息(多种方法)
不多说,直接上干货! 至于这里怎FQ,很简单,请见我下面的博客! kali 2.0安装 lantern(成功FQ) shadowsocks(简称SSFQ软件)步骤详解 FQ软件lantern-inst ...
- tnsnames.ora文件说明
目录位置 unix:$ORACLE_HOME/network/admin WINDOW:%ORACLE_HOME%\network\admin 设置相应的环境变量:TNS_ADMIN tnsname. ...
- js中作用域链的问题
为什么没有var声明的变量是全局的? 是因为,在js中,如果某个变量没有var声明,会自动到上一层作用域中去找这个变量的声明语句,如果找到,就使用,如果没有找到,继续向上查找,一直查找到全局作用域为止 ...
- PostgreSQL Replication之第九章 与pgpool一起工作(1)
在前面的章节中,我们已经能够深入地理解了pgbouncer,同时也学会了如何使用它来尽可能地优化复制设置.在本章我们将了解一个经常被称作与pgbouncer相对应的工具.尽管pgpool的思想与pgb ...
- hadoop ha
https://blog.csdn.net/daydayup_668819/article/details/70815335 https://www.jianshu.com/p/8a6cc2d7206 ...
- Debian9.5 系统Samba配置说明
Samba是在Linux和UNIX系统上实现SMB协议的一个免费软件.SMB(Server Messages Block,信息服务块)通信协议是微软(Microsoft)和英特尔(Intel)在198 ...
- UVA-10200 Prime Time 素数(注意除法精度)
题目链接:https://cn.vjudge.net/problem/UVA-10200 题意 给出一个公式$ m=n^2+n+41, n \in Z^+ $ 现在$ a,b\in[0, 10000] ...
- [HAOI2007][SDOI2005]反素数
题目:洛谷P1463.BZOJ1053.Vijos P1172.codevs2912. 题目大意:对于任何正整数x,其约数的个数记作g(x).例如g(1)=1.g(6)=4. 如果某个正整数x满足:g ...
- eclipse调试(debug)弹出错误
原创:http://www.cnblogs.com/lanhj/p/3874426.html 警告信息: Cannot connect to VM com.sun.jdi.connect.Transp ...