주장의 주요 역할을 이해하기위한 실제 사례 는 무엇입니까 ?
주장의 주요 역할을 이해하기위한 실제 사례 는 무엇입니까 ?
답변:
주장 (의 방법에 의한 어설 션 키워드) 자바 1.4에 추가되었습니다. 코드에서 불변의 정확성을 확인하는 데 사용됩니다. 프로덕션 코드에서 트리거되지 않아야하며 코드 경로의 버그 나 오용을 나타냅니다. 명령 의 -ea
옵션을 통해 런타임시 활성화 될 수 java
있지만 기본적으로 켜져 있지는 않습니다.
예를 들면 :
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
공용 메소드 매개 변수 ( docs.oracle.com/javase/1.4.2/docs/guide/lang/assert.html ) 를 확인하는 데 사용하지 말라고 지시합니다 . 그것은 Exception
프로그램을 죽이는 대신에 던져야합니다 .
This convention is unaffected by the addition of the assert construct. Do not use assertions to check the parameters of a public method. An assert is inappropriate because the method guarantees that it will always enforce the argument checks. It must check its arguments whether or not assertions are enabled. Further, the assert construct does not throw an exception of the specified type. It can throw only an AssertionError.
docs.oracle.com/javase/8/docs/technotes/guides/language/…
원자력 발전소를 제어하는 프로그램을 작성한다고 가정 해 봅시다. 따라서 코드는, 심지어 가장 사소한 실수가 치명적인 결과를 가질 수있는 매우 분명하다 이어야 버그 프리 (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는 함수의 입력 및 출력을 항상 확인하여 올바르게 작동하는지 확인 해야한다고 정의 합니다. Java는 어설 션을 통해이를 수행 할 수 있습니다.
// 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;
}
이 기능이 이제 실패하면 알 수 있습니다. 코드에 문제가 있음을 알 수 있으며, 코드의 위치와 발생 원인을 알 수 있습니다 (예외와 유사). 그리고 더 중요한 것은 코드가 잘못된 값으로 작동하지 못하게하고 제어하는 모든 항목에 손상을 줄 수있는 경우 즉시 실행을 중지합니다.
Java 예외도 비슷한 개념이지만 모든 것을 확인하지 못합니다. 더 많은 검사를 원한다면 (어택 속도로) 어설 션을 사용해야합니다. 그렇게하면 코드가 부풀어 질 수 있지만 결국 개발 시간이 놀랍도록 짧은 시간에 제품을 제공 할 수 있습니다 (버그를 조기에 해결할수록 비용은 줄어 듭니다). 또한 코드 내부에 버그가 있으면 감지합니다. 버그 제거 방법은 없으며 나중에 문제를 일으킬 수 있습니다.
이것은 여전히 버그가없는 코드를 보장하지는 않지만 일반적인 프로그램보다 훨씬 더 가깝습니다.
new IllegalArgumentException
메시지와 함께 a 를 던지는 것의 차이점은 무엇 입니까? 나는 throws
메소드 선언과 코드를 추가 하여 그 예외를 다른 곳에서 관리하는 것을 제외하고. 왜 assert
새로운 예외가 발생합니까? 아니면 왜 if
대신에 assert
? 실제로 이것을 얻을 수 없습니다 :(
a
음수가 될 수있는 경우 오버플로를 확인하는 어설 션이 잘못되었습니다 . 두 번째 주장은 쓸모가 없다. int 값의 경우 항상 a + b-b == a입니다. 컴퓨터가 근본적으로 고장난 경우에만 해당 테스트가 실패 할 수 있습니다. 이러한 우발적 인 상황을 방지하려면 여러 CPU에서 일관성을 확인해야합니다.
어설 션은 코드에서 버그를 포착하는 개발 단계 도구입니다. 그것들은 쉽게 제거되도록 설계되었으므로 프로덕션 코드에는 존재하지 않습니다. 따라서 어설 션은 고객에게 제공하는 "솔루션"의 일부가 아닙니다. 그들은 가정이 올바른지 확인하기 위해 내부 검사입니다. 가장 일반적인 예는 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 검사를 수행해야한다고 주장합니다. 이 경우 어설 션은 여전히 유용합니다. 다음과 같이 작성할 수 있습니다.
void doSomething(Widget widget) {
assert widget != null;
if (widget != null) {
widget.someMethod(); // ...
... // do more stuff with this widget
}
}
이런 식으로 동료들은 프로덕션 코드에 대해 null 검사가 있다는 것을 기쁘게 생각하지만 개발 중에 위젯이 null 일 때 더 이상 버그를 숨기지 않습니다.
실제 예는 다음과 같습니다. 두 번의 임의의 값이 동일한 지 비교하는 방법을 작성했습니다. 두 값 중 하나가 null 일 수 있습니다.
/**
* 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;
}
이 코드 equals()
는 thisValue가 null이 아닌 경우 메서드 작업을 위임합니다 . 그러나이 equals()
방법 equals()
이 null 매개 변수를 올바르게 처리 하여 계약을 올바르게 이행 한다고 가정합니다 .
동료가 내 코드에 반대하여 많은 클래스 equals()
에 null을 테스트하지 않는 버그가있는 메소드가 있다고 알려주 므로이 검사를 체크해야합니다. 이것이 현명하거나 오류를 강제해야한다면 논쟁의 여지가 있습니다. 따라서 오류를 발견하고 수정할 수는 있지만 동료에게 연기하고 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;
}
여기서 추가 검사 는 계약에서 요구 한대로 메소드가 널을 검사하지 못하는 other != null
경우에만 필요합니다 equals()
.
버그가있는 코드를 코드 기반으로 유지하는 데 대한 지혜에 대해 동료들과 결실없는 토론에 참여하기보다는 코드에 두 가지 주장 만 썼습니다. 이 어설 션은 개발 단계에서 클래스 중 하나가 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;
}
명심해야 할 중요한 사항은 다음과 같습니다.
어설 션은 개발 단계 도구 일뿐입니다.
주장의 요점은 코드뿐만 아니라 코드 기반에도 버그가 있는지 알려주는 것 입니다. (여기의 주장은 실제로 다른 클래스의 버그를 표시합니다.)
동료가 수업이 제대로 작성되었다고 확신하더라도 여기에있는 주장이 여전히 유용 할 것입니다. null 테스트에 실패 할 수있는 새로운 클래스가 추가 될 예정이며이 메서드는 이러한 버그를 플래그로 지정할 수 있습니다.
개발 중에는 작성한 코드가 어설 션을 사용하지 않더라도 항상 어설 션을 설정해야합니다. 내 IDE는 새로운 실행 파일에 대해 항상 기본적 으로이 작업을 수행하도록 설정되어 있습니다.
어설 션은 프로덕션 환경에서 코드의 동작을 변경하지 않으므로 동료는 null 검사가 있고 equals()
메소드가 버그가 있어도이 메소드가 제대로 실행된다는 것을 기쁘게 생각합니다 . equals()
개발에서 버그가있는 방법을 잡을 수 있기 때문에 행복 합니다.
또한 실패 할 임시 어설 션을 넣어 어설 션 정책을 테스트해야하므로 로그 파일 또는 출력 스트림의 스택 추적을 통해 알림을받을 수 있습니다.
assert
키워드의 기능을 설명하는 좋은 답변 은 많지만 "실제 키워드는 언제 사용해야 assert
합니까?"라는 실제 질문에 대한 답변은 거의 없습니다.
대답 은 거의 없습니다 .
개념으로서의 주장은 훌륭합니다. 좋은 코드에는 많은 if (...) throw ...
진술이 있고 (과의 친척이 Objects.requireNonNull
and Math.addExact
) 있습니다. 그러나 특정 디자인 결정은 assert
키워드 자체 의 유용성을 크게 제한했습니다 .
assert
키워드 의 원동력 은 조기 최적화이며 주요 기능은 모든 검사를 쉽게 해제 할 수 있다는 것입니다. 실제로, assert
검사는 기본적으로 해제되어 있습니다.
그러나 생산에서 변하지 않는 점검을 계속 수행하는 것이 매우 중요합니다. 완벽한 테스트 범위가 불가능하기 때문에 모든 프로덕션 코드에는 진단 및 완화에 도움이되는 버그가 있습니다.
따라서 if (...) throw ...
public 메소드의 매개 변수 값을 확인하고 throw하는 데 필요한 것처럼 선호해야합니다 IllegalArgumentException
.
때때로, 처리하는 데 바람직하지 않은 시간이 오래 걸리는 불변 검사를 작성하고 싶을 수도 있습니다 (종종 문제가되기에 충분하다고도 함). 그러나 이러한 검사는 테스트 속도를 저하 시키므로 바람직하지 않습니다. 이러한 시간이 많이 걸리는 점검은 일반적으로 단위 테스트로 작성됩니다. 그럼에도 불구하고 때때로 사용하는 것이 합리적 일 수 있습니다assert
이러한 이유로 하는 .
assert
그것이 if (...) throw ...
깨끗하고 예쁘기 때문에 단순히 사용하지 마십시오 (나는 깨끗하고 예쁘기 때문에 큰 고통으로 말합니다). 자신을 도울 수없고 응용 프로그램이 시작되는 방식을 제어 할 수 있다면 자유롭게 사용 assert
하되 항상 프로덕션에서 어설 션을 활성화하십시오. 물론 이것이 내가하는 경향이있다. 나는 롬복 주석을 assert
더 밀고 나아갈 것입니다.if (...) throw ...
입니다. 여기에 투표하십시오.
(Rant : JVM 개발자는 끔찍하고 조기에 최적화 된 코더였습니다. 따라서 Java 플러그인 및 JVM의 많은 보안 문제에 대해 들었습니다. 프로덕션 코드에 기본 확인 및 어설 션을 포함하지 않기로했습니다. 가격을 지불하십시오.)
catch (Throwable t)
입니다. 등 OutOfMemoryError를, AssertionError를, 복구 / 트랩, 로그, 또는 재 시도에 시도하지 할 이유가 없다
assert
키워드 의 구현 이 잘못되었습니다. 개념이 아니라 키워드를 참조하고 있음을보다 명확하게하기 위해 답변을 편집하겠습니다.
가장 일반적인 사용 사례는 다음과 같습니다. 열거 형 값을 설정한다고 가정합니다.
switch (fruit) {
case apple:
// do something
break;
case pear:
// do something
break;
case banana:
// do something
break;
}
모든 경우를 다루는 한 괜찮습니다. 그러나 언젠가 누군가가 열거 형에 그림을 추가하고 스위치 문에 추가하는 것을 잊어 버릴 것입니다. switch 문을 떠날 때까지 효과가 느껴지지 않기 때문에 잡기가 까다로울 수있는 버그가 발생합니다. 그러나 다음과 같이 스위치를 작성하면 즉시 잡을 수 있습니다.
switch (fruit) {
case apple:
// do something
break;
case pear:
// do something
break;
case banana:
// do something
break;
default:
assert false : "Missing enum value: " + fruit;
}
AssertionError
어설 션이 활성화 된 경우 ( -ea
)가 발생합니다. 프로덕션에서 원하는 동작은 무엇입니까? 사형 집행이 끝날 무음과 재난이 있을까? 아마 아닙니다. 나는 명시 적으로 제안 할 것이다 throw new AssertionError("Missing enum value: " + fruit);
.
default
는 컴파일러가 누락 된 경우에 대해 경고 할 수 있도록 사용해서는 안됩니다 . return
대신 break
(이 방법을 추출해야 할 수도 있음) 대신 스위치 후 누락 된 사례를 처리 할 수 있습니다. 이렇게하면 경고와 기회를 모두 얻을 수 있습니다 assert
.
어설 션은 사후 조건을 확인하고 사전 조건을 "실패해서는 안됩니다"를 확인하는 데 사용됩니다. 올바른 코드는 어설 션에 실패하지 않아야합니다. 그들이 발동 할 때, 버그를 나타내야합니다 (실제로 문제의 실제 위치가있는 곳에 가깝습니다).
주장의 예는 특정 그룹의 메소드가 올바른 순서로 호출되는지 확인하는 것입니다 (예 :에서 hasNext()
이전 next()
에 호출 됨 Iterator
).
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()
이다 true
경우-ea
명령 행에서 가 전달 그렇지 않으면 false입니다.
우리는 System.currentTimeMillis()
그것이 최적화되지 않도록 보장하기 위해 사용 합니다 assert true;
.
합성 필드는 Java Assert.class.desiredAssertionStatus()
가로드시 한 번만 호출 하면 결과가 캐시되도록 생성됩니다. 참조 : "정적 합성"의 의미는 무엇입니까?
다음을 통해 확인할 수 있습니다.
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
: 그것은 Java 언어 개념입니다.assert
명령 줄에서 -Pcom.me.assert=true
대체 할 시스템 속성과 꽤 잘 에뮬레이션 할 수 있습니다 .-ea
throw new AssertionError()
catch (Throwable t)
조항은 어설 션 위반도 포착 할 수 있습니까? 저에게는 주장의 본문이 시간이 많이 걸리는 경우로만 그 유용성을 제한합니다.
AssertionError
첫 번째를 잡아서 다시 던질 수 있습니다.
스택 클래스의 실제 예 ( Java 기사의 어설 션 )
public int pop() {
// precondition
assert !isEmpty() : "Stack is empty";
return stack[--num];
}
어설 션을 사용하면 코드의 결함을 감지 할 수 있습니다. 프로그램이 프로덕션 환경에있을 때는 그대로두고 테스트 및 디버깅을위한 어설 션을 설정할 수 있습니다.
그것이 사실임을 알 때 왜 무언가를 주장 하는가? 모든 것이 제대로 작동하는 경우에만 해당됩니다. 프로그램에 결함이있는 경우 실제로는 그렇지 않을 수 있습니다. 프로세스 초기에이를 감지하면 문제가 있음을 알 수 있습니다.
assert
문은 옵션과 함께이 문장이 포함되어 String
메시지를.
assert 문의 구문은 두 가지 형식이 있습니다.
assert boolean_expression;
assert boolean_expression: error_message;
어설 션을 사용해야하는 위치와 사용하지 않아야하는 위치를 결정하는 몇 가지 기본 규칙이 있습니다. 다음에 어설 션을 사용해야 합니다.
개인용 메소드의 입력 매개 변수 유효성 검증 공개 메소드에는 적합 하지 않습니다 . public
잘못된 매개 변수를 전달하면 메서드에서 정기적 인 예외가 발생합니다.
거의 확실하게 사실의 유효성을 보장하기 위해 프로그램의 어느 곳에서나.
예를 들어 1 또는 2 만 될 것이라고 확신하는 경우 다음과 같이 어설 션을 사용할 수 있습니다.
...
if (i == 1) {
...
}
else if (i == 2) {
...
} else {
assert false : "cannot happen. i is " + i;
}
...
어설 션 은 다음에 사용 해서는 안됩니다 .
공개 메소드의 입력 매개 변수 유효성 검증 어설 션이 항상 실행되는 것은 아니므로 규칙적인 예외 메커니즘을 사용해야합니다.
사용자가 입력 한 것에 대한 제약 조건을 검증합니다. 같은 상기와.
부작용에 사용해서는 안됩니다.
예를 들어, 여기에서는 어설 션이 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");
}
여기에 제공된 모든 훌륭한 답변 외에도 공식 Java SE 7 프로그래밍 안내서에는 사용에 대한 간결한 매뉴얼이 있습니다 assert
. 어설 션을 사용하는 것이 좋은 (그리고 중요한 것은 나쁜) 아이디어와 예외를 던지는 것과 어떻게 다른지에 대한 몇 가지 예를 들었습니다.
Assert는 개발시 매우 유용합니다. 뭔가 할 수 없을 때 사용코드가 올바르게 작동하면 문제가 발생 않을 합니다. 사용하기 쉽고 코드에서 그대로 유지 될 수 있습니다. 실제로는 사용되지 않기 때문입니다.
실생활에서 상태가 발생할 가능성이 있으면 처리해야합니다.
나는 그것을 좋아하지만 Eclipse / Android / ADT에서 그것을 켜는 방법을 모른다. 디버깅 할 때도 꺼져있는 것 같습니다. (이 스레드는 있지만 ADT 실행 구성에 나타나지 않는 'Java vm'을 나타냅니다).
다음은 Hibernate / SQL 프로젝트를 위해 서버에 작성한 주장이다. 엔티티 bean에는 isActive 및 isDefault라는 두 개의 유효 부울 특성이 있습니다. 각각의 값은 "Y"또는 "N"또는 null 일 수 있으며 "N"으로 처리되었습니다. 브라우저 클라이언트가이 세 값으로 제한되도록하고 싶습니다. 따라서이 두 속성에 대한 설정자 에서이 어설 션을 추가했습니다.
assert new HashSet<String>(Arrays.asList("Y", "N", null)).contains(value) : value;
다음을 주목하십시오.
이 주장은 개발 단계에만 해당됩니다. 고객이 잘못된 값을 보내면 생산에 도달하기 훨씬 전에 조기에 파악하여 수정합니다. 어설 션은 조기에 파악할 수있는 결함에 대한 것입니다.
이 주장은 느리고 비효율적입니다. 괜찮아요. 주장은 느려질 수 있습니다. 우리는 개발 전용 도구이기 때문에 신경 쓰지 않습니다. 어설 션이 비활성화되므로 프로덕션 코드 속도가 느려지지 않습니다. (이 시점에서 약간의 의견 차이가 있으며, 나중에 설명하겠습니다.) 그러면 다음 단계로 넘어갑니다.
이 주장은 부작용이 없습니다. 수정 불가능한 정적 최종 세트에 대해 내 가치를 테스트 할 수 있었지만 해당 세트는 결코 사용되지 않는 프로덕션 환경에서 유지되었습니다.
이 어설 션은 클라이언트가 올바르게 작동하는지 확인하기 위해 존재합니다. 따라서 프로덕션에 도달 할 때까지 클라이언트가 제대로 작동하는지 확인하여 어설 션을 안전하게 해제 할 수 있습니다.
어떤 사람들은 이것을 묻습니다. 어설 션이 프로덕션에 필요하지 않은 경우, 완료했을 때 어설 션을 꺼내지 않겠습니까? 다음 버전에서 작업을 시작할 때 여전히 필요하기 때문입니다.
어떤 사람들은 모든 버그가 사라 졌다고 확신 할 수 없기 때문에 어설 션을 사용해서는 안된다고 주장하면서 프로덕션 환경에서도 버그를 유지해야합니다. 따라서 assert 문을 사용하는 데는 아무런 소용이 없습니다. assert의 유일한 장점은 그것들을 끌 수 있다는 것입니다. 따라서,이 생각에 따르면, 당신은 (거의) 주장을 절대 사용해서는 안됩니다. 동의하지 않습니다. 테스트가 프로덕션 환경에 속하는 경우 어설 션을 사용하지 않아야합니다. 그러나이 테스트는하지 않습니다 프로덕션에 속하지 . 이것은 생산에 닿지 않을 수있는 버그를 잡기위한 것이므로 완료되면 안전하게 해제 될 수 있습니다.
BTW, 나는 다음과 같이 쓸 수있었습니다.
assert value == null || value.equals("Y") || value.equals("N") : value;
이것은 세 개의 값에만 유효하지만 가능한 값의 수가 커지면 HashSet 버전이 더 편리해집니다. 효율성에 대한 요점을 밝히기 위해 HashSet 버전을 선택했습니다.
HashSet
비해 어떤 속도 이점이 있는지 의심 합니다 ArrayList
. 또한 세트 및 목록 작성이 조회 시간을 지배합니다. 상수를 사용할 때 괜찮습니다. 모든 것이 +1입니다.
어설 션은 기본적으로 응용 프로그램을 디버깅하는 데 사용되거나 일부 응용 프로그램에서 응용 프로그램의 유효성을 검사하기 위해 예외 처리를 대체하는 데 사용됩니다.
어설 션은 런타임에 작동합니다. 간단한 예를 들어, 즉 매우 간단 전체 개념을 설명 할 수 여기에있다 - 어설 자바에서 할 키워드 무엇? (WikiAnswers).
어설 션은 기본적으로 비활성화되어 있습니다. 이를 가능하게하려면 -ea
옵션으로 프로그램을 실행해야합니다 (과립도는 다를 수 있음). 예를 들면 다음과 같습니다 java -ea AssertionsDemo
.
어설 션 사용에는 두 가지 형식이 있습니다.
assert 1==2; // This will raise an AssertionError
.assert 1==2: "no way.. 1 is not equal to 2";
주어진 메시지가 표시된 상태에서 AssertionError가 발생하여 더 좋습니다. 실제 구문은 assert expr1:expr2
expr2가 값을 반환하는식이 될 수있는 곳 이지만 메시지를 인쇄하는 데 더 자주 사용했습니다.요약하자면 (그리고 이것은 Java뿐만 아니라 많은 언어에서 사실입니다) :
"assert"는 주로 디버깅 프로세스 중에 소프트웨어 개발자가 디버깅 보조 도구로 사용합니다. 어설 션 메시지가 나타나지 않아야합니다. 많은 언어들이 "프로덕션"코드 생성에 사용하기 위해 모든 "어설 션"이 무시되도록하는 컴파일 타임 옵션을 제공합니다.
"예외"는 논리 오류를 나타내는 지 여부에 관계없이 모든 종류의 오류 조건을 처리 할 수있는 편리한 방법입니다. 계속할 수없는 오류 조건이 발생하면 단순히 "공중으로 던질 수 있습니다. "당신이 어디에 있든 다른 누군가가 그들을"잡을 "준비가되기를 기대합니다. 제어는 예외를 발생시킨 코드에서 바로 포수 미트까지 한 단계로 전달됩니다. 포수는 발생한 호출의 전체 역 추적을 볼 수 있습니다.
또한, 해당 서브 루틴의 호출자는 서브 루틴이 성공했는지 여부를 확인할 필요가 없습니다. "지금 우리가 여기 있다면 성공했을 것입니다. 그렇지 않으면 예외가 발생하여 지금 여기에 있지 않을 것입니다!" 이 간단한 전략을 통해 코드 디자인 및 디버깅이 훨씬 쉬워집니다.
예외는 치명적 오류 조건이 "정규에 대한 예외"인 상황을 편리하게 허용합니다. 그리고 그것들이 "규칙에 대한 예외 ... "플라이볼! "인 코드 경로에 의해 처리되기 위해서
어설 션은 해제 될 수있는 검사입니다. 그들은 거의 사용되지 않습니다. 왜?
result != null
이러한 검사는 매우 빠르며 저장할 것이 거의 없으므로 간단한 검사에는 사용해서는 안됩니다 .그래서 무엇이 남았습니까? 실제로 예상되는 조건에 대한 비싼 검사 . RB-tree와 같은 데이터 구조의 변형이 좋은 예입니다. 실제로 JDK8에는에 대한 몇 가지 의미있는 주장이 있습니다.ConcurrentHashMap
TreeNodes
때로는 수표가 실제로 비싸지는 않지만 동시에 확실하게 통과 할 것입니다. 내 코드에는 예를 들어,
assert Sets.newHashSet(userIds).size() == userIds.size();
내가 방금 만든 목록에 고유 한 요소가 있다고 확신하지만 문서화하고 다시 확인하고 싶었습니다.
assert
키워드입니다. JDK 1.4에 도입되었습니다. 는 두 종류 assert
의
assert
진술assert
진술.기본적으로 모든 assert
명령문은 실행되지 않습니다. 는 IF assert
문이 거짓 수신 후 자동으로 어설 션 오류가 발생합니다.