1

finalキーワードがオブジェクトへの定数参照を作成することはわかっています。例えば:

final Object object = new Object();

ただし、この場合、オブジェクトへの参照のみが固定され、プログラムの実行実行中に変更することはできません。このオブジェクトでsetterメソッドを呼び出して、そのデータメンバーの値を変更することもできます。Javaでこれを防ぐ方法はありますか(C ++のconstに相当)?

このオブジェクトクラスにセッターを定義するべきではない、または値の設定を1回だけ許可する必要がある方法を理解していますが、このオブジェクトを関数の引数として渡し、その関数がこのオブジェクトの値を変更したくない場合はどうなりますか?データメンバー。それでも関数の外で値を変更したい場合があります。

その場合、関数プロトタイプはどうあるべきですか?

4

4 に答える 4

4

秘訣は、オブジェクトへの読み取り専用インターフェイスを定義し、次のようにセッターのみをクラスに配置することです。

public interface ConstInterface {
    int getFirst();
    String getSecond();
}

public class MutableClass implements ConstInterface {
    private int _first;
    private String _second;
    int getFirst() {
        return _first;
    }
    void setFirst(int f) {
        _first = f;
    }
    String getSecond() {
        return _second;
    }
    void setSecond(String s) {
        _second = s;
    }
}

final ConstInterface obj = new MutableClass();

この時点で、objそのインターフェイスを介して読み取り専用としてアクセスできます。プロパティを設定する必要がある場合は、 にキャストobjMutableClassてセッターを呼び出します。

于 2012-10-29T06:29:48.563 に答える
3

しかし、このオブジェクトを引数として関数に渡し、その関数がこのオブジェクトのデータメンバーの値を変更したくない場合はどうなりますか。それでも関数の外で値を変更したい場合があります。

その場合、オブジェクト自体ではなく、オブジェクトのクローンをメソッドに渡す必要があります。

于 2012-10-29T06:26:13.253 に答える
2

いくつかの解決策があります。

  1. まず、設計によって解決できます。オブジェクトの状態を変更できるメソッドを持たないインターフェイスを作成します。たとえば、ゲッターのみが含まれます。現在、変数の型はインターフェイスです。クライアントは状態を変更できません。
  2. クラスがインターフェイスを実装している場合は、セッターの呼び出しを防ぐ動的プロキシを使用してラップできます。ところで、クラスが実際にコレクションまたはマップである場合、使用するCollections.unmodifireableMap()Collections.unmodifireableList()、実際に変更不可にすることができます。
  3. バイトコードエンジニアリングを使用できます。これは、クラスがインターフェイスを実装していない場合でも機能します。これには 2 つの方法があります。javassist や cglib などのライブラリを使用すると、具象クラスをラップする動的プロキシを作成できます。したがって、これらのライブラリのいずれかを利用して作成されたプロキシを使用して、オブジェクトをラップできます。セッターが呼び出されると、プロキシは例外をスローします。
  4. コンパイル時にバイト コードの変更を使用します。たとえば、AspectJ が役に立ちます。
于 2012-10-29T06:31:31.023 に答える
0

別のオプションは、オブジェクトの状態を変更し、代わりに例外をスローするか、ノーオペレーションを実行するすべてのメソッドをオーバーライドするデリゲートを作成することです。

于 2012-10-29T06:28:53.630 に答える