Java通配符和泛型方法

时间:2013-09-23 08:46:11

标签: 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 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)

我对通配符和泛型方法有点新意,所以我做错了什么?

2 个答案:

答案 0 :(得分:4)

Map<String, ?>并不意味着您可以将任何放入该地图中。这意味着值类是未知。但它可以是例如Foo或Bar。并且Foo可能与任何类型T不兼容,因此编译器会抱怨。请改为使用Map<String, Object>或将T参数设为类级别,然后使用它参数化地图:Map<String, T>

答案 1 :(得分:4)

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

private Map<String, ?> posts;

您将无法将null之外的任何内容放入其中。因为?是任何类型的替代品。基本上,您的MapMap的所有实例化的超类型,其中String作为键,以及任何类型的值。 ?可以是日期数字 Cat Tiger ,等等。

假设您的地图实例化如下:

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

并且方法中的type参数推断为String,然后您的put方法正在执行:

posts.put(String, String);

...因此尝试添加需要String的{​​{1}}类型。当然会在运行时失败。通用类型通过为此发出编译器错误来避免这些问题。


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

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只有几毫秒的精度,因此在一个毫秒内覆盖的间隔期间放置的任何内容都将存储为相同的密钥,从而覆盖该密钥的旧值。