java 지역변수 자바 주장 키워드는 무엇을하며 언제 사용해야합니까?




자바 final 변수 (15)

단언의 주요 역할을 이해하기위한 실제 사례 는 무엇입니까?


어설 션은 사후 조건을 확인하고 사전 조건을 "절대로 실패해서는 안됩니다"라는 데 사용됩니다. 올바른 코드가 어설 션을 실패해서는 안됩니다. 그들이 방아쇠를 당길 때, 그들은 버그 (문제의 실제 궤적이있는 곳과 가까운 곳에 있기를 바랍니다)를 나타내야합니다.

어설 션의 예는 특정 순서의 메서드 그룹이 올바른 순서로 호출 hasNext() 하는 것입니다 (예 : hasNext()Iterator 에서 next() 보다 먼저 호출 됨).


Java에서 assert 키워드는 무엇을합니까?

컴파일 된 바이트 코드를 살펴 보겠습니다.

결론은 다음과 같습니다.

public class Assert {
    public static void main(String[] args) {
        assert System.currentTimeMillis() == 0L;
    }
}

다음과 같이 거의 동일한 바이트 코드를 생성합니다.

public class Assert {
    static final boolean $assertionsDisabled =
        !Assert.class.desiredAssertionStatus();
    public static void main(String[] args) {
        if (!$assertionsDisabled) {
            if (System.currentTimeMillis() != 0L) {
                throw new AssertionError();
            }
        }
    }
}

여기서, Assert.class.desiredAssertionStatus()-ea 가 명령 행에서 전달 될 때 true 이고, 그렇지 않으면 false입니다.

우리는 System.currentTimeMillis() 를 사용하여 최적화되지 않도록합니다 ( assert true; ).

synthetic 필드는 생성 될 때 Java가 단지 Assert.class.desiredAssertionStatus() 를로드 할 때 한 번 호출하면되고 그 결과를 거기에 캐시합니다. 또한보십시오 : "static synthetic"의 의미는 무엇입니까?

다음과 같이 확인할 수 있습니다.

javac Assert.java
javap -c -constants -private -verbose Assert.class

Oracle JDK 1.8.0_45에서는 합성 정적 필드가 생성되었습니다 (참조 : "정적 합성"의 의미는 무엇입니까? ) :

static final boolean $assertionsDisabled;
  descriptor: Z
  flags: ACC_STATIC, ACC_FINAL, ACC_SYNTHETIC

정적 이니셜 라이저와 함께 :

 0: ldc           #6                  // class Assert
 2: invokevirtual #7                  // Method java/lang Class.desiredAssertionStatus:()Z
 5: ifne          12
 8: iconst_1
 9: goto          13
12: iconst_0
13: putstatic     #2                  // Field $assertionsDisabled:Z
16: return

주요 방법은 다음과 같습니다.

 0: getstatic     #2                  // Field $assertionsDisabled:Z
 3: ifne          22
 6: invokestatic  #3                  // Method java/lang/System.currentTimeMillis:()J
 9: lconst_0
10: lcmp
11: ifeq          22
14: new           #4                  // class java/lang/AssertionError
17: dup
18: invokespecial #5                  // Method java/lang/AssertionError."<init>":()V
21: athrow
22: return

결론은 다음과 같습니다.

  • assert 위한 바이트 코드 수준의 지원이 없다 : 자바 언어 개념이다.
  • assert 는 시스템 속성에서 꽤 잘 에뮬레이트 될 수 있습니다. -Pcom.me.assert=true 명령 줄에서 -ea 를 바꾸고 throw new AssertionError() 합니다.

다음은 Hibernate / SQL 프로젝트를 위해 서버에서 작성한 어설 션입니다. 엔티티 bean에는 isActive 및 isDefault라는 두 개의 유효 부울 속성이 있습니다. 각각은 "Y"또는 "N"값 또는 "N"으로 처리 된 널 값을 가질 수 있습니다. 우리는 브라우저 클라이언트가이 세 가지 값으로 제한되는지 확인하려고합니다. 그래서,이 두 속성에 대한 제 설정 자에서이 어설 션을 추가했습니다.

