etc./StackOverFlow

Java의 +=, -=, *=, /= 복합 할당 연산자에 캐스팅이 필요하지 않은 이유는 무엇입니까?

청렴결백한 만능 재주꾼 2021. 10. 6. 03:01
반응형

질문자 :Honza Brabec


오늘까지는 예를 들어 다음과 같이 생각했습니다.

 i += j;

바로가기:

 i = i + j;

그러나 우리가 이것을 시도한다면:

 int i = 5; long j = 8;

그런 다음 i = i + j; 컴파일되지 않지만 i += j; 잘 컴파일됩니다.

i += j; 의미합니까? i = (type of i) (i + j) 와 같은 것에 대한 단축키입니까?



이러한 질문에 항상 그렇듯이 JLS가 답을 가지고 있습니다. 이 경우 §15.26.2 복합 할당 연산자 . 추출물:

E1 op= E2 형식의 복합 할당 표현식은 E1 = (T)((E1) op (E2)) 와 동일합니다. 여기서 T E1 의 유형입니다. 단, E1 은 한 번만 평가됩니다.

§15.26.2 에서 인용한 예

[...] 다음 코드가 맞습니다.

 short x = 3; x += 4.6;

다음과 같기 때문에 x의 값은 7입니다.

 short x = 3; x = (short)(x + 4.6);

즉, 귀하의 가정이 맞습니다.


Lukas Eder

이 캐스팅의 좋은 예는 *= 또는 /=를 사용하는 것입니다.

 byte b = 10; b *= 5.7; System.out.println(b); // prints 57

또는

 byte b = 100; b /= 2.5; System.out.println(b); // prints 40

또는

 char ch = '0'; ch *= 1.1; System.out.println(ch); // prints '4'

또는

 char ch = 'A'; ch *= 1.5; System.out.println(ch); // prints 'a'

Peter Lawrey

아주 좋은 질문입니다.Java 언어 사양 은 귀하의 제안을 확인합니다.

예를 들어 다음 코드는 정확합니다.

 short x = 3; x += 4.6;

다음과 같기 때문에 x의 값은 7입니다.

 short x = 3; x = (short)(x + 4.6);

Thirler

예,

기본적으로 우리가 쓸 때

 i += l;

컴파일러는 이것을 다음으로 변환합니다.

 i = (int)(i + l);

.class 파일 코드를 확인했습니다.

정말 알아두면 좋은 점


Umesh Awasthi

i = i + l 경우 explicitly long 에서 int 로 캐스트해야 합니다. 그러면 컴파일되어 올바른 출력을 제공합니다. 처럼

 i = i + (int)l;

또는

 i = (int)((long)i + l); // this is what happens in case of += , dont need (long) casting since upper casting is done implicitly.

그러나 += 경우 연산자가 암시적으로 오른쪽 변수 유형에서 왼쪽 변수 유형으로 유형 캐스팅을 수행하므로 명시적으로 캐스팅할 필요가 없기 때문에 잘 작동합니다.


dku.rajkumar

여기서 문제는 유형 캐스팅과 관련이 있습니다.

int와 long을 추가하면

  1. int 객체는 long으로 캐스팅되고 둘 다 추가되고 long 객체를 얻습니다.
  2. 그러나 long 객체는 암시적으로 int로 캐스팅될 수 없습니다. 따라서 명시적으로 수행해야 합니다.

그러나 += 는 유형 캐스팅을 수행하는 방식으로 코딩됩니다. i=(int)(i+m)


dinesh028

Java에서 유형 변환은 할당 작업의 오른쪽에 있는 표현식의 유형이 할당의 왼쪽에 있는 변수 유형으로 안전하게 승격될 수 있을 때 자동으로 수행됩니다. 따라서 다음을 안전하게 할당할 수 있습니다.

 byte -> short -> int -> long -> float -> double.

