Что такое инвариант класса в Java? - PullRequest
82 голосов
/ 18 января 2012

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

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

Ответы [ 3 ]

81 голосов
/ 18 января 2012

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

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

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

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

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

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

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

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

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

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

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

15 голосов
/ 25 октября 2013

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

Например,

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

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

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

...