2012-07-19 10 views
7

私はこのようなメソッド呼び出しをしようとしていますにどのように、Javaの

public class GenericsTest<T> { 

    public static <T> Map<String, T> createMap(Class<? extends Map<String, T>> clazz) { 
     return null; 
    } 

    public static void main(String[] argv) { 
     Map<String, Integer> result = createMap(TreeMap.class); 
    } 
} 

しかし、私はこのエラーを取得しています、

<T>createMap(java.lang.Class<? extends java.util.Map<java.lang.String,T>>) in test.GenericsTest<T> cannot be applied to (java.lang.Class<java.util.TreeMap>) 

どのようにこの問題を解決するためにジェネリック型を持つクラスを取得しますか?

+0

タイプの消去が原因ではありません。特に、メソッドのシグネチャは、値パラメータを 'T'として' Map'の 'Class'を取り込んでいても' T'を出そうとしているので意味がありません。オブジェクトの既存のインスタンスがなければ、ネストされた型を取得することはできません。 (あなたは '(新しいHashMap ())。getClass()'を渡すことができますが、そのメソッドから 'Integer'を取り戻すことはできません)。 – pickypg

+0

createMap()は、使用するライブラリのものです。そのメソッドを呼び出す方法が必要です。 –

+0

私は返されたオブジェクトの合法性に疑問を呈します。これは 'Map'の' Class'に渡されるとき、値パラメータのインスタンス 'T'を返すと思われ、メソッド名は' createMap'です。それのどれも意味をなさない。 – pickypg

答えて

3
Map<String, Integer> instance = new TreeMap<String, Integer>(); 

@SuppressWarnings("unchecked") 
Map<String, Integer> map = 
    createMap((Class<? extends Map<String, Integer>>)instance.getClass()); 

map.put("x", 1); 

System.out.println("THIS IS x: " + map.get("x")); 

これは、適切に1からメソッドの実装を出力しますが、それらは、タイプにTをお聞きする彼らのAPIのより高度な実装は次のようになり

try 
{ 
    return clazz.newInstance(); 
} 
catch (Exception e) 
{ 
    throw new RuntimeException(e); 
} 

可能性が最も高い、とのために彼らはあなたにすべての詳細を尋ねるのではなく、Mapを返すようにしました。そうでなければ、限り、彼らは任意のデータでMapに充填されていないとして、あなたはそうのようなジェネリック型引数を自分でMapをインスタンス化することができます

public static <T> Map<String, T> getMap() 
{ 
    return new TreeMap<String, T>(); 
} 

をあなたはその後、警告なしということでアクセスできます。

// note the lack of type arguments, which are inferred 
Map<String, Integer> instance = getMap(); 

// alternatively, you could do it more explicitly: 
// Map<String, Integer> instance = ClassName.<Integer>getMap(); 

実装に正確に一致し、あなたをお返しする場合を除き、それらはあなたのMapClassタイプのためにあなたを依頼するための理由は、あなたがHashMapに固執する場合(例えば、あなたはHashMapを取り戻す、とあればなり本当にありませんあなたはにこだわるを入力すると、TreeMapが返されます)。しかし、TreeMapは、それが構築されたComparatorを失い、それはのフィールドが不変(final)なので修正できないと思われます。つまり、その場合はMapが同じではなく、あなたが望むものではない可能性があります。

データでMapを入力すると、意味がなくなります。 Mapのインスタンスを渡すこともできますし、Mapを返すようにすることもできます(たとえばnew TreeMap<String, Integer>(instance);)。データに最も多くのユーティリティを提供するのはMapです。

+0

これは実行されますが、未チェックの警告が表示されます。警告なしでこのメソッドを呼び出す方法が必要です。ジェネリック医薬品を使用する目的はそれだけです。 –

+0

目的は正しいですが、この問題の原因となっている型消去のためにJavaにはジェネリックが限られています。コンパイラがあなたのためにそれをやり遂げることなく、あなたができることには限界があります。おそらく、Javaの最もよく使われない機能です。なぜなら、Javaの修正や置き換えが最も難しいからです。 .NETは実行時に忘れられないので、汎用性の高い汎用システムを備えています。 コンパイル後、返される型は実際には 'Object'なので、そのマップアクセスは'(Integer)map.get( "x") 'になります。 – pickypg