4

は、だから私はこのようになります機能を持っている:私は、これはjavax.persistence.Queryを取り、その結果は、一般的なSet<Class>として設定されて戻ってやっていると信じて何をJavaの「チェックされていない変換」から潜在的な実行時例外を処理する最善の方法は何ですか?

@SuppressWarnings("unchecked") 
public static <E> Set<E> getSetOfClass(Query q,Class<E> clazz) { 
    return new LinkedHashSet<E>(q.getResultList()); 
} 

これはすばらしい解決策のように思えますが、最初はそれが実際に私が思っていることを実行しているのですか?これを達成するにはこれが最善の方法ですか?私は私のclazz paramを決して参照していないのは奇妙だと思っていますが、それは私が望むことをするようです。

第2に、これがすべて正確で分かりやすい場合、どのようなエラーが発生する可能性がありますか?私はそれが正しくないクラスを与えると、この関数はうまくいきませんが、それについてはわかりません。

私のような何かを行う場合は、次の

Query q = em.createQuery("FROM Element"); 
Set<Fish> s = MyUtil.getSetOfClass(q, Fish.class); 

そしてFishElementのスーパークラスでない場合は、次に何が起こりますか?この関数は常に正しく使用されると思いますか、そうでなければエラー処理を行うべきですか?ベストプラクティスアプローチの人々の推奨事項は何ですか?

よろしく、

グレンはgetSetOfClassは、セット内のすべての要素がタイプEのオブジェクトであることを保証するものではありません

+1

未使用の 'clazz'については、実際にはclass paramを使用しません。これは、渡す必要がないからです。あなたはそのパラメータを省略してメソッドを: 'MyUtilとして呼び出すことができます。 getSetOfClass(q) 'ですが、それほど慣れていない場合はより慎重な構文です。 @Andreas_Dで推奨されているように 'clazz'パラメータを使うことをお勧めします。 – Blaisorblade

答えて

3

をxは。

は私が公共 getSetOfClassにいくつかのチェックを追加したい

Set<Cat> cats = getSetOfClass(findAllFish(), Cat.class); 
後で上のさまざまな場所でクラスキャスト例外を受け取ります

...:あなたは同じように、(あなたがいつも缶)が誤ってそれを呼び出す場合セットの内容は、typeパラメータと一致していることを保証する方法:

@SuppressWarnings("unchecked") 
public static <E> Set<E> getSetOfClass(Query q,Class<E> clazz) { 
    return getSetOfClass(Query q,Class<E> clazz, true); 
} 

@SuppressWarnings("unchecked") 
public static <E> Set<E> getSetOfClass(Query q,Class<E> clazz, boolean validate) { 
    List result = q.getResultList(); 
    if (validate) { 
     for (Object o:result) { 
      if(!o.getClass().equals(clazz)) { 
       // handle error 
      } 
     } 
    } 
    return new LinkedHashSet<E>(result); 
} 
+1

おそらく、 'Class.isAssignableFrom(Class)'は 'Object.equals(Object)'よりも適切でしょう。 –

+0

はい、そうです。要件に応じて、 "パターン"は両方のテストで動作します。 (私は通常、テストするためのIDEを持っていないときに 'isAssignable'を推奨しません - 間違った方向にそれを使う機会は50%です;)) –

+0

私はまったく同じ問題に遭遇します:) –

2

だけで、すべてのJavaのジェネリック情報はコンパイル時にのみ型正しさのためにあなたのコードをチェックするために使用されていることを覚えて、Andreas_Dの答え@に追加するには、と実行時に消去されます。

public static Set<Object> getSetOfClass(Query q,Class<Object> clazz) { 
    return new LinkedHashSet<Object>(q.getResultList()); 
} 

