0

Map をフィールド変数として使用するクラスがあります。

private Map<String, ?> posts;

そして、同じクラスにジェネリック メソッドがあります。

public <T> void log(T message) {
   if (isEnabled) {
        Date time = Calendar.getInstance().getTime();
        SimpleDateFormat sdf = new SimpleDateFormat("YYYY-MM-dd HH:mm:ss:SS");
        posts.put(sdf.format(time.getTime()), message);
    }
}

ただし、posts.put ステートメントで次のようなコンパイラ エラーが発生します。

The method put(String, capture#2-of ?) in the type Map<String,capture#2-of ?> is not 
applicable for the arguments (String, T)

私はワイルドカードとジェネリックメソッドに少し慣れていないので、何が間違っていますか?

4

2 に答える 2

4

Map無制限のワイルドカード タイプで宣言すると、次のようになります。

private Map<String, ?> posts;

あなたはそれ以外に何も入れることができませんnull?どんなタイプでも代用できるからです。基本的に、 yourはキーとしてMapのすべてのインスタンス化のスーパータイプでありMap、任意の型の値です。DateNumberCatTiger 、何でもかまいません。String?

マップが次のようにインスタンス化されているとします。

private Map<String, ?> posts = new HashMap<String, Date>();

メソッドの型パラメータが と推測されるString場合、putメソッドは次のように動作します。

posts.put(String, String);

...したがってString、 a が必要な場所にタイプを追加しようとしてDateいます。確かに、それは実行時に失敗します。ジェネリック型は、これに対してコンパイラ エラーを発行することで、これらの問題を回避します。


この問題は、クラス自体をジェネリックにすることで解決できます。したがって、メソッドとマップで同じ型パラメーターを使用します。

class YourClass<T> {
    private Map<String, T> posts;

    public void log(T message) {
        if (isEnabled) {
            Date time = Calendar.getInstance().getTime();
            SimpleDateFormat sdf = new SimpleDateFormat("YYYY-MM-dd HH:mm:ss:SS");
            posts.put(sdf.format(time.getTime()), message);
        }
    }
}

また、コメントに記載されているように、timeキーとして持つことは避けてください。Date#getTime()ミリ秒単位の精度しかないため、間隔中に 1 ミリ秒でカバーされるものはすべて同じキーとして保存されるため、そのキーの古い値が上書きされます。

于 2013-09-23T08:49:19.197 に答える
4

Map<String, ?>そのマップに何かを入れることができるという意味ではありません。値のクラスが不明であることを意味します。ただし、Foo や Bar などの場合もあります。また、 Foo はどの type とも互換性がない可能性があるTため、コンパイラは文句を言います。代わりに使用Map<String, Object>するか、Tパラメーターをクラスレベルにしてから、それを使用してマップをパラメーター化します。Map<String, T>

于 2013-09-23T08:48:20.103 に答える