ここで整数リテラルを(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 update 29とJava 7 update 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 '26年

1
また、IDEで発生するエラーはExpression expectedどこにあるのでしょうかInteger
Bringer128 '26年

回答:


151

コンパイラは、にキャストする代わりに、からの減算128を試みます。追加して修正する(Integer)-128Integer()

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

コメントのBoltClockによると、キャストintは意図したとおりに 機能します。これは予約語であり、識別子として解釈できないためです。

そして、Bringer128はJLSリファレンス15.16を見つけました。

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

ご覧のとおり、プリミティブ型へのキャストにはany UnaryExpressionが必要ですが、参照型へのキャストにはが必要UnaryExpressionNotPlusMinusです。これらは、JLS 15.15のCastExpressionの直前に定義されています。


31
それintはJavaのキーワードだからですが、そうでIntegerはありません。intはキーワードなので、変数またはクラスの識別子として使用することはできず、型キャストになる可能性は残ります。それはそれを説明するでしょう。
BoltClock

@BoltClockは、コメントに回答を組み込みました。
Jens Schauder、2011年

3
これをさらにすばらしい答えにするには、私のリンクをJLSに追加しますか?
Bringer128 '26年

3
この問題に関する興味深い(私にとっての)しわは、C#での類似の問題をどのように解決するかです。これは、「括弧付きの式をオペランドとしてのバイナリ減算演算子」と「キャスト演算子の正しいオペランドキャストは単項マイナス式です。」曖昧さの解決を試みて賢くするために使用するヒューリスティックの詳細な説明については、C#仕様のセクション7.7.6を参照してください。
Eric Lippert、2011年

1
@BillKなぜあなたはそれを言うのですか?C#仕様では、セクション7.7.6でのオペレーターのオーバーロードについて言及していないため、問題ではありませんでした。
Bringer128

48

JLSリファレンスを見つけました。15.16

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

ご覧のとおり、プリミティブ型へのキャストにはany UnaryExpressionが必要ですが、参照型へのキャストにはが必要UnaryExpressionNotPlusMinusです。これらは、JLS 15.15のCastExpressionの直前に定義されています。

キャストをプリミティブ型に変更する必要があります:

... (int) -128;

または、キャストの右側にある式をプラスマイナスマイナス単項式に変更できます。

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

12

コンパイラーは-、2引数のマイナス演算子として解釈します。つまり、と名付けられた他の数値から128を減算しようとしIntegerますが、そのような変数はスコープ内にありません。

これはコンパイルします:

Integer i3 = (Integer) (-128)

(int)違いを生む理由についてコメントを追加できます。
Peter Lawrey、2011年

1
オートボクシングが原因ですよね?
ブライアンローチ

9

これは構文解析と関係があるかもしれません。そのことに注意してください

Integer i4 = (Integer) (-128); 

正常に動作します。

通常、Integerクラスにキャストしないでください。これには、オートボクシングと呼ばれるものが含まれ、コードで微妙なエラーが発生する可能性があります。あなたがしたいことをするための好ましい方法は:

Integer i6 = Integer.valueOf(-128)

1
Integerへのキャストは、valueOfの合成糖です。
bestsss

4
はい、しかし、時々、合成糖は微妙な方法で失敗します。自動ボクシングが原因で、大規模なアプリケーションでnullポインター例外を追跡するのが困難でした。将来の悩みを解消するために、オートボクシングをエラーとして扱うことまで行いました。魔法はいいですが、失敗すると頭が痛くなります。私はそれを明確にし、頭痛を省く方が良いと思います。
Krystian Cybulski、2011年

NPEは送信ボックス付きのb1tchです。ESPケースのfor (int i in Collection<Integer>)b / cのような場合 、NPEはまったく予期しない場所にあります。キャッシュ範囲は小さいため(XXオプションを使用して増やすことができます)、オートボクシングを使用したIntegerは実際には使用しませんが、IntegerProvider(1.1以降)と呼ばれるクラスを使用して、まったく同じことを行います。Map(java.utilの任意のもの)を使用するInteger-> Anythingは、それが些細な場合に使用されない限り、通常はパフォーマンスヒットとなり、ほとんどの場合、より良い解決策があります。
bestss

intをIntegerにキャストしても、おそらくヒープオーバーフローを除いて、エラーが発生することはありません。ただし、その逆は当てはまりません。
2010年

@MattBall、わかりません。合成糖は広く使用されています。eggcorns.lascribe.net / forum / viewtopic.php?id = 4400と合成の方がいいです。
bestss

9

それはそれを解析してInteger <minus operator> 128、変数を見つけませんInteger-128括弧で囲む必要があります:

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

他のすべての回答に+1を付与しましたが、すべて正解です:)
ボヘミアン


6

3行目は、括弧内の式から128を差し引こうとしているように解釈され、括弧内の式はそうではなく、int型の式です(「-」は「-」演算子として扱われます)。式を次のように変更した場合:

Integer i3 = (Integer) (-128);

次に、コンパイラーは、「-」が負の整数を示す単項マイナスであることを理解します。


3

C#コンパイラも同じ動作をします。それはなぜそれがコンパイルに失敗するのかより良いヒントを与えます:

負の値をキャストするには、値を括弧で囲む必要があります

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.