Java에서 클래스 불변이란 무엇입니까?


93

주제를 검색했지만 위키피디아 외에는 유용한 문서 나 기사를 찾지 못했습니다.

아무도 그것이 의미하는 바를 간단한 말로 설명하거나 멋지고 이해하기 쉬운 문서를 참조 할 수 있습니까?


2
위키피디아 페이지에는 내가 당신이 할 수 있다는 것을 알지 못했던 정말 훌륭한 예가 있기 때문에 질문에 +1하십시오. 그들의 설명은 내가 당신을 위해 할 수있는 것보다 낫습니다. 매우 간단합니다.
iandisme


Java에 대한 불변성에 관심이 있다면 Java 계약에 관심이있을 것 입니다.
Mike Samuel

답변:


91

Java와 관련하여 특별히 의미하는 것은 아닙니다.

클래스 불변은 다른 코드가 수행하는 작업에 관계없이 항상 클래스의 모든 인스턴스를 유지하는 속성입니다.

예를 들면

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

X는 y속성이 있고 결코 존재하지 않으며 nulltype 값을 갖는다 는 불변 클래스를 가지고 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로 결과를 반환하거나 결과를 반환하지 않음"과 같은 불변성을 유지하기 쉽게하는 예외가 있지만 "항상 결과를 반환합니다"와 같은 불변성을 유지하기가 더 어렵습니다.

†- 외부 성 또는 TCB 위반 은 시스템 설계자가 낙관적으로 발생하지 않을 것이라고 가정하는 이벤트입니다.

일반적으로 우리는 기본 하드웨어가 그 위에 구축 된 고급 언어의 속성에 대해 이야기 할 때 광고 된대로 작동한다고 믿고 불변성이 보유하고있는 우리의 주장은 다음 가능성을 고려하지 않습니다.

  • 프로그램이 코드가 할 수없는 방식으로 실행될 때 디버그 후크를 사용하여 지역 변수를 변경하는 프로그래머.
  • 피어는 리플렉션을 사용 setAccessible하여 private조회 테이블 을 수정 하지 않습니다 .
  • Loki가 물리학을 변경하여 프로세서가 두 숫자를 잘못 비교합니다.

일부 시스템의 경우 TCB는 시스템의 일부만 포함 할 수 있으므로

  • 관리자 또는 권한있는 데몬은 JVM 프로세스를 종료하지 않습니다.

하지만 우리는

  • 신뢰할 수있는 트랜잭션 파일 시스템을 검사 할 수 있습니다.

시스템의 수준이 높을수록 일반적으로 TCB가 더 커지지 만 TCB에서 얻을 수있는 불안정한 항목이 많을수록 불변성이 유지 될 가능성이 높아지고 장기적으로 시스템의 안정성이 높아집니다.


1
" count동일한 값을 두 번 반환하지 않는다"는 것이 실제로 클래스 불변으로 간주됩니까?
ruakh

@ruakh, 좋은 질문입니다. 잘 모르겠습니다. hashCode 안정성 (각 인스턴스 i에 대해 i.hashCode ()는 변경되지 않음)과 같은 것들은 종종 이전에 반환 된 값에 대한 추론이 필요한 클래스 불변이라고 불립니다. 따라서 "각 인스턴스 i에 대해 i.count () not in (i.count ()의 이전 결과) "는 클래스 불변입니다.
Mike Samuel

@ruakh 순수한 정의가 아닌가? 그러한 불변성을 가정한다면 왜 안됩니까? 확실히 흥미롭고 중요한 보증이 될 수 있습니다 (예 : 고유 ID 생성). 개인적으로도 "단일 스레드 코드 만이 클래스에 액세스하면 다음 속성이 유지됩니다"와 같은 것이 유용하다고 생각합니다. 조건이 참입니다. (그리고 고려 반사 그렇지 않으면 보증 아무것도 흥미에 기본적으로 불가능!)
Voo

1
@ruakh-클래스 불변 또는 메서드 불변으로 모델링 할 수 있습니다. 어느 쪽이든이를 모델링하려면 특정 개체에 대한 메서드에 대한 이전 호출의 개념적 기록이 필요합니다. 사실,이를 메서드에 대한 사후 조건으로 모델링 할 수도 있습니다. 즉, 결과 값은 이전에 반환되지 않은 값입니다.
Stephen C

@Voo : Re : "그건 순수한 정의가 아닌가?": 물론입니다.하지만 여기서 질문은 " '클래스 불변'이란 무엇입니까?"이므로 정의는 100 % 관련성이 있다고 생각합니다. 가능한 한 명확한 예를 사용하거나 명확하지 않은 사례를 명시 적으로 호출하는 것이 바람직합니다. (내가 그냥 놀랐다하고 있는지 확인하기 위해 요청 된 I 적극적으로 방법으로, 예와 의견이 맞지 않을거야.)
ruakh

20

Invariant는 변경 사항이나 사용 / 변형에 관계없이 조건을 고수해야하는 것을 의미합니다. 즉, 클래스의 속성은 public 메서드를 사용하여 변형을 거친 후에도 항상 어떤 조건을 충족하거나 만족시킨다. 따라서이 클래스의 클라이언트 또는 사용자는 클래스 및 해당 속성에 대해 보장됩니다.

예를 들면

  1. 함수 인수의 조건은 항상> 0 (0보다 큼)이거나 null이 아니어야한다는 것입니다.
  2. 계정 클래스의 minimum_account_balance 속성은 100 이하로 내려갈 수 없습니다. 따라서 모든 공용 함수는이 조건을 존중하고 클래스 불변성을 보장해야합니다.
  3. 변수 간의 규칙 기반 종속성, 즉 한 변수의 값이 다른 변수에 종속되므로 하나가 변경되면 일부 수정 규칙을 사용하여 다른 변수도 변경되어야합니다. 두 변수 간의이 관계는 유지되어야합니다. 그렇지 않으면 불변이 위반됩니다.

11

인스턴스 클래스에 대해 사실이어야하는 사실입니다. 예를 들어 클래스에 X 속성이 있고 불변이 X는 0보다 커야합니다. 내 지식으로는 속성을 비공개로 설정하고 getter와 setter가 불변 속성을 적용하는지 확인해야합니다.

리플렉션과 인터셉터를 사용하여 속성을 확인할 수있는 주석이 있습니다. http://docs.oracle.com/javaee/7/api/javax/validation/constraints/package-summary.html

당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.