assert new HashSet<String>(Arrays.asList("Y", "N", null)).contains(value) : value;

다음 사항에 유의하십시오.

  1. 이 주장은 개발 단계에만 해당됩니다. 클라이언트가 나쁜 값을 보내는 경우, 우리가 생산에 도달하기 오래 전에 그것을 잡아서 고칠 것입니다. 어설 션은 사용자가 일찍 잡을 수있는 결함에 대한 것입니다.

  2. 이 단언은 느리고 비효율적이다. 괜찮아. 어설 션은 자유롭게 느려질 수 있습니다. 개발 전용 도구이기 때문에 상관 없습니다. 어설 션이 비활성화되므로 프로덕션 코드가 느려지지 않습니다. (이 점에 대해서는 약간의 불일치가 있는데, 나중에 설명하겠다.) 이것이 나의 다음 요점으로 이어진다.

  3. 이 단언은 부작용이 없습니다. 수정 불가능한 정적 최종 세트에 대해 내 가치를 테스트 할 수는 있었지만, 그 세트는 결코 사용되지 않을 생산 환경에서 머물러 있었을 것입니다.

  4. 이 어설 션은 클라이언트의 올바른 작동을 확인하기 위해 존재합니다. 따라서 프로덕션에 도달 할 때까지는 클라이언트가 제대로 작동하고 있으므로 어설 션을 안전하게 해제 할 수 있습니다.

  5. 어떤 사람들은 이것을 묻습니다 : 프로덕션에서 어설 션이 필요하지 않다면, 끝내면 그냥 꺼내지 않는 이유는 무엇입니까? 다음 버전 작업을 시작할 때 여전히 필요하기 때문입니다.

어떤 사람들은 모든 버그가 사라 졌는지 절대 확신 할 수 없으므로 어설 션을 사용해서는 안된다는 주장을 했으므로 프로덕션 환경에서도이를 유지해야합니다. assert 문을 사용하는 것은 아무런 의미가 없습니다. 단점은 assert 문을 끌 수 있다는 것입니다. 그러므로이 생각에 따르면, 당신은 (거의) 주장을 사용해서는 안됩니다. 나는 동의하지 않는다. 테스트가 프로덕션 환경에 속한 경우에는 어설 션을 사용하지 않아야합니다. 그러나이 테스트는 프로덕션에 속하지 않습니다 . 이 도구는 프로덕션에 도달하지 않을 가능성이있는 버그를 잡기위한 것입니다. 따라서 작업이 끝나면 안전하게 끌 수 있습니다.

BTW, 나는 이것을 다음과 같이 쓸 수 있었다 :

assert value == null || value.equals("Y") || value.equals("N") : value;

3 개의 값만 유효하지만, 가능한 값의 수가 커지면 HashSet 버전이보다 편리해진다. 저는 효율성에 대한 요점을 나타 내기 위해 HashSet 버전을 선택했습니다.



어설 션은 코드의 버그를 잡기위한 개발 단계의 도구입니다. 그것들은 쉽게 제거 할 수 있도록 설계되었으므로 프로덕션 코드에는 존재하지 않습니다. 그래서 주장은 고객에게 제공하는 "솔루션"의 일부가 아닙니다. 그것들은 여러분이 가정하는 가정이 정확한지 확인하기위한 내부 검사입니다. 가장 일반적인 예는 null을 테스트하는 것입니다. 다음과 같이 많은 메소드가 작성됩니다.

void doSomething(Widget widget) {
  if (widget != null) {
    widget.someMethod(); // ...
    ... // do more stuff with this widget
  }
}

이와 같은 방법으로 매우 자주 위젯은 null이 될 수 없습니다. 따라서 null 인 경우 코드에 어딘가에 추적해야하는 버그가 있습니다. 그러나 위 코드는 결코 이것을 알려주지 않습니다. 따라서 "안전한"코드를 작성하려는 선의의 노력을 할 때도 버그를 숨길 수 있습니다. 다음과 같은 코드를 작성하는 것이 훨씬 더 좋습니다.