ちょうど限り、上記の方法が行くように、動作するランタイムすべての意味:したがって、あなたが得る効果的にどのようなこのようなものです。
更新: @Blaisorbladeによって親切に指摘されているように、getSetOfClassメソッドは、タイプが間違っているかどうかをチェックするためにclazzを使用してタイプの正しさとフェイル・ファーストをチェックできます。コンパイル時には実行できませんが、実行時に障害が発生した場合に問題を特定するのが簡単になります。

は、今後のあなたが持っていると仮定:

Query q = em.createQuery("FROM Element"); 
Set<Fish> s = MyUtil.getSetOfClass(q, Fish.class); 
for(Fish fish : s){ 
    fish.swim(); 
} 

その後、実行時に、それは次のようになります。今では要素がタイプCatである場合に何が起こるかを見ることができます

Query q = em.createQuery("FROM Element"); 
Set<Object> s = MyUtil.getSetOfClass(q, Fish.class); 
for(Object fish : s){ 
    ((Fish)fish).swim(); 
} 

(Fish)fishの部分はClassCastException(それがそれを超える場合)をスローします。

したがって、コンパイルによって型情報が追跡されて、末尾の先頭から警告が表示されない場合は、ジェネリックスが本当に役に立ちます。ジェネリックが真ん中で「ハッキングされている」(あなたのような)他のケースでは、プログラムの正しさを保証することはできません。特に、永続化されたデータが正しいタイプであることを確認する方法がないため、データがディスクまたはデータベースに永続化される場合は避けられません。プログラマーはちょっと注意する必要があります。

+0

あなたの投稿は興味深いです。この場合は、(奇妙なことに) 'Class'インスタンスが渡されたので、実行時にすべてが動作することを確認できます。もちろん、あなたが言うように、それはコンパイラによってチェックすることはできません:チェックされていないコードを正しく取得する必要があります。あなたが結論にこれを組み込むなら、私はそれをアップヴォートするでしょう。 – Blaisorblade

+0

完了しました。ありがとうございました。 – rodion

1

私はジェネリック医薬品が好きかどうかはわかりません。この場合、彼らは良いアイデアになると思われ、あなたに多くの問題を救いました。永続性が(まだ)それらをサポートしているように見えるので、私は私のアンチジェネリックスの帽子を置いて、説明する方法を説明します実質 Javaプログラミングが行われます。 「可能な場合は、必要に応じて

public static Set getSetOfClass(Query q) { 
    return new LinkedHashSet(q.getResultList()); 
} 

(使用@SuppressWarnings(「チェックなし」):

私の提案、そして、ジェネリックやクラスをあきらめ、ちょうど昔ながらのセットを返すようになりますtは1.4コンパイラを取得します。)

クエリにEだけが含まれている場合は、問題はありません。または、いずれにせよ、問題は実行時にはまれで、まれであり、あなたの方法を悪用しているプログラマーが最も対処しています。実行時に予期しないClassCastExceptionのような「基本的なアプローチを変更する」とは何も言いません。

場合によっては、正当でないE Fishオブジェクトがある場合、そのメソッドを使用しているプログラマは、自分のものよりも扱いやすくなります。彼らは実行時にチェックすることができます。オプションで個々の魚を投げ捨てたり、セット全体を投げたりすることができます。

の目的を知っていれば、Clazzパラメータを追加することで問題を回避できます。その後、フィルタリングを実行するか、nullを返すか、独自のチェック例外をスローするか、Setコンテンツの性質を詳細に説明する特別なクラスオブジェクトを返します。ただし、メソッドのユーザーを保存するよりも多くの作業を行わないようにしてください。

+0

私はサービスを提供しています。これらのクエリはDAOにあり、このサービスはさまざまな 'Set getSet()'メソッドを提供していますので、いつかこれらの変換を行う必要があります。私はそれを単一のユーティリティクラスに分離することを選択しました。私は1つの場所で警告を抑止し、全員にジェネリックを喜ばせることができます。私はそれを行うには非常にクリーンな方法だと思う。 – Link19

関連する問題