Что такое инвариант класса в Java?

я погуглил тему, но кроме Википедия Я не нашел никакой дополнительной полезной документации или статей.

может ли кто-нибудь объяснить мне простыми словами, что это значит, или сослаться на какую-нибудь приятную и легкую для понимания документацию?

3 ответов


это ничего не значит, в частности, в отношении java.

инвариант класса-это просто свойство, которое выполняется для всех экземпляров класса всегда, независимо от того, что делает другой код.

например,

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

X имеет инвариант класса, что существует y свойство и это никогда null и имеет значение типа Y.

class Counter {
  private int x;

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

не удается сохранить два важных инварианты

  1. это count никогда не возвращает отрицательное значение из-за возможной потери точности.
  2. что вызовов count строго монотонно возрастающей.

модифицированный класс сохраняет эти два инварианта.

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 или не возвращает результата", но сложнее поддерживать инварианты, такие как"всегда возвращает результат".

† - An внешнее или TCB нарушение - это событие, которое системный дизайнер оптимистично предполагает, что не произойдет.

обычно мы просто верим, что основное оборудование работает так, как рекламируется, когда речь идет о свойствах высокого уровня языки, построенные на них, и наши аргументы, которые придерживаются инвариантов, не учитывают возможность:

  • программист, использующий отладочные крючки для изменения локальных переменных, поскольку программа работает так, как код не может.
  • ваши сверстники не используют отражение с setAccessible изменить private таблицы подстановки.
  • Loki изменение физики в результате чего ваш процессор неправильно сравнить два числа.

для некоторых систем наш TCB может включите только части системы, поэтому мы не можем предположить, что

  • администратор или привилегированный демон не убьет наш процесс JVM,

но мы могли бы предположить, что

  • мы можем проверить надежную транзакционную файловую систему.

чем выше уровень системы, тем больше ее TCB обычно, но чем более ненадежные вещи вы можете получить из своего TCB, тем более вероятно, что ваши инварианты будут держаться, и более надежной ваша система будет в долгосрочной перспективе.


инвариант означает то, что должно придерживаться его условий независимо от того, какие изменения или кто его использует/преобразует. То есть свойство класса всегда выполняет или удовлетворяет некоторому условию даже после прохождения преобразований с помощью общедоступных методов. Таким образом, клиент или пользователь этого класса обеспечивается о классе и его собственность.

например,

  1. условие аргумента функции заключается в том, что он всегда должен быть > 0 (больше, чем zero) или не должно быть null.
  2. minimum_account_balance свойство класса счета состояния, он не может идти ниже 100. Поэтому все публичные функции должны уважать это условие и обеспечивать инвариант класса.
  3. зависимость на основе правил между переменными, то есть значение одной переменной зависит от другой, поэтому, если одно изменение, используя некоторое правило fix, другое также должно измениться. Эта связь между 2 переменными должна быть сохранена. Если это не так, то инвариант нарушаться.

Это факты, которые должны быть верны для класса экземпляра. Например, если класс имеет свойство X и инвариант может быть X должен быть больше 0. Насколько мне известно, нет встроенного метода для поддержания инвариантов, вы должны сделать свойства частными и убедиться, что ваши геттеры и сеттеры применяют свойство инвариантности.

доступны аннотации, которые могут проверять свойства с помощью отражения и ракет-перехватчиков. http://docs.oracle.com/javaee/7/api/javax/validation/constraints/package-summary.html