/**
 * @param Widget widget Should never be null
 */
void doSomething(Widget widget) {
  assert widget != null;
  widget.someMethod(); // ...
    ... // do more stuff with this widget
}

이렇게하면이 버그를 조기에 발견하게 될 것입니다. (계약에서이 매개 변수가 null이 아니어야 함을 지정하는 것도 유용합니다.) 개발 중에 코드를 테스트 할 때 어설 션을 켜야합니다. (그리고 동료를 설득하여이 일을하도록 설득하는 것은 종종 어렵 기 때문에 매우 성가시다.)

이제 동료 중 일부는 프로덕션 환경에서 예외를 방지하기 위해 계속 null 체크를 수행해야한다고 주장하면서이 코드를 거부합니다. 이 경우 어설 션은 여전히 ​​유용합니다. 다음과 같이 작성할 수 있습니다.

void doSomething(Widget widget) {
  assert widget != null;
  if (widget != null) {
    widget.someMethod(); // ...
    ... // do more stuff with this widget
  }
}

이렇게하면 동료가 프로덕션 코드에 null 체크가 있다는 것을 기쁜 마음으로 알게 될 것입니다. 그러나 개발 중에 위젯이 null 일 때 더 이상 버그를 숨기지 않습니다.

실세계의 예가 있습니다 : 어느 쪽의 값도 null 일 가능성이있는, 2 개의 임의의 값을 비교하는 메소드를 작성했습니다 :

/**
 * Compare two values using equals(), after checking for null.
 * @param thisValue (may be null)
 * @param otherValue (may be null)
 * @return True if they are both null or if equals() returns true
 */
public static boolean compare(final Object thisValue, final Object otherValue) {
  boolean result;
  if (thisValue == null) {
    result = otherValue == null;
  } else {
    result = thisValue.equals(otherValue);
  }
  return result;
}

이 코드는 thisValue가 null이 아닌 경우 equals() 메서드의 작업을 위임합니다. 그러나 null 매개 변수를 적절히 처리하여 equals() 메서드가 equals() 계약을 올바르게 수행한다고 가정합니다.

동료는 내 코드에 반대하여 많은 클래스가 널 (null)을 테스트하지 않는 버그가있는 equals() 메소드를 가지고 있기 때문에이 메소드를이 메소드에 넣어야한다. 이것이 현명하거나 논쟁의 여지가있는 경우 논쟁의 여지가 있기 때문에 오류를 찾아서 고칠 수는 있지만 동료에게 연기하고 null 체크를 달았습니다.

public static boolean compare(final Object thisValue, final Object otherValue) {
  boolean result;
  if (thisValue == null) {
    result = otherValue == null;
  } else {
    result = otherValue != null && thisValue.equals(otherValue); // questionable null check
  }
  return result;
}

equals() 메소드가 계약에서 요구하는대로 null을 확인하지 못하는 경우에만 other != null 이 필요합니다.

버그 코드를 코드 기반에 머물게하는 지혜에 관해 제 동료와 무의미한 토론을하기보다는 코드에 두 가지 단정을 간단히 나타냅니다. 이 단언은 개발 단계에서 클래스 중 하나가 equals() 제대로 구현하지 못하면 해결할 수 있도록 알려줍니다.

public static boolean compare(final Object thisValue, final Object otherValue) {
  boolean result;
  if (thisValue == null) {
    result = otherValue == null;
    assert otherValue == null || otherValue.equals(null) == false;
  } else {
    result = otherValue != null && thisValue.equals(otherValue);
    assert thisValue.equals(null) == false;
  }
  return result;
}

