다음 코드는 다음을 던집니다 NullPointerException
.
int num = Integer.getInteger("123");
내 컴파일러 getInteger
가 정적이기 때문에 null을 호출 합니까? 말이 안 돼!
무슨 일이야?
다음 코드는 다음을 던집니다 NullPointerException
.
int num = Integer.getInteger("123");
내 컴파일러 getInteger
가 정적이기 때문에 null을 호출 합니까? 말이 안 돼!
무슨 일이야?
답변:
여기에는 두 가지 문제가 있습니다.
Integer getInteger(String)
당신이 생각하는대로하지 않는다
null
이 경우 반환Integer
to 에서 할당 int
하면 자동 언 박싱 이 발생합니다.
Integer
IS null
, NullPointerException
발생합니다구문 분석하기 (String) "123"
위해 (int) 123
, 당신은 예를 사용할 수 있습니다 int Integer.parseInt(String)
.
Integer
API 참조Integer.getInteger
이 메서드가 수행하는 작업에 대한 설명서의 내용은 다음과 같습니다.
public static Integer getInteger(String nm)
: 지정된 이름을 가진 시스템 속성의 정수 값을 결정합니다. 지정된 이름의 속성이 없거나 지정된 이름이 비어 있거나null
또는 속성에 올바른 숫자 형식이없는 경우null
반환됩니다.
즉,이 메서드는 a String
를 int/Integer
값 으로 구문 분석하는 것과 관련이 없지만 오히려 System.getProperty
메서드 와 관련이 있습니다.
물론 이것은 상당히 놀라운 일입니다. 라이브러리에 이와 같은 놀라움이 있다는 것은 안타깝지만 귀중한 교훈을 제공합니다. 항상 문서를 찾아 메서드가 수행하는 작업을 확인하십시오.
공교롭게도이 문제의 변형은 Return of the Puzzlers : Schlock and Awe (TS-5186) , Josh Bloch 및 Neal Gafter의 2009 JavaOne 기술 세션 프레젠테이션에 등장했습니다. 결론 슬라이드는 다음과 같습니다.
도덕
- 도서관에는 이상하고 끔찍한 방법이 숨어 있습니다.
- 일부는 무해한 이름을 가지고 있습니다.
- 코드가 잘못 작동하는 경우
- 올바른 메서드를 호출하고 있는지 확인
- 라이브러리 문서 읽기
- API 디자이너 용
- 최소 경악의 원칙을 위반하지 마십시오
- 추상화 계층을 위반하지 마십시오
- 매우 다른 행동에 유사한 이름을 사용하지 마십시오.
완전성을 위해 Integer.getInteger
다음 과 유사한 방법도 있습니다 .
물론 다른 문제는 어떻게 NullPointerException
던져 지는가입니다. 이 문제에 집중하기 위해 다음과 같이 코드 조각을 단순화 할 수 있습니다.
Integer someInteger = null;
int num = someInteger; // throws NullPointerException!!!
다음은 Effective Java 2nd Edition, 항목 49의 인용문입니다. 박스형 기본 형식보다 기본 형식을 선호합니다.
요약하면, 선택권이있을 때마다 boxed primitive보다 우선적으로 primitive를 사용하십시오. 기본 유형은 더 간단하고 빠릅니다. 박스형 프리미티브를 사용해야한다면 조심하세요! Autoboxing은 boxed primitives를 사용하는 위험은 아니지만 자세한 정도를 줄입니다. 프로그램이 두 개의 박스형 프리미티브를
==
연산자 와 비교할 때 ID 비교를 수행합니다. 이는 거의 확실히 원하는 것이 아닙니다. 프로그램이 boxed 및 unboxed 프리미티브와 관련된 혼합 유형 계산을 수행하면 unboxing을 수행하고 프로그램에서 unboxing을 수행하면NullPointerException
. 마지막으로, 프로그램이 기본 값을 상자에 넣으면 비용이 많이 들고 불필요한 객체 생성이 발생할 수 있습니다.
제네릭과 같은 boxed primitive를 사용하는 것 외에 선택의 여지가없는 곳이 있습니다. 그렇지 않으면 boxed primitives를 사용하기로 한 결정이 정당한지 진지하게 고려해야합니다.
Integer.getInteger(s)
대략 같 Integer.parseInt(System.getProperty(s))
습니까? 시스템 속성에서 정보를 가져오고 있다는 사실을 강조하기 때문에 더 장황하지만 두 번째를 선호한다고 생각합니다.
Integer.decode
대신에를 사용 하는 것을 제외하고는 올바른 길을 가고 있었는데 Integer.parseInt
, 이는 각각 선행을 0x
찾거나 0
숫자를 16 진수 또는 8 진수로 구문 분석합니다.
NullPointerException
묻는 사람들을 위해 ? : programmers.stackexchange.com/questions/158908/...
에서 http://konigsberg.blogspot.com/2008/04/integergetinteger-are-you-kidding-me.html :
getInteger '지정된 이름을 가진 시스템 속성의 정수 값을 결정합니다.'
당신은 이것을 원합니다 :
Integer.parseInt("123")
getInteger () 메소드의 문서를 확인하십시오 . 이 메서드에서 String
매개 변수는 지정된 이름을 가진 시스템 속성의 정수 값을 결정하는 시스템 속성입니다. 여기에 설명 된대로 "123"은 시스템 속성의 이름이 아닙니다 . 이 문자열을로 변환 int
하려면 메서드를
int num = Integer.parseInt("123")
.