文档章节

OpenJDK源码研究笔记(十五):吐槽JDK中的10个富有争议的设计

FansUnion
 FansUnion
发布于 2015/05/03 01:30
字数 1349
阅读 14
收藏 0

前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会有警告,黄色的感叹号还是比较烦人的。

相关阅读

我的CSDN博客专栏  OpenJDK源码研究笔记

OpenJDK源码研究过程中整理的学习笔记。 OpenJDK是GPL许可(GPL-licensed)的Java平台的开源实现。

原文参见http://FansUnion.cn/articles/3174(小雷网-FansUnion.cn)

© 著作权归作者所有

FansUnion
粉丝 60
博文 858
码字总数 825464
作品 0
丰台
高级程序员
私信 提问
openJdk和sun jdk的区别

使用过LINUX的人都应该知道,在大多数LINUX发行版本里,内置或者通过软件源安装JDK的话,都是安装的OpenJDK, 那么到底什么是OpenJDK,它与SUN JDK有什么关系和区别呢? 历史上的原因是,Ope...

jason_kiss
2018/06/18
368
0
Skara 开源,JDK 源码管理与审查选项研究工具

OpenJDK 官方宣布开源 Project Skara 工具。Project Skara 是官方 OpenJDK 上游 Mercurial 存储库基于 GitHub 原型的镜像,其旨在研究用于 JDK 源代码的源码管理和代码审查的备选项,包括基于...

afterer
06/26
2.1K
0
CentOS为OpenJDK设置系统变量

转载著名出处:http://www.crazyphper.com/?p=2328 今天在安装phpstorm时,提示无法找到JAVA_HOME,才想起还没有安装JDK呢!那就来试试linux上的openJDK吧! Centos自带OpenJDK的Runtime(JRE...

konakona
2012/09/22
10.7K
2
openjdk和oraclejdk有什么区别吗?

1.授权协议的不同:OpenJDK采用GPL V2协议放出,而SUN JDK则采用JRL放出。两者协议虽然都是开放源代码的,但是在使用上的不同在于GPL V2允许在商业上使用,而JRL只允许个人研究使用。 2.Open...

吴伟祥
2018/11/19
49
0
JDK 源码管理与审查选项研究工具 - Skara

Skara 是一个研究用于 JDK 源码管理和代码审查的备选项的工具。 Project Skara 是官方 OpenJDK 上游 Mercurial 存储库基于 GitHub 原型的镜像,其旨在研究用于 JDK 源代码的源码管理和代码审...

匿名
06/25
432
0

没有更多内容

加载失败,请刷新页面

加载更多

setState() called after dispose() flutter

# 在setState前加入以下判断if (!mounted) return;

zdglf
17分钟前
3
0
docker和docker-compose二种方式安装mysql8.0

Docker方式安装 在命令行下运行 docker run -d -p 3306:3306 --restart always --privileged=true--name mysql-e MYSQL_USER="test" -e MYSQL_PASSWORD="test" -e MYSQL_ROOT_PASSWOR......

小白的成长
26分钟前
5
0
五大网络威胁应对挑战

既然如此,那么威胁的检测和响应过程是否像生产瑞士手表那样高效运行呢?答案远非如此。据ESG报告显示,威胁检测和响应过程充满各种各样的问题。来自372名企业网络安全和IT专家的数据,以下是...

linuxCool
27分钟前
4
0
jQuery 选择器使用大全(标签选择器,ID选择器等)

jQuery的选择器是CSS 1-3,XPath的结合物。jQuery提取这二种查询语言最好的部分,融合后创造出了最终的jQuery表达式查询语言。如果你了解CSS(绝大部分WEB开发者都用到的),那么你学起来就很...

前端老手
33分钟前
4
0
HBase四种部署模式和基本操作

本文主要包括两部分的内容,第一部分主要包HBase的四种安装方法,分别是:① 单机版模式,② 伪集群模式,③ 使用HBase自带的zookeeper构建分布式集群,④ 使用独立安装的zookeeper构建分布式...

繁荣3000
41分钟前
4
0

没有更多内容

加载失败,请刷新页面

加载更多

返回顶部
顶部