명심해야 할 중요한 사항은 다음과 같습니다.

  1. 어설 션은 개발 단계 도구 일뿐입니다.

  2. 어설 션의 요점은 코드에있는 것이 아니라 코드 기반에 버그가 있는지 알려주는 것입니다. (여기에있는 어설 션은 실제로 다른 클래스의 버그를 표시합니다.)

  3. 제 동료가 수업이 제대로 작성되었다고 확신한다고해도 여기에있는 주장은 여전히 ​​유용 할 것입니다. 널 (null)을 테스트하지 못할 수도있는 새로운 클래스가 추가 될 것이고,이 메소드는 우리에게 버그를 표시 할 수 있습니다.

  4. 개발시, 작성한 코드가 어설 션을 사용하지 않더라도 항상 어설 션을 켜야합니다. 내 IDE는 새로운 실행 파일에 대해 기본적으로 항상이 작업을 수행하도록 설정됩니다.

  5. 어서션은 프로덕션에서 코드의 동작을 변경하지 않으므로 동료가 null 체크가되어 기쁘다. equals() 메서드가 버그가 있어도이 메서드가 제대로 실행됩니다. 개발 과정에서 버그가있는 equals() 메서드를 발견 할 것이기 때문에 나는 행복하다.

또한 실패 할 임시 어설 션을 넣어 어설 션 정책을 테스트해야하므로 로그 파일이나 출력 스트림의 스택 추적을 통해 알 수 있음을 확신 할 수 있습니다.


여기에 제공된 모든 위대한 답변 외에도 공식 Java SE 7 프로그래밍 가이드에는 assert 사용에 대한 매우 간결한 설명서가 있습니다. 어설 션을 사용하는 것이 좋은 (그리고 중요한 것은 나쁜) 아이디어 일 때와 예외를 던지는 것과 다른 점이 몇 가지 있습니다.

Link


다음은 가장 일반적인 사용 사례입니다. 열거 형 값을 사용한다고 가정 해보십시오.

switch (fruit) {
  case apple:
    // do something
    break;
  case pear:
    // do something
    break;
  case banana:
    // do something
    break;
}

모든 사건을 처리하는 한 괜찮습니다. 하지만 언젠가는 누군가가 당신의 열거 형에 무화과를 추가하고 그것을 스위치 명세서에 추가하는 것을 잊어 버릴 것입니다. 스위치 문을 종료 할 때까지 효과가 느껴지지 않기 때문에 잡기가 까다로운 버그가 생성됩니다. 그러나 이와 같이 스위치를 작성하면 즉시 잡을 수 있습니다.

switch (fruit) {
  case apple:
    // do something
    break;
  case pear:
    // do something
    break;
  case banana:
    // do something
    break;
  default:
    assert false : "Missing enum value: " + fruit;
}

어설 션은 코드의 결함을 탐지 할 수있게합니다. 테스트 및 디버깅을 위해 어설 션을 켤 수 있으며 프로그램 생산 중에는 어설 션을 해제 할 수 있습니다.

그것이 사실임을 알 때 왜 뭔가를 주장합니까? 모든 것이 제대로 작동 할 때만 사실입니다. 프로그램에 결함이있는 경우 사실이 아닐 수도 있습니다. 이 과정의 초기 단계에서이를 감지하면 잘못된 점을 알 수 있습니다.

assert 문은이 문을 선택적 String 메시지와 함께 포함합니다.

assert 문의 구문에는 다음과 같은 두 가지 형식이 있습니다.

assert boolean_expression;
assert boolean_expression: error_message;

다음은 어설 션을 사용해야하는 위치와 사용하지 말아야 할 위치를 제어하는 ​​몇 가지 기본 규칙입니다. 어설 션 다음 용도로 사용 되어야 합니다.

  1. 개인 메소드의 입력 매개 변수를 검증합니다. 공개 메소드가 아닙니다 . public 메소드는 잘못된 매개 변수를 전달할 때 일반 예외를 throw해야합니다.

  2. 거의 확실하게 사실의 타당성을 보장하는 프로그램의 어느 곳에서나.

예를 들어, 그것이 1 또는 2 중 하나 일 것이라는 확신이 들면 다음과 같은 어설 션을 사용할 수 있습니다.

