Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/java/373.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Java通配符和泛型方法_Java_Generics_Wildcard - Fatal编程技术网

Java通配符和泛型方法

Java通配符和泛型方法,java,generics,wildcard,Java,Generics,Wildcard,我有一个使用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

我有一个使用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)
我对通配符和泛型方法有点陌生,那么我做错了什么呢?

映射并不意味着你可以在该映射中放入任何内容。这意味着值类未知。但也可以是Foo或Bar。而Foo可能与任何类型T都不兼容,因此编译器会抱怨。改用Map,或者使您的T参数类处于级别,然后使用它参数化您的Map:Map

当您使用无界通配符类型声明您的Map时:

private Map<String, ?> posts;
方法中的类型参数被推断为字符串,那么put方法将执行以下操作:

posts.put(String, String);
…因此,尝试在需要日期的位置添加字符串类型。当然,这会在运行时失败。泛型类型通过为此发出编译器错误来避免这些问题

您可以通过使类本身成为泛型来解决此问题,从而在方法和映射中使用相同的类型参数:

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);
        }
    }
}

正如评论中提到的,你应该避免把时间当作关键。由于DategetTime的精度只有毫秒,因此在一个毫秒的时间间隔内放置的任何内容都将存储为同一个键,从而覆盖该键的旧值。

posts应该是私有映射posts;正如你所知,它包含T个元素。只是出于考虑,永远不要把时间当作一把钥匙。时间的分辨率有限,因此不是关键。每次在同一毫秒内将某个内容放入映射时,旧值将被覆盖。改用计数器。
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);
        }
    }
}