最近、console.log の柔軟性を Java で再現したかったので、次のように複数の引数を受け入れてカンマ区切りで出力できる汎用の print 関数を作成することにしました。 JavaScript または TypeScript の console.log。結果?答えよりも疑問の方が多く残りました。順を追って説明しましょう。
まず、T 型の可変引数を受け取り、値をカンマで区切って出力する単純な汎用関数を Java で作成しました。
public class Main { public static void main(String[] args) { Main.print(1, "4", new ArrayList<>()); // Expected type issues, but it ran without any problem! } private static <T> void print(T... args) { System.out.println(Arrays.toString(args)); } }
Java の厳密な型指定により、混合型 (Integer、String、ArrayList) を渡したときに警告が表示されるか、エラーがスローされると期待していましたが、そうではありませんでした。コードは問題なくコンパイルおよび実行され、何も問題なく [1, 4, []] を出力しました。
これには私も驚きました。なぜなら、TypeScript も扱う人間として、これは不快に感じたからです。 Java はこの型の不一致を検出すべきではないでしょうか?
当然のことながら、これをどのように処理するかを確認するために TypeScript に目を向けました。 TypeScript で同様の関数を書きました:
function print<T>(...args: T[]) { console.log(args.join(",")); } print(1, "4", []); // TS warns (which makes sense): // Argument of type 'string' is not assignable to parameter of type 'number'.
予想どおり、TypeScript は警告をスローしました。 TypeScript は、最初の引数 (1) から型 T を数値として推論したため、2 番目と 3 番目の引数 (「4」と []) に無効のフラグを立てました。 TypeScript はジェネリック関数に対して一貫した型を強制するため、この動作は完全に理にかなっています。
必ずしもそうとは限りません。ここで何が起こっているのかというと、型の消去により Java の型システムの動作が異なるということです。 Java では、ジェネリック型情報は実行時に消去されます。つまり、異なる型を T... args に渡すとき、Java はすべての引数が同じ型であることを強制しません。単に入力をオブジェクトとして扱います。
一方、TypeScript はコンパイル時と実行時の両方で厳密なチェックを行い、すべての引数が推論または宣言された型と一致することを保証します。
この経験から私は考えさせられました。Java は TypeScript のように、より厳密な型チェックを強制すべきでしょうか?それとも、この柔軟性は Java の設計の意図的な部分なのでしょうか?
どう思いますか? Java と TypeScript を切り替えるときに、同様の不具合に遭遇したことがありますか?コメントでご意見をお待ちしております!
以上がこれは Java のバグですか?の詳細内容です。詳細については、PHP 中国語 Web サイトの他の関連記事を参照してください。