반대의 경우에도 동일하게 작동하지 않습니다. 예를 들어 첫 번째는 두 번째보다 더 많은 저장 공간이 필요하고 결과적으로 정보가 손실될 수 있기 때문에 long을 int로 자동 변환할 수 없습니다. 그러한 변환을 강제하려면 명시적 변환을 수행해야 합니다.
유형 - 전환


tinker_fairy

가끔 면접에서 그런 질문을 할 수 있습니다.

예를 들어 다음과 같이 작성할 때:

 int a = 2; long b = 3; a = a + b;

자동 유형 캐스팅이 없습니다. C++에서는 위의 코드를 컴파일하는 데 오류가 없지만 Java에서는 Incompatible type exception 과 같은 오류가 발생합니다.

따라서 이를 방지하려면 다음과 같이 코드를 작성해야 합니다.

 int a = 2; long b = 3; a += b;// No compilation error or any exception due to the auto typecasting

Stopfan

주요 차이점은 a = a + b 하면 유형 변환이 진행되지 않으므로 컴파일러가 유형 변환을 하지 않는 것에 대해 화를 낸다는 것입니다. 그러나 함께 a += b , 무엇을 정말하고있는 것은 타입 캐스팅의 인 b 와 호환되는 유형 a . 그래서 당신이 할 경우

 int a=5; long b=10; a+=b; System.out.println(a);

당신이 정말로하고있는 일은 다음과 같습니다.

 int a=5; long b=10; a=a+(int)b; System.out.println(a);

takra

여기서 미묘한 포인트...

j 가 double이고 i 가 int일 때 i+j 대한 암시적 유형 변환이 있습니다. Java는 정수 사이에 연산이 있을 때 항상 정수를 정수로 변환합니다.

여기서 i 는 정수이고 j i+=j 를 명확히 하기 위해 다음과 같이 설명할 수 있습니다.

 i = <int>(<double>i + j)

참조: 암시적 캐스팅에 대한 이 설명

이 경우 명확성을 위해 j(int) 로 유형 변환할 수 있습니다.


Gabe Nones

Java 언어 사양 E1 op= E2 E1 = (T) ((E1) op (E2)) 와 동일하다고 정의합니다. 여기서 TE1 유형이고 E1 은 한 번 평가 됩니다.

그것은 기술적 인 대답이지만 왜 그런지 궁금해 할 수 있습니다. 자, 다음 프로그램을 생각해보자.

 public class PlusEquals { public static void main(String[] args) { byte a = 1; byte b = 2; a = a + b; System.out.println(a); } }

이 프로그램은 무엇을 인쇄합니까?

당신은 3을 추측 했습니까? 유감스럽게도 이 프로그램은 컴파일되지 않습니다. 왜요? 음, Java에서 바이트 추가가 int 를 반환하도록 정의되어 있습니다. 이것은 Java Virtual Machine이 바이트 코드를 저장하기 위해 바이트 작업을 정의하지 않기 때문이라고 생각합니다(결국 제한된 수의 작업이 있음). 대신 정수 작업을 사용하는 것은 언어에 노출된 구현 세부 사항입니다.

그러나 a = a + b E1 += E2 E1 = E1 + E2 로 정의된 a += b 가 바이트에 대해 작동하지 않는다는 것을 의미합니다. 앞의 예에서 알 수 있듯이 실제로 그렇습니다. += 연산자가 바이트 및 단락에 대해 작동하도록 하는 해킹으로 암시적 캐스트가 포함됩니다. 그다지 대단한 해킹은 아니지만 Java 1.0 작업 중에 처음에는 언어를 릴리스하는 데 중점을 두었습니다. 이제 이전 버전과의 호환성으로 인해 Java 1.0에 도입된 이 해킹을 제거할 수 없습니다.


Konrad Borowski

출처 : http:www.stackoverflow.com/questions/8710619/why-dont-javas-compound-assignment-operators-require-casting

반응형