Java에는 부울 (클래스) 대 부울 (기본)이 있습니다. 마찬가지로 정수 (클래스) 대 int (기본)가 있습니다. 기본 버전과 클래스를 사용하는시기에 대한 모범 사례는 무엇입니까? 특정 (성능?) 이유가없는 한 기본적으로 항상 클래스 버전을 사용해야합니까? 가장 일반적으로 사용되는 방법은 무엇입니까?
Java에는 부울 (클래스) 대 부울 (기본)이 있습니다. 마찬가지로 정수 (클래스) 대 int (기본)가 있습니다. 기본 버전과 클래스를 사용하는시기에 대한 모범 사례는 무엇입니까? 특정 (성능?) 이유가없는 한 기본적으로 항상 클래스 버전을 사용해야합니까? 가장 일반적으로 사용되는 방법은 무엇입니까?
답변:
Joshua Bloch는 효과적인 Java의 항목 5에서
교훈은 분명하다 : 박스형 프리미티브보다 프리미티브를 선호하고 의도하지 않은 오토 박싱에주의한다 .
클래스의 일반적인 용도는 클래스를 일반 유형 (목록 및 맵과 같은 Collection 클래스 포함)으로 사용하거나 암시 적 캐스트없이 다른 유형으로 변환하려는 경우입니다 (예 : Integer
class에는 메소드 doubleValue()
또는) byteValue()
.
편집 : Joshua Bloch의 이유는 다음과 같습니다.
// Hideously slow program! Can you spot the object creation? public static void main(String[] args) { Long sum = 0L; for (long i = 0; i < Integer.MAX_VALUE; i++) { sum += i; } System.out.println(sum); }
이 프로그램은 정답을 얻지 만 한 글자 인쇄상의 오류로 인해 예상보다 훨씬 느립니다. 변수
sum
는 aLong
대신에 선언됩니다.long
즉, 프로그램은 약 2 ^ 31 개의 불필요한Long
인스턴스를 구성합니다 (대개long i
에 추가 될 때마다 대략 1 개씩Long sum
). 합계 선언을에서Long
로 변경long
하면 컴퓨터에서 런타임이 43 초에서 6.8 초로 줄어 듭니다.
일반적인 방법은 제네릭을 다루지 않는 한 기본 요소를 사용하는 것입니다 (자동 상자 및 상자 해제에 대해 알고 있어야합니다 !).
이 협약을 따라야하는 여러 가지 이유가 있습니다.
1. 간단한 실수를 피하십시오.
초보자를 종종 사로 잡는 미묘하고 직관적이지 않은 경우가 있습니다. 숙련 된 코더조차도 실수를해서 실수를 저지르기도합니다 (코드를 디버깅하고 오류를 찾을 때 맹세합니다!).
가장 일반적인 실수는 a == b
대신을 사용하는 것입니다 a.equals(b)
. 사람들은 a == b
프리미티브 작업에 익숙 하므로 Object 래퍼를 사용할 때 쉽게 수행 할 수 있습니다.
Integer a = new Integer(2);
Integer b = new Integer(2);
if (a == b) { // Should be a.equals(b)
// This never gets executed.
}
Integer c = Integer.valueOf(2);
Integer d = Integer.valueOf(2);
if (c == d) { // Should be a.equals(b), but happens to work with these particular values!
// This will get executed
}
Integer e = 1000;
Integer f = 1000;
if (e == f) { // Should be a.equals(b)
// Whether this gets executed depends on which compiler you use!
}
2. 가독성 :
다음 두 가지 예를 고려하십시오. 대부분의 사람들은 두 번째가 더 읽기 쉽다고 말합니다.
Integer a = 2;
Integer b = 2;
if (!a.equals(b)) {
// ...
}
int c = 2;
int d = 2;
if (c != d) {
// ...
}
3. 성능 :
사실 프리미티브를 사용하는 것보다 프리미티브에 Object 래퍼를 사용하는 것이 속도 가 느립니다. 객체 인스턴스화, 메소드 호출 등의 비용을 모든 곳에서 사용하는 것에 추가하고 있습니다 .
Knuth의 "... 시간의 약 97 % : 조기 최적화는 모든 악의 근원"이라는 말은 실제로 적용되지 않습니다. 그는 코드 (또는 시스템)를 더 복잡하게 만드는 최적화에 대해 이야기했습니다. 포인트 # 2에 동의하면 코드가 덜 복잡해집니다.
4. 컨벤션입니다.
다른 Java 프로그래머의 99 %와 다른 스타일을 선택하면 두 가지 단점이 있습니다.
일반적으로 나는 몇 가지 반점을 열거하지만, 나는 여기서 대회에 참석하지 않는 좋은 이유를 솔직히 생각할 수 없습니다!
==
. 객체는와 비교해야합니다 equals()
.
equals()
대상과 비교 ==
하면 예상 결과를 얻을 수 있습니다.
equals()
두 번째 코드 스 니펫에 추가 하고 투표를 변경했습니다.
보통 나는 프리미티브와 함께 간다. 그러나, 같은 클래스를 사용하여 하나의 특질 Integer
및 Boolean
할당의 가능성 null
이 변수에이. 물론 이것은 null
항상 검사 를 수행해야 하지만 올바르게 초기화되지 않은 일부 int
또는 boolean
변수 를 사용하여 논리 오류가 발생하는 것보다 NullPointerException을 얻는 것이 좋습니다 .
물론, Java 8 이후로 한 단계 더 발전 Integer
할 수 있습니다 ( 예 : Optional<Integer>
값이 있거나없는 변수에 사용할 수 있음).
또한 null
해당 변수에 " 알 수없는 "또는 " 와일드 카드 "값 을 할당하는 데 사용할 수 있는 가능성을 소개합니다 . 이는 Ternary Logic 과 같은 일부 상황에서 유용 할 수 있습니다 . 또는 특정 개체가 일부 템플릿과 일치하는지 확인하고 싶을 수도 있습니다. 이 경우 null
개체의 값을 가질 수있는 템플릿의 변수에 사용할 수 있습니다.
null
기본값 으로 할당 할 수있는 능력에서 많은 것을 얻지 못합니다 . 반대로 : 변수를 "초기화"하지 않는 것이 좋습니다. 기본값을 null
설정해도 컴파일러가 종료되지만 모든 코드 경로 에 유용한 할당 이 부족하다는 것을 감지하지 못합니다 . 따라서 컴파일러가 잡을 수있는 오류가 런타임으로 빠져 나갑니다.
0.0
, 또는 -1
, 또는 Integer.MAX_VALUE
, 또는로 설정할 수 False
있지만 결국 기본값인지 또는 해당 변수에 지정된 실제 값인지 알 수 없습니다. 이것이 중요한 경우, null
가치가 더 명확 할 수 있습니다.
null
에는 null paranoia를 포함하여 많은 문제가 있습니다.) 함수 내에서 실제로 사용 시점에서 초기화되지 않은 변수는 일반적으로 발견되지 않은 경우를 나타냅니다. (확정 할당 분석은 단순하므로 오 탐지가 가능합니다. 그러나 논리를 단순화하여이를 해결할 수도 있습니다.)