2017-01-07 5 views
2

実行時にクラスの型だけがわかっているオブジェクトを受け入れる必要があるプログラムがあります。プログラムがオブジェクトを正しいクラス型に自動的にキャストバックさせることが可能かどうか疑問に思っていましたか?自動型キャスト

次のコードは現在のものです。私はそれがステップ・バイ・ステップを行うことを期待するかを説明します:

  1. は二組(クラスタイプFooの1、クラスタイプBarの1)を追加しTryingSomethingインスタンスを作成します。
  2. セットはハッシュマップに追加されるはずです。この時点で私は既にEclipseから警告を受けて、セットが何らかの形で互換性がないことを警告します。しかし、タイプは同じです。何がここで間違っていた?
  3. 前の手順が意図したとおりに動作したと仮定して移動を続けます。私は再びメインメソッドのコレクションを取得したいが、正しいクラスタイプ(FooBar)にキャストしたい。これは使えますか?そうでない場合は、オブジェクトを正しいクラス・タイプに戻すことができる代替手段がありますか?
  4. (ボーナス)各コレクションに添付されている名前の文字列を使用して、さまざまなクラスタイプを区別することができます。ストリングを必要とせずに、ステップ3で結果を得ることが可能であればさらに良いでしょう。

私にいくつかの指摘を与えることができる誰にも感謝します。

class TryingSomething<T> { 
    private Map<String, Set<T>> map = new HashMap<String, Set<T>>(); 

    public void addCollection(Set<T> s, String name){ 
     this.map.put(name, s); 
    } 

    public void test(){ 
     Set<Foo> foo = new HashSet<Foo>(); 
     Set<Bar> bar = new HashSet<Bar>(); 
     addCollection(foo, "foo"); 
     addCollection(bar, "bar"); 
    } 

    public Set<T> getCollections(String name){ 
     return this.map.get(name); 
    } 

    @SuppressWarnings("unchecked") 
    public static void main(String[] args){ 
     TryingSomething t = new TryingSomething(); 
     Set<Foo> foo = new HashSet<Foo>(); 
     Set<Bar> bar = new HashSet<Bar>(); 
     t.addCollection(foo, "foo"); 
     t.addCollection(bar, "bar"); 
     Set<Foo> fooList = t.getCollections("foo"); 
     Set<Bar> barList = t.getCollections("bar"); 
    } 

} 

class Foo{ 
} 

class Bar{ 
} 
+0

まず、 'addCollection'はジェネリックメソッドとして宣言され、独自の' T'を定義します。その 'T'はクラス' T'と同じではないので、エラーメッセージです。 ''を最初から削除してください。不要になります。 – eran

+1

私は今すぐ完全な答えを投稿することはできませんが、これについて考えてみましょう。あなたが 'getCollection'呼び出しの文字列をユーザ提供の文字列で置き換えるとします。コンパイラは、その値が何であるかを予測することはできません。どのようにあなたのコードがブレークしていないかコンパイラが知ることができますか(これは**問題そのものではなく、あなたがしようとしていることはそれほど意味をなさないとのヒントです...) – Amit

+0

@eran私はあなたが私に与えた提案を編集しました。エラーは 'test()'メソッドの2つのaddCollection/2呼び出しに移動しました。私はその情報をメインメソッドに移して読みやすくしました(そして 'test()'メソッドを削除しました)。しかし、メインメソッドではエラーが出ません。それは変だ。 – Babyburger

答えて

1

あなたは、マップキーのクラスのクラスオブジェクト(ランタイムタイプ)を使用することができます。

class TryingSomething { 
    private Map<Class<?>, Set<?>> map = new HashMap<>(); 

    public <T> void addCollection(Set<T> s, Class<T> clazz){ 
     map.put(clazz, s); 
    } 

    public void test(){ 
     Set<Foo> foo = new HashSet<Foo>(); 
     Set<Bar> bar = new HashSet<Bar>(); 
     addCollection(foo, Foo.class); 
     addCollection(bar, Bar.class); 
    } 

    @SuppressWarnings("unchecked") 
    public <T> Set<T> getCollections(Class<T> clazz){ 
     return (Set<T>)this.map.get(clazz); 
    } 


    public static void main(String[] args){ 
     TryingSomething t = new TryingSomething(); 
     Set<Foo> foo = new HashSet<Foo>(); 
     Set<Bar> bar = new HashSet<Bar>(); 
     t.addCollection(foo, Foo.class); 
     t.addCollection(bar, Bar.class); 
     Set<Foo> fooList = t.getCollections(Foo.class); 
     Set<Bar> barList = t.getCollections(Bar.class); 
    } 

} 

class Foo{ 
} 

class Bar{ 
} 

あなたは、任意の種類のセットを保存するため、クラスTryingSomethingは、一般的なことではないはずです(実行時に動的に選択されます)。この実装では、挿入されたセットに、指定された型のオブジェクトが実際に挿入されているか検索されていないかはチェックされません。ここでは、このコンテナクラスのユーザーに適用されます。

+0

これは正常に動作するようです。ありがとうございました! – Babyburger