OpenJDKソース研究ノート(十五):JDKの中の10の論争に富んだ設計にツッコミを入れる


最初の14の文章は、JDKで学ぶべきコードと設計方法を共有しています.
コインごとに両面があります.Every coin has two sides.
もちろん、JDKにも改善や議論に値するデザインがたくさんあります.
本編では、JDKの中の10の議論に富んだデザインについて詳しく突っ込みます.
ネットユーザーは1.異常を求めて投げて、誤ったヒントは合理的ではありません.
OpenJDKソース研究ノート(一)-パラメータチェック&キーエラーメッセージ付きの異常を投げ出すこの記事で、あるネットユーザーは「3番目のifのヒント情報に問題がある.前の2つの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ソース研究ノート(三)-ReandomAccessなどのタグインタフェースの役割この文章では、あるネットユーザーが「空のインタフェース、例えばSerializableなどは、一つの記号にすぎず、実用的なannotationが適切だ」と指摘している.
例えばArrayListの定義はclass ArrayList implements Serialiable{}である.
@Serializeclass ArrayList{}のいくつかの観点に変更できます
a.注記はJDK 1.5ならではです.以前のAPIはもちろんサポートすべきだった.注釈なら、いいと思います.簡潔に見えないかもしれません.空のインタフェースを実現するにはinstanceofが便利です.
b.インタフェースを実現しても、注釈を使ってもいい.最終的には,いずれも1つの設計の2つの異なる実装である.実装インタフェースはInstance of,注釈呼び出しメソッドを用いる.インタフェースを使用すると、以前のコードとよりよく互換性があります.c.互換性の観点から見ると、確かにそうです.しかし、設計目的から見ると、注釈のほうがいいです.また、オブジェクト継承構造に影響を及ぼさず、タグを付けます.
メソッド定義3.定義方法を繰り返します.
 
public interface List<E> extends Collection<E>{

    int size();
    boolean isEmpty();

}

親インタフェースCollectionを継承した以上、親にすでに存在するインタフェースを繰り返し定義するのはなぜですか?
public interface Setextends Collectionなどのインタフェースの定義も同様である.
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<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);
この方法の実装は,実際には「可変」のリスト実装を返す.
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();
  }

}

それらのリストを修正する方法を,異常を投げ出すように実現する.
ソースコードを見る前に、私はいつも他の方法があるような気がします.
ソースコードがこのように実現されているのを見て、私は少しがっかりしました.
考えすぎたようだ.
 8.パラメータチェックが不合理です. 
java.util.logging.Handler.setFormatter(Formatter)
 
 public void setFormatter(Formatter newFormatter) throws SecurityException {
  checkAccess();
  // Check for a null pointer:
  newFormatter.getClass();
  formatter = newFormatter;
 }

単純にクラスを呼び出す方法ですgetClass();をクリックして、クラスがnullであるかどうかを確認します.
この方法はもっといいですか?
if(newFormatter==null){
    throw new NullPointerException("");

コーディング習慣
 9.If文のかっこの問題.ほとんどの文は1つの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)