여기에서 정수 리터럴을 (int)로 캐스팅해야하는 이유를 아십니까?


122

다음 예에서

int i = -128;
Integer i2 = (Integer) i; // compiles

Integer i3 = (Integer) -128; /*** Doesn't compile ***/

Integer i4 = (Integer) (int) -128; // compiles
Integer i4 = -128; // compiles
Integer i5 = (int) -128; // compiles
Integer i6 = (Integer) (-128); // compiles
Integer i7 = (Integer) 0-128; // compiles

나는 캐스팅 수 없습니다 -128(Integer)하지만 난 캐스트 할 수 있습니다 (int) -128.

난 항상 생각 -128이었다 int종류와 함께 캐스팅하는 것은 (int)중복해야합니다.

줄의 오류 i3

cannot find symbol variable Integer

Java 6 업데이트 29 및 Java 7 업데이트 1에서 이것을 시도했습니다.

편집 : +128대신 -128. 단항 연산자와 이항 연산자 사이의 혼동으로 보입니다.


5
당신의 컴파일러는 무엇입니까? Integer i = -128;그래도 컴파일되어야합니다.
bestsss

이상 Integer i3 = (Integer) (-128);하지만 준수합니다.
Eng.Fouad

2
@ Eng.Fouad, Peter, 단항 기호 (+-)는 오른쪽에서 왼쪽으로의 연관성을 가지며 플러스, 마이너스는 왼쪽에서 오른쪽으로 연결됩니다. -128의 효과는 +128과 동일하며 앞에 0을 입력하면 수정됩니다 (예 : 0-128 또는 0 + 128). (atm을 테스트 할 수 없지만 그럴 것입니다)
bestsss

좋은 질문! 개인적으로 단항 / 이진 연산자의 해결과 캐스트가 표현식으로 처리 될 때 JLS 참조를보고 싶습니다. 그렇지 않으면 다른 컴파일러가 오류로 간주하지 않을 수 있습니다!
Bringer128

1
또한 내 IDE에서 발생하는 오류는 Expression expected어디에 Integer있습니다.
Bringer128

답변:


151

컴파일러는 뺄 시도 128에서 (Integer)대신 캐스팅의 -128Integer. ()그것을 수정하기 위해 추가

Integer i3 = (Integer) -128; // doesn't compile
Integer i3 = (Integer) (-128); // compiles

댓글에있는 BoltClock에 따르면 캐스트 int는 예약어이므로 식별자로 해석 할 수 없기 때문에 의도 한대로 작동합니다.

Bringer128은 JLS Reference 15.16을 찾았습니다 .

 CastExpression :
    (PrimitiveType Dims opt ) UnaryExpression
    (ReferenceType) UnaryExpressionNotPlusMinus

보시다시피 기본 유형으로 UnaryExpression캐스트 하려면 any가 필요 하지만 참조 유형으로 캐스트하려면 UnaryExpressionNotPlusMinus. 이것들은 JLS 15.15 의 CastExpression 직전에 정의되어 있습니다 .


31
intJava의 키워드 이기 때문이라고 생각 하지만 Integer그렇지 않습니다. int키워드 이므로 변수 나 클래스의 식별자로 사용할 수 없으며 유형 변환 일 가능성 만 남습니다. 그것은 그것을 설명 할 것입니다.
BoltClock

@BoltClock 답변에 귀하의 의견을 통합했습니다.
Jens Schauder 2011 년

3
이 질문을 더욱 멋진 답변으로 만들기 위해 JLS에 내 링크를 추가 하시겠습니까?
Bringer128

3
이 문제에 대한 흥미로운 (나에게) 주름은 C #에서 유사한 문제를 해결하는 방법입니다.이 문제는 또한 "이진 빼기 연산자에 대한 피연산자로서의 괄호로 묶인 표현"과 "올바른 피연산자의 캐스트 연산자"사이의 문법이 모호합니다. 캐스트는 단항 마이너스 표현식입니다. " 모호성을 해결하는 데 사용하는 휴리스틱에 대한 자세한 설명은 C # 사양의 섹션 7.7.6을 참조하십시오.
Eric Lippert 2011 년

1
@BillK 왜 그렇게 말합니까? C # 사양은 섹션 7.7.6의 연산자 오버로딩을 참조하지 않으므로 문제가되지 않았습니다.
Bringer128 2011 년

48

JLS 참조를 찾았습니다. 15.16 .

 CastExpression :
    (PrimitiveType Dims opt ) UnaryExpression
    (ReferenceType) UnaryExpressionNotPlusMinus

