done is better than perfect

自分が学んだことや、作成したプログラムの記事を書きます。すべての記載は他に定める場合を除き個人的なものです。

JavaのUnmodifialeMapの使い道について

自分向け備忘録

下記のコードの問題点を考える。

class CustomerRecords {
    private Map<String, Customer> records;
    public Map<String, Customer> getCustomers() {
        return this.records;
    }
}

getCustomers() がreferenceを返してしまっているので、カプセル化に失敗していますね。

では、以下ではどうでしょうか。

class CustomerRecords implements Iterable<Customer> {
    private Map<String, Customer> records;
    public Map<String, Customer> getCustomers() {
        return this.records;
    }
    @Override
    public Iterator<Customer> iterator() {
         return records.values().iterator();
    }
}

マシですが、実はiteratorにはremoveメソッドがあるので、これも完璧なソリューションではないです。

なら、コピーしたオブジェクトを返せばいいのでは??

class CustomerRecords implements Iterable<Customer> {
    private Map<String, Customer> records;
    public Map<String, Customer> getCustomers() {
        return new Map<String, Customer>(this.records);
    }
    @Override
    public Iterator<Customer> iterator() {
         return records.values().iterator();
    }
}

これも完璧ではない。なぜなら、コピーしたオブジェクトが更に参照しているオブジェクトは、同じ参照を保持している可能性があるから。

ということで、UnmodifiableMapを使いましょう。

class CustomerRecords {
    private Map<String, Customer> records;
    public Map<String, Customer> getCustomers() {
        return Collections.unmodifiableMap(this.records);
    }
}