programing

부언, 조건부 연산자 및 자동 박스

randomtip 2022. 9. 4. 12:41
반응형

부언, 조건부 연산자 및 자동 박스

왜 던지죠?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.FALSEnullboolean--그건 불가능해요.하지만 그건 질문이 아니야.문제는 일까?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이 반환됩니다.


이 질문에는 유사한 유형의 분석이 필요합니다.

Java 조건부 연산자 ?: 결과 유형

행:

    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

반응형