보시다시피 기본 유형으로 UnaryExpression캐스트 하려면 any가 필요 하지만 참조 유형으로 캐스트하려면 UnaryExpressionNotPlusMinus. 이것들은 JLS 15.15 의 CastExpression 직전에 정의되어 있습니다 .

캐스트를 기본 유형으로 변경해야합니다.

... (int) -128;

또는 캐스트 오른쪽에있는 표현식을 플러스 마이너스가 아닌 단항 표현식으로 변경할 수 있습니다.

... (Integer) (-128);  // Either
... (Integer) 0 - 128; // Or

12

컴파일러 -는을 두 인수 빼기 연산자로 해석합니다 . 즉, 이름이 지정된 다른 숫자에서 128을 빼려고합니다.Integer , 하지만 범위에 그러한 변수가 없습니다.

이것은 다음을 컴파일합니다.

Integer i3 = (Integer) (-128)

(int)차이를 만드는 이유에 대한 의견을 추가 할 수 있습니다 .
Peter Lawrey 2011 년

1
오토 박싱 때문이지?
Brian Roach

9

이것은 구문 분석과 관련이있을 수 있습니다. 그것을주의해라

Integer i4 = (Integer) (-128); 

잘 작동합니다.

일반적으로 Integer 클래스로 캐스트해서는 안됩니다. 여기에는 자동 박싱이라는 것이 포함되며 코드에 미묘한 오류가 발생할 수 있습니다. 원하는 작업을 수행하는 데 선호되는 방법은 다음과 같습니다.

Integer i6 = Integer.valueOf(-128)

1
Integer로 캐스트는 valueOf에 대한 정확히 합성 설탕입니다.
bestsss

4
예, 그러나 때로는 합성 설탕이 미묘한 방식으로 실패합니다. 자동 박싱으로 인해 대형 애플리케이션에서 널 포인터 예외를 추적하기가 어려웠습니다. 우리는 미래에 골치 아픈 일을 피하기 위해 자동 복싱을 오류로 처리하는 데까지갔습니다. 마법은 좋지만 실패하면 머리가 아파요. 나는 명시 적으로 표현하고 두통을 덜어주는 것이 더 낫다는 것을 알았습니다.
Krystian Cybulski

NPE는 발신 함이 전혀 없어 사실입니다. for (int i in Collection<Integer>)b / c NPE 와 같은 Esp 사례 는 절대적으로 예상치 못한 위치에 있습니다. 캐시 범위가 작기 때문에 (XX 옵션을 사용하여 늘릴 수 있지만) 실제로 Integer w / autoboxing을 사용하지 않지만 동일한 작업을 수행하기 위해 IntegerProvider (1.1 이후)라는 클래스가 있습니다. Map 사용 (java.util에서 모두) Integer-> Anything은 사소한 경우에 사용되지 않고 거의 항상 더 나은 솔루션이 없으면 일반적으로 성능 저하입니다.
bestsss

int를 Integer로 캐스팅 하면 힙 오버플로를 제외하고는 오류가 발생할 수 없습니다 . 그러나 그 반대는 사실이 아닙니다.
Ingo

@MattBall, 잘 모르겠습니다. 합성 설탕이 널리 사용됩니다. eggcorns.lascribe.net/forum/viewtopic.php?id=4400 및 합성 사운드가 나에게 더 좋습니다.
bestsss

9

그것은 그것을 파싱 Integer <minus operator> 128하고 변수를 찾지 않습니다 Integer. 당신은 포장해야합니다 -128괄호 :

Integer i3 = (Integer) (-128);  // compiles

다른 모든 답변에도 +1을 받았습니다. 모두 정확하기 때문에 :)
Bohemian

7
Integer i3 = (Integer) (-128);

문제는 -컴파일러가 그것을 연산자로 본다는 것입니다.


6

3 행은 괄호 안의 표현식에서 128을 빼려고하고 괄호 안의 표현식은 그렇지 않고 int 유형의 표현식이 아닌 것처럼 해석됩니다 ( '-'를 '-'연산자로 취급합니다). 표현식을 다음과 같이 변경하는 경우 :

Integer i3 = (Integer) (-128);

그러면 컴파일러는 '-'가 음의 정수를 나타내는 단항 마이너스임을 이해할 것입니다.


3

C # 컴파일러는 동일한 동작을합니다. 그래도 컴파일에 실패한 이유를 더 잘 알 수 있습니다.

음수 값을 캐스트하려면 값을 괄호로 묶어야합니다.

당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.