2

基本的なことを質問し続けて申し訳ありませんが、この単純なコードと、最初の print ステートメントがコンパイラを通過し、true を出力する理由がわかりませんが、2 番目の print ステートメントはコンパイルされず、「比較できない型」エラーが表示されます。

int in1 = 38;
Number Nn1 = in1;
System.out.println(in1 == Nn1);
System.out.println(Nn1 == in1);

私はこの結果を期待していません.==が対称であることはかなり標準的だと思いましたか?

javac 1.6.0_26 と NetBeans を使用していますが、同じ結果が得られます。最初の println ステートメントは問題なくコンパイルされ、2 番目のステートメントはコンパイルされません。

4

5 に答える 5

3

Java 言語仕様によれば、どちらの方法でもコンパイルするべきではないと私は信じています。

auto(un)boxing は、特定の基準を満たす式にのみ適用され、特定のラッパー クラス(Integer、Long など、Number ではありません) にのみ適用されることを理解することがまず重要です。

現在、== の場合、ルールに従って一方が [プリミティブ] 数値型であり、もう一方が [プリミティブ] 数値型(JLS 15.12.1) に変換可能である場合に、特に autounboxing が適用されます。先ほど述べたように、「規則に従って」、Number は数値プリミティブ型に変換できません

たとえば、int を Integer に変換してから参照比較を行う必要はありません。オートボクシングは == 参照比較に適用されるように指定されていません(JLS 15.21.3)。

したがって、コンパイラが引用されたコードのコンパイルを許可している場合、Java 言語仕様には従いません

数値比較を実行するには、数値昇格を実行するためにコンパイラが両方のオペランドの実際の特定の型を知る必要があるため、この動作は理にかなっています。たとえば、数値と整数を比較でき、コンパイラは数値に対して .intValue() を呼び出すだけでよいと考えるかもしれません。しかし、これは不適切です。元の数値型が実際には Float だった場合、正しい比較は、実際には最初に整数を Float に変換することであり、その逆ではありません。つまり、数値の場合、コンパイラはプリミティブとの数値比較を正しく実行するためのすべての情報を持っていません

于 2012-11-18T01:27:38.947 に答える
2

私のコンパイラ ( jdk1.7.0_03Windows 上) は、両方の行が間違っていると言います:

ここに画像の説明を入力

int演算子 == はandには適用できませんjava.lang.Number

于 2012-11-18T00:34:36.543 に答える
1

と が等しいかどうかを確認するintInteger、ボックス化解除が発生します。実際、コンパイラは、Integerオペランドがラップするだけであることを認識していintます。みたいな手がかりです。

ただし、 (およびその他の)Numberによって実装されていますがInteger、一般的すぎて、ボックス化解除を操作するためにコンパイラが元のプリミティブ型を抽出するためにあまりにも多くの仕事を期待します。

したがって、コンパイラはそれについて不平を言い、よりきめの細かい型を期待します。

于 2012-11-18T00:57:49.443 に答える
0

どちらの行もコンパイルエラーです。そうでない場合は、NetBeansにバグがあります。

に変更NumberするとInteger、両方の行がコンパイルされます。

int in1 = 38;
Integer Nn1 = in1; // Changed to Integer
System.out.println(in1 == Nn1); // compiles
System.out.println(Nn1 == in1); // compiles
于 2012-11-18T00:48:39.993 に答える
0

値の参照型の値をプリミティブ値と比較しているため、それが機能する唯一の方法は、ボックス化されていない自動変換のためです。しかし、そのタイプの変換はJava 言語仕様で指定されていないようです。

可能にすることをまったく意図していないため、おそらく対称ではありません。コンパイラのバグかもしれません。

于 2012-11-18T01:04:50.873 に答える