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


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

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

3 74

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 может вызвать исключение или он может заблокировать, если a заблокированный поток владеет монитором счетчика.

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

  1. классы Java последовательно имеют или не имеют свойства и методы, поэтому инварианты интерфейса просты в обслуживании.
  2. классы Java могут защитить их private поля, поэтому инварианты, которые полагаются на личные данные, легко поддерживать.
  3. классы Java могут быть окончательными, таким образом, инварианты, которые полагаются на отсутствие кода, который нарушает инвариант, создавая вредоносный подкласс, могут поддерживаться.
  4. Java позволяет null значения, чтобы проникнуть во многих отношениях, так что трудно поддерживать "имеет реальное значение" инварианты.
  5. Java имеет потоки, что означает, что классы, которые не синхронизируются, имеют проблемы с поддержанием инвариантов, которые полагаются на последовательные операции в потоке, происходящем вместе.
  6. Java имеет исключения, что делает его легко поддерживать инварианты, такие как" возвращает результат со свойством p или не возвращает результата", но сложнее поддерживать инварианты, такие как"всегда возвращает результат".

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

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

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

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

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

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

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

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

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

например,

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

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

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