3

私の知る限り、ジェネリックはコンパイル時にのみ役立ちます。

したがって、次のように宣言できます。

private Set set = new HashSet<String>();

そして、この文字列ハッシュセットで、犬などをそのセットに追加します。実行時に配列のようなチェックがないため (ArrayStoreException...) (ただし、それを使用するとクラスキャストのような問題が発生する可能性があります)設定...

だから私が言いたいのは、私たちは通常、ジェネリックコレクションをそのようにインスタンス化するということです:

Set<String> set = new HashSet<String>();

私の質問は、変数の参照の型だけが本当に重要なので、なぜ HashSet の型を置くのかということです (私は思います)。

つまり、単純に次のように書くことができます。

Set<String> set = new HashSet();

そして、それはまったく同じように機能しますか?では、インスタンス化の際に型を記述するのはなぜでしょうか? (必須ではありません)


編集

型推論のための「ダイヤモンド演算子」については知っていますが、なぜそれが必要なのですか!!! 型推論はすでに機能しているためです。

次のコード:

            Set<String> set = new HashSet();
            set.add("Test add a string 1");
            set.add("Test add a string 2");
            for ( String s : set ) {
                    System.out.println(s);
            }

出力を生成します。

文字列を追加するテスト 1 文字列を追加するテスト 2

自分でテストしてください http://ideone.com/vuiCE

では、Java7 の機能としての型推論について話されていますが、それはすでに私にとっては機能しています...

Java7では、私を交換する必要があります

            Set<String> set = new HashSet();

            Set<String> set = new HashSet<>();

まったく同じことをするのに、まだ 2 文字追加ですよね?(ジェネリックがJava7でコンパイル時だけでない限り?わかりません)

4

5 に答える 5

4

そして、それはまったく同じように機能しますか?

実行時:はい

コンパイル時:いいえ

コードは、任意のオブジェクトを含むセットを、文字列を含むセットを格納する変数に割り当てますが、これは悪いことであり、タイプチェッカーによって眉をひそめられます。

あなたが書いているときは、 raw typenew HashSet()を使用しています。その意味と、なぜ避けるべきかについて、この質問を参照します。


一般に、次のように主張できます。

Set<String> set = new HashSet();

から遠くない

HashSet tmp = new HashSet();
...
Set<String> set = tmp;

それは遠くない

HashSet tmp = new HashSet();
tmp.add(7);
...
Set<String> set = tmp;

これはまだコンパイルされますが、何千もの理由で悪いです:)


Java 7では、次のように書くことができます

Set<String> set = new HashSet<>();

ただし、これはコンパイラに...間の型を推測するように指示します。<>

「ダイヤモンド演算子」に関するドキュメント:

于 2011-11-04T14:06:42.597 に答える
3

最後の提案は型推論であり、いわゆるダイヤモンド演算子を介して Java 7 で導入されました。

Set<String> set = new HashSet<>();

そうです、それは最初からそこにあった可能性があります。しかし、これは Java であり、通常、新しい言語機能が承認されるまでに数十年かかります (<-- 少し誇張されています)。

于 2011-11-04T14:05:59.460 に答える
1

Java は現在ジェネリック型情報を消去していますが、完全なジェネリック型情報 (具体化と呼ばれます) を将来追加できるように、言語とライブラリの設計に細心の注意を払っています。正しく記述された一般的なコード (つまり、javac 警告なし) は、そのような言語の変更に耐えますあなたの例では、ダイヤモンドバージョンは将来の証拠です。生のバージョンはそうではありません-もちろんコンパイルする必要がありますが、実行時に型キャスト例外をスローします。

しかし、この将来互換性は完全に妄想です。消去は永遠に残ります。完全な具体化が導入された場合、誰もが間違ったジェネリック コードを書いているため、自明でないジェネリック コードのほとんどすべてが機能しなくなると言っても過言ではありません。

それは私たちのせいではありません。Javaは私たちに強制します。それは私たちにでたらめな消去を提供し、それをハッキングして何かを実装するしかありません。私たちのコードは、消去の詳細な知識への依存でいっぱいです。

JDKは最も罪深いものです。JDK API は、具体化されても生き残るように慎重に設計されています。ただし、実装は消去に依存します。Java が具体化を追加する場合、これらの JDK コードを書き直す必要があります。Java チームは、自分たちで同じことをしなければならないのに、間違ったコードを書いたことで私たちを責めるなら、非常に偽善的です。

書き直さないと具体化に耐えられないコードの量を考えると、Java が下位互換性へのコミットメントを維持している限り、具体化を追加することは決してないと言っても過言ではありません。

その場合、ええ、何でも。について本当にひどいことは何もありませんSet<String> set = new HashSet()<>個人的には、警告を避けるために常に追加します。(実際には、可能な限りコードを具象化できないようにしようとしますが、これは前述したように妄想行為です)

あなたの例では、推論は簡単です。<>推論がそれほど自明ではない、より複雑なケースが存在する可能性があり、その型チェックが役立つ可能性がありますが、生のバージョンには欠けています。

class Foo<T>
{
    Foo(Class<T> clazz){}
}

Foo<String> foo1 = new Foo(Integer.class);    // compiles (wrongly) 

Foo<String> foo2 = new Foo<>(Integer.class);  // does not compile
于 2011-11-05T03:12:09.813 に答える
0

Java 7 は、クラス インスタンス作成式の制限付き型推論の追加に対応しています。コンストラクターに対してパラメーター化された型を明示的に宣言する必要があり、そのコンストラクターの完全なパラメーター化された型 < T1 , T2 , ...Tn > がコンテキストから明らかな場合、コンストラクターのパラメーター化された型を型パラメーターの空のセット: <>。<> コンストラクトは、オブジェクトを構築して変数に代入するとき、またはパラメーターとして渡すときに使用できます。

詳細はこちら

于 2011-11-04T14:11:52.313 に答える
0

実際には必須ではありません。入力すると

Set<String> s = new HashSet();

コードがコンパイルされ、Xlint で確認できる警告が表示されます。

Note: filetest.java uses unchecked or unsafe operations.
Note: Recompile with -Xlint:unchecked for details.

次に、たとえば整数値を追加しようとすると、コンパイル エラーが発生します。

于 2011-11-04T14:13:45.557 に答える