2012-03-05 17 views
4

私は変換をハンドラに委譲するメソッドtoString(Object)を持っています。コードは次のようになりますマップで「これらの2つのジェネリックタイプは同じです」とはどうすればわかりますか?

public interface IToStringService<T> { 
    public String toString(T value); 
} 

@SuppressWarnings("rawtypes") // Can't add generics to "Class" or I get compile errors when calling DefaultToStringService.addSpecialHandler() :-(
public class ClassToStringService implements IToStringService<Class> { 

    @Override 
    public String toString(Class value) { 
     return value == null ? "null" : value.getName(); 
    } 
} 

私はここにいくつかの問題があります。

// (1) How can I say that these two wildcards must in fact be the same type? 
private Map<Class<?>, IToStringService<?>> specialHandlers = Maps.newHashMap(); 

// Generic method, must accept Object (any type really) 
@Override 
public String toString(Object value) { 

    if(null == value) { 
     return "null"; 
    } 

    Class<?> type = value.getClass(); 
    if(type.isArray()) { 
     return arrayToString(value); 
    } 

    // (2) How can I get rid of this SuppressWarnings? 
    @SuppressWarnings("unchecked") 
    IToStringService<Object> handler = (IToStringService<Object>) specialHandlers.get(type); 

    if(null != handler) { 
     return handler.toString(value); 
    } 

    return value.toString(); 
} 

public <T> void addSpecialHandler(Class<T> type, IToStringService<T> handler) { 
    specialHandlers.put(type, handler); 
} 

そして、もう一つの実装は、このようになりますハンドラは次のように定義されています

  1. どうすればよいですかspecialHandlersマップのハンドラは、キーとして使用されているタイプと一致する必要がありますか?

  2. キャストを避けるために、メソッド内で同じ情報を使用するにはどうすればよいですか?@SuppressWarnings

  3. ClassToStringServiceIToStringService<Class<?>>を実装すると、addSpecialHandler(Class.class, new ClassToStringService());を呼び出すときにコンパイルエラーが発生するこれを解決するにはどうすればよいですか?

+1

キーのジェネリックスが値のジェネリックスと同じであることを強制したいとします。まあ、あなたはマップでそれをすることはできません。しかし、あなたがマップに置かれているものを制御しているので、本当にその制限はありますか? – Luciano

+0

@ルキアーノ:そうだと思ったが時には、誰かがトリックを知っている。最後のポイントはどうですか? –

+1

[一般的なキーの一般的なマップ/関連するタイプの値]の複製が可能です(http://stackoverflow.com/questions/2208317/generic-map-of-generic-key-values-with-related-types) –

答えて

1

これはJavaでは実行できません。理由を説明します。 ?型理論ではextendsを実在型と呼んでいますが、Javaには限られた形しかありません。 ? Xは、Yは、YがXを拡張することを我々はMap<Class<?>, IToStringService<?>>書き換えることができますが存在することを意味拡張:

Map<Class<(exists T1 extends Object)>, IToStringService<(exist T2 extends Object)>> 

をしかし、我々が望む:

Map<(exists T extends Object Class<T>, IToStringService<T>> 

我々はJavaでこれを表現することはできませんので、存在記号に」 Javaでは明示的に指定する必要があります。しかし、Scalaではこれを行うことができます。

関連する問題