...
if (i == 1)    {
    ...
}
else if (i == 2)    {
    ...
} else {
    assert false : "cannot happen. i is " + i;
}
...
  1. 모든 메소드의 끝에서 사후 조건 검증. 즉, 비즈니스 로직을 실행 한 후에 어설 션을 사용하여 변수 또는 결과의 내부 상태가 예상 한 것과 일치하는지 확인할 수 있습니다. 예를 들어, 소켓 또는 파일을 여는 메소드는 끝에 어설 션을 사용하여 소켓 또는 파일이 실제로 열려 있는지 확인할 수 있습니다.

어설 션 다음 용도로 사용 하면 안됩니다 .

  1. 공용 메소드의 입력 매개 변수를 검증합니다. 어설 션은 항상 실행되지 않을 수 있기 때문에 규칙적인 예외 메커니즘을 사용해야합니다.

  2. 사용자가 입력 한 것에 대한 제약 조건을 검증합니다. 같은 상기와.

  3. 부작용으로 사용되어서는 안됩니다.

예를 들어 여기에서는 doSomething() 메서드 호출의 부작용에 어설 션을 사용하기 때문에 적절하지 않습니다.

public boolean doSomething() {
...    
}
public void someMethod() {       
assert doSomething(); 
}

이것이 정당화 될 수있는 유일한 경우는 코드에서 어설 션을 사용할 수 있는지 여부를 알아 내려고 할 때입니다.

boolean enabled = false;    
assert enabled = true;    
if (enabled) {
    System.out.println("Assertions are enabled");
} else {
    System.out.println("Assertions are disabled");
}

요점을 되짚어 보자. (그리고 이것은 자바 뿐만이 아니라 많은 언어에서 가능하다.)

"assert"는 주로 디버깅 프로세스 중에 소프트웨어 개발자가 디버깅을 돕는 데 사용됩니다. 어설 션 메시지는 절대 나타나서는 안됩니다. 많은 언어가 "생산"코드를 생성하는 데 사용하기 위해 모든 "주장"을 무시하도록하는 컴파일 타임 옵션을 제공합니다.

"예외"는 논리 오류를 나타내는 지 여부와 상관없이 모든 종류의 오류 조건을 처리 할 수있는 편리한 방법입니다. 오류 상태가되어 계속 진행할 수 없으면 단순히 " "당신이있는 곳이면 어디든지 다른 사람이 그들을"붙잡을 "준비가되어 있다고 기대합니다. 컨트롤은 예외를 던진 코드에서 곧바로 포수의 미트에게 한 단계로 전달됩니다. (그리고 포수는 일어난 전화의 완전한 백 트레이스를 볼 수 있습니다.)

게다가 서브 루틴을 호출 한 사람은 서브 루틴이 성공했는지 여부를 확인하지 않아도됩니다. "우리가 지금 여기 있으면 성공했을 것입니다. 그렇지 않으면 예외가 발생했을 것이고 지금은 여기에 없을 것입니다!" 이 간단한 전략은 코드 디자인과 디버깅을 훨씬 더 쉽게 만듭니다.

예외는 치명적 오류 조건을 "규칙 예외"로 편리하게 허용합니다. 그리고 그들도 "규칙의 예외"인 코드 경로에 의해 처리되어야합니다 ... "공을!"


assert키워드입니다. 이것은 JDK 1.4에서 소개되었습니다. 는 두 종류 assert

  1. 아주 간단한 assert진술
  2. 간단한 assert진술.

기본적으로 모든 assert명령문은 실행되지 않습니다. 는 IF assert문이 거짓 수신 후 자동으로 어설 션 오류가 발생합니다.


어설 션은 기본적으로 비활성화되어 있습니다. 이를 사용하려면 -ea 옵션을 사용하여 프로그램을 실행해야합니다 (세분성은 다양 할 수 있음). 예를 들어, java -ea AssertionsDemo .

