2008-09-09 3 views
24

にオブジェクトoのクラスを比較するのは、私は次のクラスがあるとしましょう:Javaのジェネリック:<E>

public class Test<E> { 
    public boolean sameClassAs(Object o) { 
     // TODO help! 
    } 
} 

にはどうすればoEと同じクラスであることを確認しますでしょうか?

Test<String> test = new Test<String>(); 
test.sameClassAs("a string"); // returns true; 
test.sameClassAs(4); // returns false; 

私はスーパークラスをオーバーライドすることだし、ので、私のメソッドのシグネチャを選択するために取得しないように私は(Object o)からメソッドのシグネチャを変更することはできません。

また、私はむしろ、キャストをしようとし、それが失敗した場合に結果の例外をキャッチする道を行かないだろう。

答えて

26

TestのインスタンスはEは、実行時に何であるかについての情報がありません。したがって、Class<E>をTestのコンストラクタに渡す必要があります。

public class Test<E> { 
    private final Class<E> clazz; 
    public Test(Class<E> clazz) { 
     if (clazz == null) { 
      throw new NullPointerException(); 
     } 
     this.clazz = clazz; 
    } 
    // To make things easier on clients: 
    public static <T> Test<T> create(Class<T> clazz) { 
     return new Test<T>(clazz); 
    } 
    public boolean sameClassAs(Object o) { 
     return o != null && o.getClass() == clazz; 
    } 
} 

あなたは "instanceofの" 関係をしたい場合は、Class比較するのではなく、Class.isAssignableFromを使用しています。 EClassオブジェクトが必要Test同じ理由で、非ジェネリック型である必要があります、注意してください。 Java APIの例については

は、java.util.Collections.checkedSetと同様のを参照してください。

+1

。または、==を使用する特別な理由はありますか? – ordnungswidrig

+1

これは同等です。 IMO ==は読むのが簡単です(ただし、読者は型について知っていなければなりません)。それはインライン化の前に部分的に高速です。さて、私がテストしたとは思わないものは、ヌル・クラジです。 –

2

私はそれがこのように取り組んで作ることができます:

public class Test<E> { 

    private E e; 

    public void setE(E e) { 
     this.e = e; 
    } 

    public boolean sameClassAs(Object o) { 

     return (o.getClass().equals(e.getClass())); 
    } 

    public boolean sameClassAs2(Object o) { 
     return e.getClass().isInstance(o); 
    } 
} 
9

私はいつも使用してきた方法は以下の通りです。それは痛みと少し醜いですが、私はより良いものを発見していません。ジェネリックスがコンパイルされたときにクラス情報が失われたときのように、クラス型を構築時に渡す必要があります。

public class Test<E> { 
    private Class<E> clazz; 
    public Test(Class<E> clazz) { 
     this.clazz = clazz; 
    } 
    public boolean sameClassAs(Object o) { 
     return this.clazz.isInstance(o); 
    } 
} 
-1

私はちょうど同じことをしようとしていた、と私はちょうど実現1つのきちんとしたトリックは、あなたがキャストを試すことができ、およびキャストが失敗した場合は、ClassCastExceptionがスローされるということです。あなたはそれを捕まえることができ、何でもすることができます。

ので、あなたのsameClassAs方法は、次のようになります。私はむしろ対等でクラスを比較したい

public boolean sameClassAs(Object o) { 
    boolean same = false; 
    try { 
     E t = (E)o; 
     same = true; 
    } catch (ClassCastException e) { 
     // same is false, nothing else to do 
    } finally { 
     return same; 
    } 
} 
+3

いいえ、それはできません。それはチェックされていないキャストです。それは決して例外をスローしません。実行時には、 "t"はEの消去の型を持ちます。これはObjectだけなので、キャストは実行されません。 – newacct

+0

あなたは正しいです。コンパイルがうまくいくので、後でトラブルシューティングをしなくて済むでしょう。 – Ayman