development

Java API가 short 또는 byte 대신 int를 사용하는 이유는 무엇입니까?

big-blog 2020. 6. 27. 10:10
반응형

Java API가 short 또는 byte 대신 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, 그리고 하지 작은 유형.

(여담 : 작은 유형 ( byteshort) 기본적으로 만 의도된다 어레이 .의 배열 과 같이 new byte[1000]1000 바이트를 취할 것이며, 같은 배열은 new int[1000]4000 바이트를 취한다)

물론, 다음과 같이intlong 말할 수 있습니다. "... 다음 분명한 질문은 다음 같습니다. 왜이 지침이 (및 )에 대해서만 제공 됩니까?" .

위에서 언급 한 JVM 스펙에 한 가지 이유가 있습니다.

각 유형별 명령어가 모든 Java Virtual Machine의 런타임 데이터 유형을 지원하면 바이트로 표시 될 수있는 것보다 많은 명령어가 있습니다

또한 Java Virtual Machine은 실제 프로세서의 추상화로 간주 될 수 있습니다. 더 작은 유형의 전용 산술 논리 장치도입 하는 것은 노력할 가치가 없습니다. 추가 트랜지스터가 필요하지만 한 클록 사이클에서 하나의 추가 만 수행 할 수 있습니다. JVM이 설계되었을 때의 주요 아키텍처는 32 비트였으며 32 비트에 적합했습니다 int. 64 비트 long값과 관련된 작업 은 특수한 경우로 구현됩니다.

(참고 : 마지막 단락은 가능한 벡터화 등을 고려하여 약간 단순화되었지만 프로세서 설계 주제에 너무 깊이 들어 가지 않고 기본 아이디어를 제공해야합니다)


편집 : 짧은 부록은 질문의 예에 초점을 맞추지 만보다 일반적인 의미 에서 더 작은 유형을 사용하여 필드 를 저장하는 것이 유익하지 않은지 여부를 물을 수 있습니다. 예를 들어, 하나는 메모리에 저장하여 저장 될 수있다 생각 Calendar.DAY_OF_WEEKA와 byte. 그러나 여기서 Java 클래스 파일 형식이 작동합니다. 클래스 파일의 모든 필드 는 크기가 1 int(32 비트) 인 하나 이상의 "슬롯"을 차지 합니다. (이하 "폭"필드 doublelong, 두 개의 슬롯을 차지). 따라서 필드를 명시 적으로 선언 short하거나 byte메모리를 저장하지 않습니다.


(거의)에 대한 모든 작업은 님에게 다음 byte과 같이 short승격시킵니다. int예를 들어 다음과 같이 작성할 수 없습니다.

short x = 1;
short y = 2;

short z = x + y; //error

를 사용할 때 산술이 더 쉽고 간단 int하며 캐스팅 할 필요가 없습니다.

공간의 측면에서, 그것은 만드는 아주 작은 차이. byte그리고 short일을 복잡 것, 우리가 변수의 고정 된 양에 대해 이야기하고 있기 때문에이 마이크로 최적화의 가치를 생각하지 않습니다.

byte임베디드 장치를 프로그래밍하거나 파일 / 네트워크를 처리 할 때 관련성이 있고 유용합니다. 또한 이러한 기본 요소는 제한되어 있습니다. 향후 계산이 한계를 초과 할 경우 어떻게됩니까? Calendar더 큰 숫자로 진화 할 수있는 클래스 확장에 대해 생각해보십시오 .

또한 64 비트 프로세서에서, 지역 주민들이 그렇게 사용하여 레지스터에 저장하고 모든 자원을 사용하지 않습니다 int, short그리고 다른 기본 요소는 전혀 차이를하지 않습니다. 또한 많은 Java 구현에서 변수 * (및 객체)를 정렬합니다 .


* byteshort같은 공간을 차지 int그들이 경우 지역 변수, 클래스 변수 또는 인스턴스 변수. 왜? (대부분의) 컴퓨터 시스템에서 변수 주소는 정렬 되므로 예를 들어 단일 바이트를 사용하는 경우 실제로는 변수 자체와 패딩에 대한 두 바이트로 끝납니다.

