web-dev-qa-db-ja.com

Javaのクラス不変式とは何ですか?

私はこのトピックをグーグルで検索しましたが、 Wikipedia に加えて、これ以上役立つドキュメントや記事は見つかりませんでした。

誰でも簡単な言葉でそれが何を意味するのか説明したり、素敵でわかりやすいドキュメントを紹介してくれたりできますか?

82
Saurabh Kumar

Javaに関して特に意味はありません。

クラス不変式は、他のコードが何をするかに関係なく、常にクラスのすべてのインスタンスを保持するプロパティです。

例えば、

class X {
  final Y y = new Y();
}

Xにはyプロパティがあり、決してnullではなく、Y型の値を持つというクラス不変式があります。

class Counter {
  private int x;

  public int count() { return x++; }
}

2つの重要な不変式を維持できない

  1. アンダーフローの可能性があるため、そのcountは決して負の値を返しません。
  2. countの呼び出しは、厳密に単調に増加しています。

変更されたクラスは、これら2つの不変式を保持します。

class Counter {
  private int x;

  public synchronized int count() {
    if (x == Integer.MAX_VALUE) { throw new IllegalStateException(); }
    return x++;
  }
}

しかし、countへの呼び出しが常に正常に成功する不変式を保存することに失敗します(TCB違反がない場合countは例外をスローするか、デッドロックスレッドがカウンターのモニターを所有している場合にブロックする可能性があるためです。

クラスを含む各言語を使用すると、一部のクラス不変式を簡単に維持できますが、他の不変式は維持できません。 Javaも例外ではありません:

  1. Javaクラスには一貫してプロパティとメソッドがあるかどうかがあるため、インターフェイスの不変式は簡単に管理できます。
  2. Javaクラスはprivateフィールドを保護できるため、プライベートデータに依存する不変式は簡単に維持できます。
  3. Javaクラスは最終クラスになる可能性があるため、悪意のあるサブクラスを作成して不変条件に違反するコードがないことに依存する不変条件を維持できます。
  4. Javaではnullの値をさまざまな方法で忍び込ませることができるため、「実際の値を持つ」不変式を維持するのは困難です。
  5. Javaにはスレッドがあります。つまり、同期しないクラスは、スレッド内の連続した操作が同時に発生することに依存する不変式の維持に問題があります。
  6. Javaには例外があり、「プロパティpで結果を返す、結果を返さない」などの不変式を簡単に維持できますが、「常に結果を返す」などの不変式を維持するのは困難です。

†-externalityまたは[〜#〜] tcb [〜#〜] violationは、システム設計者が楽観的に発生しないと想定するイベントです。

通常、基本的なハードウェアは、その上に構築された高レベル言語のプロパティについて説明するときに宣伝どおりに機能することを信頼し、不変式が保持する引数は次の可能性を考慮しません:

  • デバッグフックを使用して、プログラムではコードでは不可能な方法でローカル変数を変更するプログラマー。
  • ピアはsetAccessibleでリフレクションを使用してprivateルックアップテーブルを変更しません。
  • Lokiが物理を変更すると、プロセッサが2つの数値を誤って比較します。

一部のシステムでは、TCBにシステムの一部のみが含まれる場合があるため、以下のことを想定しない場合があります。

  • 管理者または特権デーモンがJVMプロセスを強制終了することはありませんが、

しかし、我々はそれを仮定するかもしれません

  • 信頼できるトランザクションファイルシステムへのチェックポイントを作成できます。

システムのレベルが高いほど、そのTCBは通常大きくなりますが、TCBから取得できる信頼性の低いものほど、不変式が保持される可能性が高くなり、システムの長期的な信頼性が高まります。

81
Mike Samuel

不変式とは、どのような変更またはそれを使用/変換しても、その条件に固執するものを意味します。つまり、クラスのプロパティは、パブリックメソッドを使用して変換を行った後でも、常にいくつかの条件を満たしているか満たしています。したがって、このクラスのクライアントまたはユーザーは、クラスとそのプロパティについて保証されます。

例えば、

  1. 関数の引数の条件は、常に0より大きい(ゼロより大きい)か、nullであってはならないということです。
  2. アカウントクラスのminimum_account_balanceプロパティは、100を下回ることはできません。したがって、すべてのパブリック関数はこの条件を尊重し、クラス不変を保証する必要があります。
  3. 変数間のルールベースの依存関係、つまり、1つの変数の値は別の変数に依存するため、ある修正ルールを使用して変更した場合、他の変数も変更する必要があります。 2つの変数間のこの関係は保持する必要があります。そうでない場合は、不変式に違反しています。
16
aab10

これらは、インスタンスクラスについて真実でなければならない事実です。たとえば、クラスにプロパティXがあり、不変式はXが0より大きくなければならない場合です。私の知る限り、不変式を維持するための組み込みメソッドはありません。

リフレクションとインターセプターを使用してプロパティをチェックできる注釈があります。 http://docs.Oracle.com/javaee/7/api/javax/validation/constraints/package-summary.html

9
Usman Ismail