어설 션을 사용하는 데는 두 가지 형식이 있습니다.

  1. 단순 : 예. assert 1==2; // This will raise an AssertionError assert 1==2; // This will raise an AssertionError 합니다.
  2. 더 나은 : assert 1==2: "no way.. 1 is not equal to 2"; 주어진 메시지와 함께 AssertionError를 발생시킬 것이므로 더 좋습니다. 실제 구문은 assert expr1:expr2 여기서 expr2는 값을 반환하는 표현식이 될 수 있습니다. 메시지를 인쇄하기 위해 expr2를 자주 사용했습니다.

Assertions ( assert 키워드를 통해)이 Java 1.4에 추가되었습니다. 이들은 코드에서 불변의 정확성을 검증하는 데 사용됩니다. 프로덕션 코드에서 절대로 트리거해서는 안되며 코드 경로의 버그 또는 오용을 나타냅니다. java 명령에서 -ea 옵션을 사용하여 런타임에 활성화 할 수 있지만 기본적으로 활성화되지는 않습니다.

예 :

public Foo acquireFoo(int id) {
  Foo result = null;
  if (id > 50) {
    result = fooService.read(id);
  } else {
    result = new Foo(id);
  }
  assert result != null;

  return result;
}

assert 키워드가 무엇인지 설명하는 좋은 답변이 많지만 "실제 키워드에서 assert 키워드를 사용해야하는시기는 언제입니까?"

은 거의 없습니다 .

어설 션은 개념으로서 훌륭합니다. 좋은 코드에는 if (...) throw ... 문 (및 Objects.requireNonNullMath.addExact 와 같은 친척)이 많이 있습니다. 그러나 특정 디자인 결정은 assert 키워드 자체의 유용성을 크게 제한합니다.

assert 키워드 뒤에있는 아이디어는 시기상조의 최적화이며, 주요 기능은 모든 검사를 쉽게 끌 수 있다는 것입니다. 사실, assert 검사는 기본적으로 해제되어 있습니다.

그러나 불변 수표가 생산에서 계속 수행되는 것이 매우 중요합니다. 이는 완벽한 테스트 커버리지가 불가능하고 모든 프로덕션 코드에 어설 션이 진단 및 완화에 도움이되는 버그를 가지고 있기 때문입니다.

따라서 public 메서드의 매개 변수 값을 확인하고 IllegalArgumentException 을 throw 할 때와 마찬가지로 if (...) throw ... 를 사용하는 것이 바람직합니다.

때로는 불필요하게 오랜 시간이 걸리는 불변 수표를 쓰기를 원할 수도 있습니다. 그러나 그러한 검사는 시험을 느리게 할 수있어 바람직하지 않습니다. 그러한 시간을 소비하는 수표는 대개 단위 테스트로 작성됩니다. 그럼에도 불구하고 때때로 이러한 이유로 assert 를 사용 assert 것이 의미가있을 수 있습니다.

assert 단순히 if (...) throw ... 보다 깨끗하고 예쁘기 때문에 사용하지 마십시오 if (...) throw ... (나는 깨끗하고 예쁜 것을 좋아하기 때문에 큰 고통으로 말합니다). 자신을 도울 수없고 응용 프로그램이 시작되는 방법을 제어 할 수 있다면 assert 자유롭게 사용할 있지만 항상 프로덕션에서 assertion을 활성화하십시오. 틀림없이, 이것은 내가하는 경향이 있습니다. 나는 if (...) throw ... 와 같이 더 많은 행동을하는 어썰트를 유발할 롬복 주석을 요구하고있다. 여기에 투표하십시오.

(Rant : JVM 개발자들은 조만간 코드 작성기를 조기에 최적화했기 때문에 Java Plugin과 JVM에서 많은 보안 문제를 듣고 있으며 기본적인 코드와 어설 션을 프로덕션 코드에 포함시키지 않고 계속해서 가격을 지불하십시오.)


원자력 발전소를 제어하기위한 프로그램을 작성한다고 가정 해 봅시다. 아주 사소한 실수조차도 치명적인 결과를 가져올 수 있으므로 코드 버그가 없어야합니다 (JVM이 인수를 위해 버그가 없다고 가정).