반면에 배열에서는 배열의 시작 부분과 끝 부분 만 정렬해야하므로 배열에서는 byte1 바이트, short2 바이트, int4 바이트를 사용합니다. 예를 들어, 사용하려는 경우에 차이가 생기면 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는 심각한 문제가 있습니다. 프로그래머가 적분 상수를 사용하여 코드를 작성할 때마다 코드에주의를 기울여야합니다. 상수가 중요하다면 문서에서 유형을 찾아보고 /하거나 필요한 유형 변환을 수행하십시오.

So now that we've outlined a serious problem, what benefits could you hope to achieve with that philosophy? I would be unsurprised if the only runtime-observable effect of that change would be what type you get when you look the constant up via reflection. (and, of course, whatever errors are introduced by lazy/unwitting programmers not correctly accounting for the types of the constants)

Weighing the pros and the cons is very easy: it's a bad philosophy.


The design complexity of a virtual machine is a function of how many kinds of operations it can perform. It's easier to having four implementations of an instruction like "multiply"--one each for 32-bit integer, 64-bit integer, 32-bit floating-point, and 64-bit floating-point--than to have, in addition to the above, versions for the smaller numerical types as well. A more interesting design question is why there should be four types, rather than fewer (performing all integer computations with 64-bit integers and/or doing all floating-point computations with 64-bit floating-point values). The reason for using 32-bit integers is that Java was expected to run on many platforms where 32-bit types could be acted upon just as quickly as 16-bit or 8-bit types, but operations on 64-bit types would be noticeably slower. Even on platforms where 16-bit types would be faster to work with, the extra cost of working with 32-bit quantities would be offset by the simplicity afforded by only having 32-bit types.

As for performing floating-point computations on 32-bit values, the advantages are a bit less clear. There are some platforms where a computation like float a=b+c+d; could be performed most quickly by converting all operands to a higher-precision type, adding them, and then converting the result back to a 32-bit floating-point number for storage. There are other platforms where it would be more efficient to perform all computations using 32-bit floating-point values. The creators of Java decided that all platforms should be required to do things the same way, and that they should favor the hardware platforms for which 32-bit floating-point computations are faster than longer ones, even though this severely degraded PC both the speed and precision of floating-point math on a typical PC, as well as on many machines without floating-point units. Note, btw, that depending upon the values of b, c, and d, using higher-precision intermediate computations when computing expressions like the aforementioned float a=b+c+d; will sometimes yield results which are significantly more accurate than would be achieved of all intermediate operands were computed at float precision, but will sometimes yield a value which is a tiny bit less accurate. In any case, Sun decided everything should be done the same way, and they opted for using minimal-precision float values.

Note that the primary advantages of smaller data types become apparent when large numbers of them are stored together in an array; even if there were no advantage to having individual variables of types smaller than 64-bits, it's worthwhile to have arrays which can store smaller values more compactly; having a local variable be a byte rather than an long saves seven bytes; having an array of 1,000,000 numbers hold each number as a byte rather than a long waves 7,000,000 bytes. Since each array type only needs to support a few operations (most notably read one item, store one item, copy a range of items within an array, or copy a range of items from one array to another), the added complexity of having more array types is not as severe as the complexity of having more types of directly-usable discrete numerical values.


Actually, there'd be a small advantage. If you have a

class MyTimeAndDayOfWeek {
    byte dayOfWeek;
    byte hour;
    byte minute;
    byte second;
}

then on a typical JVM it needs as much space as a class containing a single int. The memory consumption gets rounded to a next multiple of 8 or 16 bytes (IIRC, that's configurable), so the cases when there are real saving are rather rare.

This class would be slightly easier to use if the corresponding Calendar methods returned a byte. But there are no such Calendar methods, only get(int) which must returns an int because of other fields. Each operation on smaller types promotes to int, so you need a lot of casting.

Most probably, you'll either give up and switch to an int or write setters like

void setDayOfWeek(int dayOfWeek) {
    this.dayOfWeek = checkedCastToByte(dayOfWeek);
}

Then the type of DAY_OF_WEEK doesn't matter, anyway.

참고URL : https://stackoverflow.com/questions/27122610/why-does-the-java-api-use-int-instead-of-short-or-byte

반응형