Help us understand the problem. What is going on with this article?

Effective Java 3章

More than 1 year has passed since last update.

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();
    }
}
nannany
Why not register and get more from Qiita?
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away
Comments
No comments
Sign up for free and join this conversation.
If you already have a Qiita account
Why do not you register as a user and use Qiita more conveniently?
You need to log in to use this function. Qiita can be used more conveniently after logging in.
You seem to be reading articles frequently this month. Qiita can be used more conveniently after logging in.
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away
ユーザーは見つかりませんでした