LoginSignup
1
2

More than 5 years have passed since last update.

Effective Java 3章

Posted at

3章.全オブジェクト共通のメソッド

  • この章ではObjectsのメソッドオーバーライド方法を中心にまとめられている。

10.equalsのoverrideは一般契約(general contracts)に従うべし

  • 一般契約とは、反射性(reflexive),対照性(symmetric),推移性(transitive),整合性(consistent),非 null 性(non-null)のこと。
  • googleのAutoValueを使えば、うまくequalsのオーバーライドを行ってくれる。

11.equalsをオーバーライドする場合はhashcodeもオーバーライドせよ

  • hashCodeの一般契約によると、等しい2つのオブジェクトは等しいhashCodeの値を返さねばならない。よって、equalsをオーバーライドして、論理的に等しいが同じ参照ではない場合も等しいとする場合には、hashCodeをオーバーライドしないままだと異なった値を返すことになってしまう。

  • 性能を気にする場合は、hashCodeで計算された値をキャッシュしておく。

12.常にtoStringをオーバーライドせよ

  • Thread.javaのtoStringは以下のよう。
    public String toString() {
        ThreadGroup group = getThreadGroup();
        if (group != null) {
            return "Thread[" + getName() + "," + getPriority() + "," +
                           group.getName() + "]";
        } else {
            return "Thread[" + getName() + "," + getPriority() + "," +
                            "" + "]";
        }
    }

13.cloneをオーバーライドするときは注意せよ

  • super.cloneを呼んでキャストをする。mutableな変数がある場合はdeepcopyして対応する。

  • 大体の場合において、cloneメソッドでオブジェクトのコピーを作るよりも、コンストラクタやファクトリメソッドで作るほうが容易である。唯一、配列のコピーはcloneのほうがうまくやれる。

14.Comparableを実装することを考慮せよ

  • Javaライブラリの値クラスは、enumも含めておおむねComparableを実装している。
  • BigDecimalについて、equalsではBigDecimal("1.0")とBigDecimal("1.00")は異なる扱いになるが、compareToでは同じ扱いになる。そのため、HashSetにこれらの2つを入れたときには、2つの要素が残るが、TreeSetに入れた場合には、1つになる。
  • compareToの中で、不等号を使って比較を行うことは冗長で、エラーの要因となりうるので、プリミティブ型のラッパークラスのcompareを使うべき。
  • 複数キーでのソートを考える場合、Comparatorのコンストラクションメソッドを使うことを考慮に入れる。1つずつ比較して、if文で分けていくよりもこちらのほうが性能が良いらしい。
package tryAny.effectiveJava;

import static java.util.Comparator.*;
import java.util.Comparator;
import java.util.stream.Stream;

public class CompareTest {
    public static void main(String[] args) {
    Stream<PhoneNum> s = Stream.of(new PhoneNum(111, 222, 333), new PhoneNum(111, 222, 222),
        new PhoneNum(111, 333, 111), new PhoneNum(000, 999, 1));
    s.sorted().forEach(System.out::println);
    }
}

class PhoneNum implements Comparable<PhoneNum> {
    int areaCode;
    int prefix;
    int lineNum;

    public PhoneNum(int areaCode, int prefix, int lineNum) {
    this.areaCode = areaCode;
    this.prefix = prefix;
    this.lineNum = lineNum;
    }

    private static final Comparator<PhoneNum> COMPARATOR = comparingInt((PhoneNum pn) -> pn.areaCode)
        .thenComparingInt(pn -> pn.prefix).thenComparingInt(pn -> pn.lineNum);

    @Override
    public int compareTo(PhoneNum pn) {
    return COMPARATOR.compare(this, pn);
    }

    @Override
    public String toString() {
    StringBuilder sb = new StringBuilder();
    sb.append("areaCode:").append(areaCode).append(",prefix:").append(prefix).append(",lineNum:").append(lineNum);
    return sb.toString();
    }
}
1
2
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
1
2