부언, 조건부 연산자 및 자동 박스
왜 던지죠?NullPointerException
public static void main(String[] args) throws Exception {
Boolean b = true ? returnsNull() : false; // NPE on this line.
System.out.println(b);
}
public static Boolean returnsNull() {
return null;
}
이것이 아닌 동안
public static void main(String[] args) throws Exception {
Boolean b = true ? null : false;
System.out.println(b); // null
}
?
은 어쨋든 이다.false
타타에 Boolean.FALSE
null
boolean
--그건 불가능해요.하지만 그건 질문이 아니야.문제는 왜일까?JLS에서 이 동작을 확인할 수 있는 참조가 있습니까?특히 두 번째 케이스는?
은 '이 있다는 입니다.returnsNull()
메서드는 컴파일 시 표현의 정적 입력에 영향을 줍니다.
E1: `true ? returnsNull() : false` - boolean (auto-unboxing 2nd operand to boolean)
E2: `true ? null : false` - Boolean (autoboxing of 3rd operand to Boolean)
Java Language Specification, 섹션 15.25 Conditional Operator ?를 참조하십시오.
경우 두 및 세 의 유형은 E1입니다.
Boolean
★★★★★★★★★★★★★★★★★」boolean
이치노두 번째 오퍼랜드와 세 번째 오퍼랜드 중 하나가 부울형이고 다른 오퍼랜드의 유형이 부울형일 경우 조건식의 유형은 부울형입니다.
은 '유형'이기 때문에,
boolean
는 로boolean
를 두 「」의 반환값returnsNull()
라고 타이핑하다boolean
, 당연히 「NPE」로부터의null
이치노경우 두 및 세 은 E2입니다.
<special null type>
)Boolean
(및 (E1!) »boolean
각각 특정 타이핑 절이 적용되지 않기 때문에('읽어보세요!'), 마지막 "time" 절이 적용됩니다.그 이외의 경우에는 제2 오퍼랜드와 제3 오퍼랜드가 각각 S1, S2 타입이다.S1에 박스 변환을 적용한 T1을, S2에 박스 변환을 적용한 T2를 S2로 한다.조건식의 유형은 캡처 변환(§5.1.10)을 lub(T1, T2)에 적용한 결과(1515.12.2.7)입니다.
- S1 ==
<special null type>
(§ 4.1 참조) - S2 ==
boolean
- T1 == 박스(S1) ==
<special null type>
(제5.1.7조의 복싱 변환 목록의 마지막 항목 참조) - T2 == 박스(S2) == '부리안'
- lub(T1, T2) ==
Boolean
는 '어느 정도'입니다.
Boolean
세 가 """로 .Boolean
는 세 오토박스 )를false
). 두에는 와 두 번째 오퍼랜드에는 자동 언박스가 필요하지 않습니다.E1
이 때문에, 다음의 경우, NPE 의 자동 언박스는 행해지지 않습니다.null
이 반환됩니다.- S1 ==
이 질문에는 유사한 유형의 분석이 필요합니다.
행:
Boolean b = true ? returnsNull() : false;
내부적으로는 다음과 같이 변환됩니다.
Boolean b = true ? returnsNull().booleanValue() : false;
다음과 같이 언박스를 해제합니다.null.booleanValue()
NPE가 생성됩니다.
이것은 오토박싱을 사용할 때 중요한 함정 중 하나입니다.이 동작은 실제로 5.1.8 JLS에 기재되어 있습니다.
편집: 세 번째 연산자가 (암시적인 캐스트 추가) 부울 타입이기 때문에 언박스가 된 것 같습니다.
Boolean b = (Boolean) true ? true : false;
Java Language Specification, 섹션 15.25:
- 두 번째 오퍼랜드와 세 번째 오퍼랜드 중 하나가 부울형이고 다른 오퍼랜드의 유형이 부울형일 경우 조건식의 유형은 부울형입니다.
따라서 첫 번째 예에서는 콜을 시도합니다.Boolean.booleanValue()
변환하기 위해Boolean
로.boolean
첫 번째 규칙에 따라
두 번째 경우 첫 번째 피연산자가 null 유형이고 두 번째 피연산자가 참조 유형이 아니므로 자동 상자 변환이 적용됩니다.
- 그 이외의 경우에는 제2 오퍼랜드와 제3 오퍼랜드가 각각 S1, S2 타입이다.S1에 박스 변환을 적용한 T1을, S2에 박스 변환을 적용한 T2를 S2로 한다.조건식의 유형은 캡처 변환(§5.1.10)을 lub(T1, T2)에 적용한 결과(1515.12.2.7)입니다.
이 문제는 바이트 코드에서 확인할 수 있습니다.메인의 바이트 코드 3행에서3: invokevirtual #3 // Method java/lang/Boolean.booleanValue:()Z
값 null의 박스 부울,invokevirtual
방법java.lang.Boolean.booleanValue
물론 NPE를 던집니다.
public static void main(java.lang.String[]) throws java.lang.Exception;
descriptor: ([Ljava/lang/String;)V
flags: ACC_PUBLIC, ACC_STATIC
Code:
stack=2, locals=2, args_size=1
0: invokestatic #2 // Method returnsNull:()Ljava/lang/Boolean;
3: invokevirtual #3 // Method java/lang/Boolean.booleanValue:()Z
6: invokestatic #4 // Method java/lang/Boolean.valueOf:(Z)Ljava/lang/Boolean;
9: astore_1
10: getstatic #5 // Field java/lang/System.out:Ljava/io/PrintStream;
13: aload_1
14: invokevirtual #6 // Method java/io/PrintStream.println:(Ljava/lang/Object;)V
17: return
LineNumberTable:
line 3: 0
line 4: 10
line 5: 17
Exceptions:
throws java.lang.Exception
public static java.lang.Boolean returnsNull();
descriptor: ()Ljava/lang/Boolean;
flags: ACC_PUBLIC, ACC_STATIC
Code:
stack=1, locals=0, args_size=0
0: aconst_null
1: areturn
LineNumberTable:
line 8: 0
언급URL : https://stackoverflow.com/questions/3882095/booleans-conditional-operators-and-autoboxing
'programing' 카테고리의 다른 글
불투명 C 구조체: 다양한 선언 방법 (0) | 2022.09.04 |
---|---|
아티팩트 org.apache.maven을 전송할 수 없습니다.플러그인: maven-surefire-pair: pattern: 2.7.1에서 central(http://repo1.maven.org/maven2)로) (0) | 2022.09.04 |
Java에서의 정규식 \\s vs. \\s (0) | 2022.09.04 |
Axios 호출에서 Vuejs img 요소로 이미지를 표시하려면 어떻게 해야 합니까?효과가 있는 것을 본 적이 없다 (0) | 2022.09.03 |
IntelliJ에서 이 기호는 무엇을 의미합니까? ('J'가 들어간 파일 이름의 왼쪽 아래 모서리에 있는 빨간색 원) (0) | 2022.09.03 |