2016-05-30 4 views
0

項目23は、(新しいコードでは、生の型を使用しないでください)効果的なジャワのそれは次のような方法は危険と安全ではないことを主張し、Javaコードで生タイプを使用すると、常に例えば生の型は常に悪いですか?

危険であることを主張し

// Use of raw type for unknown element type - don't do this! 
static int numElementsInCommon(Set s1, Set s2) { 
    int result = 0; 
    for (Object o1 : s1) 
     if (s2.contains(o1)) 
      result++; 
    return result; 
} 

s1とs2で書き込み操作やクラスキャスト操作を行うと、すべての種類の例外が発生することがありますが、上記の方法が安全でない理由を理解できません。著者Joshua Blochは次の方法を代わりに推奨しています。言い換えれば

// Unbounded wildcard type - typesafe and flexible 
static int numElementsInCommon(Set<?> s1, Set<?> s2){ 
    int result = 0; 
    for (Object o1 : s1) 
    if (s2.contains(o1)) 
     result++; 
    return result; 
} 

、この方法が唯一のObject.classをの方法を使用し、渡されたパラメータへの変更をしない場合は、なぜそれが悪いのですか?

+3

昔、ジェネリックスの前に、人々はその日のコレクション(すなわち、その時代のコレクションではなかった 'Hashtable'と' Vector')で**タイプをミックスしました。これは '[0、" abc "、Date]'のようなものにつながりました。これはハックです(Javaでは独自のデータ型を作成できるので)。 'Set 'では、一貫した要素タイプが保証されています。 –

+0

確かに。私の質問は、** Object.Classによって公開されたメソッドのみを含む読み取り専用のメソッドや操作の場合、生の型が安全でないことです** ** –

+0

いいえ、そうではありません。実行時には、すべての型は生のままであり、ワイルドカードで推奨されるメソッドと全く同じことを行います。しかし、この方法では、コンパイラは、あなたが実際にこれらの「安全なもの」以外の何かをしないことをチェックします。ワイルドカードがなければ、誤ってセットに追加した場合など、エラーは発生しません。だから知っていればジェネリック型、そうでなければワイルドカードを使ってください。生の型は使用しないでください。 – Thilo

答えて

2

コンパイラが多くのコードを型チェックするのを妨げるのは悪いことです。

もちろん、あなたはそれなしでも安全で安全なコードを書くことができます。人々は毎日PerlとJavascriptでそれを行います。さらに、Javaの場合でも、実行時に生の型を使用し、型付きコレクションを使用することに違いはありません。しかし、できるだけコンパイラのチェックを受けていると言われることがあります。

したがって、例のような方法では、生の種類ではなくワイルドカードの種類(Set<?>)を使用します。そうすれば、s1.addAll(s2);のような "危険な"コードを書くと、コンパイラはあなたに叫ぶでしょう。

+0

意味があります。私はインターフェイスからのキャプチャの制約が子クラスで強制されていないことに驚いています。たとえば、https://gist.github.com/dsKarthick/e6b1b62c70f3722b13d9047aa338b8c2を参照してください。 –

+0

私は子クラスの生の型についてコンパイラの警告を受けると思います。タイプを使用する場合は、親インターフェイスと一致させる必要があります。 – Thilo

+0

子クラス(または実際にJavaのどこか)で生の型を使用することさえ許可されている理由は、Java5より前の古いコードとの下位互換性です。しかし、型を使用すると、型が適切に強制されます。 – Thilo

関連する問題