int
언제 short
또는 byte
충분할 때 Java API가 왜 사용 됩니까?
예 : DAY_OF_WEEK
클래스 의 필드는을 Calendar
사용합니다 int
.
차이가 너무 작 으면 왜 해당 데이터 유형 ( short
, int
)이 존재합니까?
int
언제 short
또는 byte
충분할 때 Java API가 왜 사용 됩니까?
예 : DAY_OF_WEEK
클래스 의 필드는을 Calendar
사용합니다 int
.
차이가 너무 작 으면 왜 해당 데이터 유형 ( short
, int
)이 존재합니까?
답변:
그 이유 중 일부는 이미 지적되었습니다. 예를 들어, "... (거의) byte, short에 대한 모든 연산은 이러한 프리미티브를 int로 승격시킨다" 는 사실입니다 . 그러나 분명한 다음 질문은 다음 과 같습니다. 왜 이러한 유형이 승격 int
됩니까?
한 단계 더 깊이 들어가려면 대답은 단순히 Java Virtual Machine Instruction Set와 관련이있을 수 있습니다. 에 요약 된 바와 같이 , Java 가상 머신 스펙 표 , 모든 정수 산술 연산을 추가, 분할 및 다른 사람과 같은 유형 만 사용할 수 있습니다 int
및 유형 long
, 그리고 하지 작은 유형.
(여담 : 작은 유형 ( byte
및 short
) 기본적으로 만 의도된다 어레이 .의 배열 과 같이 new byte[1000]
1000 바이트를 취할 것이며, 같은 배열은 new int[1000]
4000 바이트를 취한다)
물론, 다음과 같이int
long
말할 수 있습니다. "... 다음 분명한 질문은 다음 과 같습니다. 왜이 지침이 (및 )에 대해서만 제공 됩니까?" .
위에서 언급 한 JVM 스펙에 한 가지 이유가 있습니다.
각 유형별 명령어가 모든 Java Virtual Machine의 런타임 데이터 유형을 지원하면 바이트로 표시 될 수있는 것보다 많은 명령어가 있습니다
또한 Java Virtual Machine은 실제 프로세서의 추상화로 간주 될 수 있습니다. 더 작은 유형의 전용 산술 논리 장치 를 도입 하는 것은 노력할 가치가 없습니다. 추가 트랜지스터가 필요하지만 한 클록 사이클에서 하나의 추가 만 수행 할 수 있습니다. JVM이 설계되었을 때 지배적 인 아키텍처는 32 비트였으며 32 비트에 적합했습니다 int
. 64 비트 long
값과 관련된 작업 은 특수한 경우로 구현됩니다.
(참고 : 마지막 단락은 가능한 벡터화 등을 고려하여 약간 단순화되었지만 프로세서 설계 주제에 너무 깊이 들어 가지 않고 기본 아이디어를 제공해야합니다)
편집 : 짧은 부록은 질문의 예에 초점을 맞추지 만보다 일반적인 의미 에서 더 작은 유형을 사용하여 필드 를 저장하는 것이 유익하지 않은지 여부를 물을 수 있습니다. 예를 들어, 하나는 메모리에 저장하여 저장 될 수있다 생각 Calendar.DAY_OF_WEEK
A와 byte
. 그러나 여기서 Java 클래스 파일 형식이 작동합니다. 클래스 파일의 모든 필드 는 크기가 1 int
(32 비트) 인 하나 이상의 "슬롯"을 차지 합니다. (이하 "폭"필드 double
와 long
, 두 개의 슬롯을 차지). 따라서 필드를 명시 적으로 선언 short
하거나 byte
메모리를 저장하지 않습니다.
int
. 다른 구현에 대한 참조가 있으면 답변을 업데이트하고 그에 따라 링크를 삽입하십시오.
(거의)에 대한 모든 작업은 님에게 다음 byte
과 같이 short
승격시킵니다 int
.
short x = 1;
short y = 2;
short z = x + y; //error
를 사용할 때 산술이 더 쉽고 간단 int
하며 캐스팅 할 필요가 없습니다.
공간의 측면에서, 그것은 만드는 아주 작은 차이. byte
그리고 short
일을 복잡 것, 우리가 변수의 고정 된 양에 대해 이야기하고 있기 때문에이 마이크로 최적화의 가치를 생각하지 않습니다.
byte
임베디드 장치를 프로그래밍하거나 파일 / 네트워크를 처리 할 때 관련성이 있고 유용합니다. 또한 이러한 기본 요소는 제한되어 있습니다. 향후 계산이 한계를 초과 할 경우 어떻게됩니까? Calendar
더 큰 숫자로 진화 할 수있는 클래스 확장에 대해 생각해보십시오 .
또한 64 비트 프로세서에서, 지역 주민들이 그렇게 사용하여 레지스터에 저장하고 모든 자원을 사용하지 않습니다 int
, short
그리고 다른 기본 요소는 전혀 차이를하지 않습니다. 또한 많은 Java 구현에서 변수 * (및 객체)를 정렬합니다 .
* byte
와 short
같은 공간을 차지 int
그들이 경우 지역 변수, 클래스 변수 또는 인스턴스 변수. 왜? (대부분의) 컴퓨터 시스템에서 변수 주소는 정렬 되어 있으므로, 예를 들어 단일 바이트를 사용하는 경우 실제로는 변수 자체와 패딩에 대한 두 바이트로 끝납니다.
반면에 배열에서는 배열의 시작 부분과 끝 부분 만 정렬해야하므로 배열에서는 byte
1 바이트, short
2 바이트, int
4 바이트를 사용합니다. 예를 들어, 사용하려는 경우에 차이가 생기면 System.arraycopy()
성능 차이가 실제로 나타납니다.
정수에 비해 정수를 사용할 때 산술 연산이 더 쉬우므로. 상수가 실제로 short
값 으로 모델링되었다고 가정하십시오 . 그런 다음이 방식으로 API를 사용해야합니다.
short month = Calendar.JUNE;
month = month + (short) 1; // is july
명시 적 캐스팅에 주목하십시오. 짧은 값은 int
산술 연산에 사용될 때 암시 적으로 값으로 승격됩니다 . (피연산자 스택에서 short는 int로 표현되기도합니다.) 이는 사용하기에 꽤 번거로워서 int
상수에 값이 자주 선호되는 이유 입니다.
이에 비해, 고정 된 수의 상수 만이 존재하기 때문에 저장 효율의 이득은 최소이다. 우리는 약 40 개의 상수를 이야기하고 있습니다. 스토리지를에서 int
로 변경하면 short
안전합니다 40 * 16 bit = 80 byte
. 자세한 내용은 이 답변 을 참조하십시오.
적분 상수가 가장 작은 유형으로 저장된 철학을 사용했다면 Java는 심각한 문제가 있습니다. 프로그래머가 적분 상수를 사용하여 코드를 작성할 때마다 코드에주의를 기울여야합니다. 상수가 중요하다면 문서에서 유형을 찾아보고 /하거나 필요한 유형 변환을 수행하십시오.
이제 심각한 문제에 대해 설명 했으므로이 철학을 통해 어떤 이점을 얻을 수 있습니까? 경우 나는 unsurprised 것입니다 만 그 변화의 런타임 관찰 효과는 당신이 반사를 통해 일정을 볼 때 당신이 얻을 입력 한 내용이 될 것입니다. (물론, 상수 유형을 올바르게 설명하지 않는 게으른 / 알지 못하는 프로그래머가 초래 한 오류는 무엇이든)
찬반 양론의 무게는 매우 쉽습니다. 그것은 나쁜 철학입니다.
가상 머신의 설계 복잡성은 수행 할 수있는 작업 종류 수의 함수입니다. "곱하기"(32 비트 정수, 64 비트 정수, 32 비트 부동 소수점 및 64 비트 부동 소수점 각각에 대해 하나씩)와 같은 네 가지 명령어 구현을 갖는 것이 더 쉽다. 위와 같이 더 작은 숫자 유형의 버전도 있습니다. 더 흥미로운 디자인 문제는 더 적은 것보다 4 가지 유형이 필요한 이유입니다 (64 비트 정수로 모든 정수 계산 수행 및 / 또는 64 비트 부동 소수점 값으로 모든 부동 소수점 계산 수행). 32 비트 정수를 사용하는 이유는 Java가 32 비트 유형이 16 비트 또는 8 비트 유형만큼 빠르게 작동 할 수있는 많은 플랫폼에서 실행될 것으로 예상되었지만 64 비트 유형의 조작은 눈에 띄게 될 것이기 때문입니다 느리게.32 비트 유형 만 있습니다.
32 비트 값에 대해 부동 소수점 계산을 수행하는 경우 이점이 다소 명확하지 않습니다. 계산과 같은 일부 플랫폼이 있습니다float a=b+c+d;
모든 피연산자를 고정밀 유형으로 변환하고 추가 한 다음 결과를 저장을 위해 32 비트 부동 소수점 숫자로 다시 변환하여 가장 빠르게 수행 할 수 있습니다. 32 비트 부동 소수점 값을 사용하여 모든 계산을보다 효율적으로 수행 할 수있는 다른 플랫폼이 있습니다. Java 제작자는 모든 플랫폼이 동일한 방식으로 작업을 수행해야하며 32 비트 부동 소수점 계산이 더 긴 PC보다 빠르지 만 하드웨어 속도를 향상시켜야한다고 결정했습니다. 부동 소수점 단위가없는 많은 컴퓨터뿐만 아니라 일반적인 PC에서도 부동 소수점 연산의 정밀도. btw는 b, c 및 d의 값에 따라 위에서 언급 한 것과 같은 표현식을 계산할 때 고정밀 중간 계산을 사용합니다.float a=b+c+d;
때로는 모든 중간 피연산자가 float
정밀하게 계산 된 것보다 훨씬 더 정확한 결과를 얻을 수 있지만 때로는 조금 덜 정확한 값을 얻을 수도 있습니다. 어쨌든 썬은 모든 것을 동일한 방식으로 수행하기로 결정했으며 최소 정밀도 float
값 을 사용하기로 결정했습니다 .
더 작은 데이터 유형의 주요 이점은 다수의 데이터 유형이 배열에 함께 저장 될 때 분명해집니다. 64 비트보다 작은 유형의 개별 변수를 갖는 이점이 없더라도 더 작은 값을보다 컴팩트하게 저장할 수있는 배열을 갖는 것이 좋습니다. 지역 변수 가 7 바이트를 절약 하는 byte
것이 아니라 long
1,000,000 번호의 배열은 각 수를 갖는 홀드 byte
아니라이보다long
7,000,000 바이트의 파도. 각 배열 유형은 몇 가지 작업 만 지원하면되므로 (주로 하나의 항목 읽기, 하나의 항목 저장, 배열 내의 항목 범위 복사 또는 한 배열에서 다른 배열로 항목 범위 복사) 더 많은 복잡성 배열 유형은 더 많은 유형의 직접 사용 가능한 이산 숫자 값을 갖는 복잡성만큼 심각하지 않습니다.
실제로 작은 이점이 있습니다. 당신이 있다면
class MyTimeAndDayOfWeek {
byte dayOfWeek;
byte hour;
byte minute;
byte second;
}
그런 다음 일반적인 JVM에서는 단일을 포함하는 클래스만큼 많은 공간이 필요합니다 int
. 메모리 소비는 8 바이트 또는 16 바이트의 다음 배수 (IIRC, 구성 가능)로 반올림되므로 실제 저장이있는 경우는 거의 없습니다.
해당 클래스 Calendar
가을 반환 하면이 클래스를 사용하는 것이 약간 더 쉬울 것 byte
입니다. 그러나 그러한 Calendar
메소드 는 없으며 다른 필드 get(int)
로 int
인해 리턴해야합니다 . 작은 유형의 각 작업은로 승격 int
되므로 캐스팅이 많이 필요합니다.
아마도, 당신은 포기하고 다음과 int
같은 설정 또는 쓰기 설정기로 전환 할 것입니다
void setDayOfWeek(int dayOfWeek) {
this.dayOfWeek = checkedCastToByte(dayOfWeek);
}
그러면 DAY_OF_WEEK
어쨌든 유형이 중요하지 않습니다.