方法参数的泛型类型

Jud*_*ing 2 java generics generic-list

这是场景:

public static <T> List<T> isTriggeredByBlackList(Map<String, T> params, Class<T> clz)   {
    System.out.println(clz.getName());

    return null;
}
Run Code Online (Sandbox Code Playgroud)

我要的是通过其中StringList<String>以这种方法.

说到它String,它的工作正常:

Map<String, String> map1 = new HashMap<String, String>();
map1.put("11", "22");
isTriggeredByBlackList(map1, String.class);
Run Code Online (Sandbox Code Playgroud)

但是当我试图通过时List<String>,它出错了:

Map<String, List<String>> map = new HashMap<String, List<String>>();
List<String> l = new ArrayList<String>();
l.add("11");
l.add("22");
map.put("1", l);
isTriggeredByBlackList(map, List.class);    //compile error!
Run Code Online (Sandbox Code Playgroud)

编译错误如下:

The method isTriggeredByBlackList(Map<String,T>, Class<T>) in the type CommonTest is not applicable for the arguments (Map<String,List<String>>, Class<List>)
Run Code Online (Sandbox Code Playgroud)

我需要的是只编写一个适用于String类型和List<String>类型的方法.

任何人都可以帮我吗?非常感谢!

isn*_*bad 9

更改方法的签名:

public static <T> List<T> isTriggeredByBlackList(Map<String, ? extends T> params, Class<T> clz)
Run Code Online (Sandbox Code Playgroud)

为什么这样做?

表达式? extends T只意味着接受任何类型T(当然也是T其自身)的类型.

什么是通配符?

所以当方法isTriggeredByBlackList被调用时:

isTriggeredByBlackList(map, List.class);
Run Code Online (Sandbox Code Playgroud)

... T被指定为(原始)List类型,因此第一个参数必须是a Map<String, any-type-that-extends-raw-List>,对于Map<String, List<String>>(因为List<String>是(raw)的子类型)是真的List.


但是为什么List是(原始)List的子类型?

泛型是棘手的,因为多态性不能按预期工作(第一眼看见).A List<String> 是-NOT-a List<Object>,虽然String延伸Object!所以这不起作用:

List<Object> objList = new ArrayList<String>(); // compile error
Run Code Online (Sandbox Code Playgroud)

(注意:这是不可能的,但这是另一个故事)

但是List<String> IS-a(原始)List(它是-a List<?>).这样可行:

List rawList = new ArrayList<String>(); // just compiler warning
List<?> unknownList = new ArrayList<String>();
Run Code Online (Sandbox Code Playgroud)

原因是:仍然支持原始类型向后兼容!否则,现在无法使用不支持泛型的旧代码.因此,具体参数化类型(例如ArrayList<String>)的任何实例都可以分配给其原始类型(例如ArrayList)或超类型(例如List)的引用!

为什么允许原始类型?

为什么我们不能通过类似的东西List<String>.class

因为参数化类型没有确切的运行时类型表示!

为什么没有具体参数化类型的类文字?

但我希望获得一个List<List<String>>返回值!

这没问题!只需将赋值的左侧定义为a List<List<String>>,然后java执行其余操作:

List<List<String>> l = isTriggeredByBlackList(map, List.class);
Run Code Online (Sandbox Code Playgroud)

但!这仅适用于您稍微修改方法声明:

public static <T> List<T> isTriggeredByBlackList(
    Map<String, ? extends T> params, Class<? super T> clz)
Run Code Online (Sandbox Code Playgroud)

(否则你不能将raw List.class作为第二个参数传递).


如果所有这些修改和调整都有意义,取决于您的方法应该完成的任务!它只是从中读取params吗?它如何使用泛型类型参数?在这里使用泛型有什么好处?等等


顺便说一句:开头的方法is...应该返回一个boolean值.考虑重命名您的方法!顺便说一句2:你的方法的返回类型是List<T>,所以万一你指定T是a List,你会得到一个List<List>.这是有意的吗?