Open8

Effective Java 再履修

SHAMOJISHAMOJI

オブジェクトの生成と消滅

コンストラクタの代わりにstaticファクトリメソッドを検討する

こんなやつ

public class Boolean {
    public static Hoge valueOf(boolean b) {
        return b ? Boolean.TRUE : Boolean.FALSE;
    }
}

自然とやってるな。Effective Java起因だったのか。

命名規則みてると「あるあるー」って感じ。

// from
// 単一のパラメータを受け取り、対応するインスタンスを返却する
Date d = Date.from(instant);
// of
// 複数のパラメータを受け取り、それらを含んだインスタンスを返却する
Set<Rank> faceCards = EnumSet.of(JACK, QUEEN, KING);
// valueOf
// from や of の代わり
BigInteger prime = BigInteger.valueOf(Integer.MAX_VALUE);
// instance or getInstance
// パラメータがあれば、そのパラメータで表されているインスタンスを返却するが、必ずしも同じ値とは限らない
StackWalker luke = StackWalker.getInstance(options);
// create or newInstance
// instanceやgetInstanceに似ているが、呼び出しごとに新しいインスタンスを返却する
Object newArray = Array.newInstance(classObject, arrayLen);
// getType
// ファクトリメソッドが対象のクラスとは異なる場合に使用
FileStore fs = Files.getFileStore(path);
// newType
// 同上
BufferedReader br = Files.newBufferedReader(path);
// type
// getTypeやnewTypeの代わり
List<Complaint> litany = Collections.list(legacyLitany);

でもfromとofの使い分け(単数か複数か)は明確に言語化できていなかったな。
きっと何でやねん、コードをたくさん書いてしまった気がする(自戒)

メリット1::コンストラクタと異なり、名前を持つ

コンストラクタと違って、生成されるインスタンスを明確に表現できるのが強み、ってことかな

メリット2:コンストラクタと異なり、その呼び出しごとに新たにオブジェクトを生成する必要がない

Singletonのお話かな。冒頭のBooleanも新しいインスタンス返してないな。

メリット3:コンストラクタと異なり、メソッドの戻り値型の任意のサブタイプのオブジェクトを返せる

タイトルは分かるが、使い所があまり浮かばないな。自然とやってたりするのだろうか

メリット4:返されるオブジェクトのクラスは、入力パラメータの値に応じて呼び出しごとに変えられる

あまりstaticメソッドが返却するオブジェクトを入力パラメータ毎に変更したことがないな。
別言語でEnumのvalueOfを自前実装した時くらいかな。

メリット5:返されるオブジェクトのクラスは、そのstaticファクトリメソッドを含むクラスが書かれた時点で存在する必要さえない

デメリット1:publicあるいはprotectedのコンストラクタを元ないクラスのサブクラスは作れない

うーん。何の問題もないな。

デメリット2:プログラマがstaticファクトリメソッドを見つけることが難しい

「Javadocツールはいつの日かstaticファクトリメソッドに注意を払うかもしれない」
そんな日はまだ来てません(2022年7月19日 現在)

SHAMOJISHAMOJI

オブジェクトの生成と消滅

多くのコンストラクタパラメータに直面した時はビルダーを検討する

これも当たり前のようにやってたな。
どこで覚えたんだろう。たぶんAndroidのアプリ作ってた時だな。

public class Profile {
    private final String firstName;
    private final String lastName;
    private final String sex;
    private final Integer height;
    private final Integer weight;

    public static class Builder {
        // 必須
        private final String firstName;
        private final String lastName;
        private final String sex;

        // 任意
        private Integer height = null;
        private Integer weight = null;

        public Builder(String firstName, String lastName, String sex) {
            this.firstName = firstName;
            this.lastName = lastName;
            this.sex = sex;
        }	
        
        public Builder height(Integer height) {
            this.height = height;
            return this;
        }

        public Builder weight(Integer weight) {
            this.weight = weight;
            return this;
        }

        public Profile build() {
            return new Profile(this)
        }
    }

    private Profile(Builder builder) {
        this.firstName = builder.firstName;
        this.lastName = builder.lastName;
        this.sex = builder.sex;
        this.height = builder.height;
        this.weight = build.weight;
    }
}
SHAMOJISHAMOJI

オブジェクトの生成と消滅

private のコンストラクタでインスタンス化不可能を強制する

Utilityクラスでよく見るやつね。

おそらくstaticおじさん達も多用したんだろうな。。。(遠い目)

public class StaticOjisan {
    private StaticOjisan() {
        throw new AssertionError();
    }
}
SHAMOJISHAMOJI

オブジェクトの生成と消滅

資源を直接結びつけるよりも依存性注入を選ぶ

え、これ、みんな息をするように使ってないか。

SHAMOJISHAMOJI

オブジェクトの生成と消滅

不必要なオブジェクトの生成を避ける

現代ではあまり気にならないだろうけど、パフォーマンスチューニングの技として覚え得ておきたい。

SHAMOJISHAMOJI

オブジェクトの生成と消滅

使われなくなったオブジェクトの参照を取り除く

GC様に全て委ねています。すみません。
あと配列を直で操作することってもう殆どないんじゃないかな。

SHAMOJISHAMOJI

オブジェクトの生成と消滅

ファイナライザとクリーナーを避ける

うーん、恥ずかしながらこの辺りも使ったことない、というか意識したことがない。
try-with-resourcesとかは使うけど。

SHAMOJISHAMOJI

オブジェクトの生成と消滅

try-finallyよりもtry-with-resourcesを選ぶ

この辺は過渡期だどコーディング規約に入ってるレベルではないのか。
まぁあまり理由が説明されることはなかったけど。