Java 泛型 -- 依据声明的变量类型自动推断

Java 泛型在调用方法操作时应用具体参数还是很好理解的,比如
Map<String, Integer> map = new HashMap<>();  //钻石操作符是 JDK 1.7 引入的

后续的 put 操作调用的具体方法就是

Integer put(String key, Integer value)

因为  put 方法的原型是

V put(K key, V value)

上面的代码我们是看到了 <>,所以知道是泛型调用。有时候并不需要 <>,但实际上也是进行的泛型调用,那就是 Java  可以依据变量声明类型来作特化调用 -- 应用具体参数类型。

例如:

List<String> list = Collections.emptyList();  //虽不见 <>, 但同样是泛型调用,类型为 String

它调用的方法的实现代码是

public static final <T> List<T> emptyList() {
        return (List<T>) EMPTY_LIST;
}

Collections.emptyList() 调用时根据声明的 List<String> 自动具体化类型为 String 来调用。

下面以一张图来呈现不用调用方式时推断出的类型

依各行代码行简要说明

行 5:    泛型方法中,什么也不知道,只是 T
行 9:    因为方法  foo() 声明的类型是 String, 所以 return abc() 时应用的具体类型就是 String
行 13:  声明的类型  ss 是 Integer, 因而应用 Integer  具体类型
行 16:  没有类型信息所以当作 Object 来处理
行 19:  String 类型是为 abc() 结果值的方法调用的返回值定义的,所以只认为 abc() 得到的是一个 Object




如果不能用声明的类型来指示,还可以通过方法参数来传达类型信息,如

 1public class Test {
 2
 3  static <T> T abc(Class<T> type) {
 4    return (T) "abc";
 5  }
 6  
 7  static <T> T abc(T t) {
 8    return (T) "abc";
 9  }
10
11  public static void main(String[] args) {
12    abc(String.class).toCharArray();
13    abc("123").toLowerCase();
14  }
15}

abc(...) 返回值就直接知道是相应的具体类型了。

小结:

三种方式告诉泛型方法具体化的类型

1. 显式的写在 <> 号,如 new ArrayList<String> 或 Test.<String>foo()
2. 声明类型,如 String s = Test.foo()
3. 方法参数, 如 Test.foo(String.class) 或 Test.foo("abc") 永久链接 https://yanbin.blog/java-generic-auto-infer-by-declare-type/, 来自 隔叶黄莺 Yanbin's Blog
[版权声明] 本文采用 署名-非商业性使用-相同方式共享 4.0 国际 (CC BY-NC-SA 4.0) 进行许可。