Java는 검증 가능한 언어가 아니므로 다음과 같은 의미입니다. 조작 결과가 완벽 할 것이라고 계산할 수는 없습니다. 이것의 주된 이유는 포인터입니다. 포인터는 어디에서나 또는 아무 곳에도 가리킬 수 있기 때문에 합리적인 코드 범위 내에서이 정확한 값으로 계산할 수 없습니다. 이 문제를 감안할 때 코드가 정확하다는 것을 증명할 방법이 없습니다. 그러나 당신이 할 수있는 일은 그것이 발생했을 때 적어도 모든 버그를 발견했음을 증명하는 것입니다.

이 아이디어는 DbC ( Design-by-Contract ) 패러다임을 기반으로합니다. 먼저 수학적 방법으로 무엇을해야하는지 정의한 다음 실제 실행 중에 테스트하여 확인하십시오. 예:

// Calculates the sum of a (int) + b (int) and returns the result (int).
int sum(int a, int b) {
  return a + b;
}

이것이 잘 작동하는 것은 명백한 반면, 대부분의 프로그래머는이 내부의 숨겨진 버그를 보지 못합니다 (힌트 : Ariane V는 유사한 버그로 인해 추락했습니다). 이제 DbC에서는 함수의 입력과 출력을 항상 확인하여 제대로 작동하는지 확인해야한다고 정의합니다. 자바는 단언을 통해 이것을 할 수있다.

// Calculates the sum of a (int) + b (int) and returns the result (int).
int sum(int a, int b) {
    assert (Integer.MAX_VALUE - a >= b) : "Value of " + a + " + " + b + " is too large to add.";
  final int result = a + b;
    assert (result - a == b) : "Sum of " + a + " + " + b + " returned wrong sum " + result;
  return result;
}

이 기능이 지금 실패하면, 당신은 그것을 알아 차릴 것입니다. 코드에 문제가 있음을 알 수 있습니다. 코드의 위치와 예외의 원인을 알 수 있습니다 (예외와 유사). 그리고 무엇보다 중요한 것은 더 이상의 코드가 잘못된 값으로 작동하지 못하도록 막 으면 바로 실행을 멈추고 제어하는 ​​항목이 손상 될 수 있습니다.

자바 예외도 비슷한 개념이지만 모든 것을 검증하지는 못합니다. 더 많은 검사 (실행 속도의 비용으로)를 원한다면 어설 션을 사용해야합니다. 이렇게하면 코드가 팽창하지만 결국에는 짧은 개발 시간에 제품을 제공 할 수 있습니다 (버그를 조기에 해결할수록 비용이 낮아집니다). 또한 코드 내에 버그가있는 경우이를 감지 할 수 있습니다. 버그가 빠져 나와 나중에 문제가 발생할 수있는 방법이 없습니다.

이것은 여전히 ​​버그없는 코드에 대한 보장은 아니지만 일반적인 프로그램보다 훨씬 가깝습니다.


어설 션은 스위치가 꺼질 수있는 수표입니다. 그들은 거의 사용되지 않습니다. 왜?

  • 공용 메서드 인수를 제어 할 수 없으므로 공용 메서드 인수를 확인하는 데 사용해서는 안됩니다.
  • result != null그러한 수표는 매우 빠르며 구원받을 것이 거의 없다는 것과 같은 단순한 수표에 사용해서는 안됩니다 .

그럼 남은 건 뭐야? 정말로 사실 일 것으로 예상되는 조건에 대한 값 비싼 검사 . RB-tree와 같은 데이터 구조의 불변량이 좋은 예입니다. 사실, JDK8에서는,에 대한 몇 가지 의미있는 주장이 있습니다.ConcurrentHashMapTreeNodes

  • 실행 시간을 쉽게 지배 할 수 있기 때문에 실제로 프로덕션 환경에서 스위치를 켜고 싶지는 않습니다.
  • 테스트 중에 스위치를 켜거나 끌 수 있습니다.
  • 코드 작업을 할 때 확실히 전환하고 싶습니다.




assertions