Java オートボックス化がオートボックス化された型のメソッド呼び出しまで拡張されないのはなぜですか?

StackOverflow https://stackoverflow.com/questions/4242

  •  08-06-2019
  •  | 
  •  

質問

プリミティブを文字列に変換したいので、次のことを試しました。

myInt.toString();

これは次のエラーで失敗します。

int cannot be dereferenced

ここで、プリミティブは参照型ではない (つまり、オブジェクトではない) ため、メソッドを持つことができないことが分かりました。ただし、Java 5 では、オートボックス化とアンボックス化 (C# のように) が導入されました。私は C# ではこれが好きではありませんでしたが、それは重要ではありません)。したがって、オートボックス化を使用すると、上記で myInt を Integer に変換し、それに対して toString() を呼び出すことが期待されます。

さらに、私の記憶が間違っていない限り、C# ではそのような呼び出しが許可されていると思います。これは Java の自動ボックス化/アンボックス化仕様の単なる残念な欠点でしょうか、それともこれには十分な理由があるのでしょうか?

役に立ちましたか?

解決

Java のオートボックス化/アンボックス化は、プリミティブの逆参照を許可する程度には機能しないため、コンパイラーはそれを阻止します。コンパイラはまだ知っています myInt プリミティブとして。この問題に関する論文は次の場所にあります。 jcp.org.

オートボクシングは主に代入またはパラメータの受け渡しの際に役立ちます。これにより、プリミティブをオブジェクトとして渡したり (またはその逆)、プリミティブをオブジェクトに割り当てたり (またはその逆) できます。

したがって、残念ながら、次のようにする必要があります。(パトリック、私はあなたのやり方に切り替えました)

Integer.toString(myInt);

他のヒント

Justin の言ったことと同じですが、代わりに次のようにする必要があります。

Integer.toString(myInt);

1 つか 2 つの割り当てが節約され、読みやすくなります。

これを行うもう 1 つの方法は、次のものを使用することです。

String.valueOf(myInt);

このメソッドはすべてのプリミティブ型に対してオーバーロードされ、 Object. 。この方法では、使用しているタイプについて考える必要さえありません。メソッドの実装は、指定されたタイプの適切なメソッドを呼び出します。 Integer.toString(myInt).

見る http://java.sun.com/javase/6/docs/api/java/lang/String.html.

私にとっての仕様の欠点のようです

他にも欠点はありますが、これは微妙なトピックです。チェック これ 外:

public class methodOverloading{
   public static void hello(Integer x){
      System.out.println("Integer");
   }

   public static void hello(long x){
      System.out.println("long");
   }

   public static void main(String[] args){
      int i = 5;
      hello(i);
   }
}

ここでは、コンパイラがオートボックス化ではなく拡張を選択しているため、「long」が出力されます (私自身は確認していません)。オートボクシングを使用する場合は注意するか、まったく使用しないでください。

あなたの例に最も近い有効な構文は次のとおりです

((Integer) myInt).toString();

コンパイラが終了すると、次と同等になります。

Integer.valueOf(myInt).toString();

ただし、従来の使用法ほどのパフォーマンスは得られません。 String.valueOf(myInt), 特別な場合を除いて、新しい Integer インスタンスを作成してすぐに破棄するため、不要なゴミがさらに多くなるからです。(狭い範囲の整数がキャッシュされ、配列アクセスによってアクセスされます。)おそらく、言語設計者は、パフォーマンス上の理由から、この使用を阻止したかったのでしょう。

編集:反対投票者が、これが役に立たない理由についてコメントしていただければ幸いです。

C# では、整数は参照型ではなく、整数をボックス化する必要もありません。 ToString() 呼ばれることに。彼らは ただし、フレームワーク内のオブジェクトは (ValueType として扱われるため、値のセマンティクスを持ちます) とみなされます。CLR では、プリミティブのメソッドはスタック (ldind) に「間接的に」ロードすることによって呼び出されます。

誰もが指摘したように、オートボクシングを使用すると一部のコードを簡素化できますが、プリミティブを複雑な型であるかのように振る舞うことはできません。

こちらも興味深い: 「オートボクシングはコンパイラレベルのハックです」 ジャワでは。オートボクシングは基本的に Java に追加された奇妙な作業です。チェックアウト この郵便受け それがどれほど奇妙であるかについて詳しくは、こちらをご覧ください。

Java がプリミティブ型を操作する特定の静的メソッドを定義し、コンパイラーに糖衣構文を組み込んで、

5.asInteger

と同等になります

some.magic.stuff.Integer.asInteger(5);

このような機能は、現在のルールでコンパイルされるコードとの非互換性を引き起こすとは考えず、多くの場合、構文の混乱を軽減するのに役立ちます。Java が逆参照されたプリミティブをオートボックス化する場合、人々は、Java が逆参照構文を静的メソッド呼び出しにマッピングしていると考えるかもしれません (事実上、.NET ではこれが行われます)。そのため、その形式で記述された操作は通常よりもコストがかからないと考えられるでしょう。同等の静的メソッドの呼び出し。人々に悪いコードを書くことを奨励する新しい言語機能を追加する (例:逆参照されたプリミティブを自動ボクシングするのは良いアイデアとは思えませんが、逆参照スタイルのメソッドを許可するのは良いかもしれません。

ライセンス: CC-BY-SA帰属
所属していません StackOverflow
scroll top