作者热门文章
- iOS/Objective-C 元类和类别
- objective-c - -1001 错误,当 NSURLSession 通过 httpproxy 和/etc/hosts
- java - 使用网络类获取 url 地址
- ios - 推送通知中不播放声音
我有一个简单的通用方法,它创建一个包含 n 个元素的列表并返回它:
import java.util.*;
class A {
public static <T> List<T> init(int n) {
List<T> l = new ArrayList<T>();
while (n --> 0) l.add(null);
return l;
}
public static void main(String[] args) {
List<String> x = init(5);
f(x);
}
public static void f(List<String> l) {
System.out.println("l: " + l);
}
}
它按预期工作:
$ javac A.java && java A
l: [null, null, null, null, null]
但是如果我消除额外的变量:
import java.util.*;
class A {
public static <T> List<T> init(int n) {
List<T> l = new ArrayList<T>();
while (n --> 0) l.add(null);
return l;
}
public static void main(String[] args) {
f(init(5));
}
public static void f(List<String> l) {
System.out.println("l: " + l);
}
}
它不再编译
$ javac A.java && java A
A.java:9: f(java.util.List<java.lang.String>) in A cannot be applied to (java.util.List<java.lang.Object>)
f(init(5));
^
1 error
为什么?
但这仍然有效:
import java.util.*;
class A {
public static <T> List<T> init(int n) {
List<T> l = new ArrayList<T>();
while (n --> 0) l.add(null);
return l;
}
public static <T> T id(T t) {
return t;
}
public static void main(String[] args) {
List<String> x = init(5);
f(id(x));
}
public static void f(List<String> l) {
System.out.println("l: " + l);
}
}
为什么?
最佳答案
Java 在未明确定义的情况下依靠推理来确定类型变量是什么。
在你的第一个例子中:
List<String> x = init(5);
f(x);
编译器推断您正在调用 <String> init
因为x
是 List<String>
.
在你的第二个例子中:
f(init(5));
编译器无法推断您正在调用 <String> init
因为您没有明确告诉它(通过 A. <String> init(5)
),也没有将它分配给适当的变量。
在你的第三个例子中:
List<String> x = init(5);
f(id(x));
编译器推断您正在调用 <List<String>> id
返回 List<String>
至 f
.
编译器对泛型推理不是很聪明。除非您通过使用变量或直接将它们传递给方法明确说明类型参数是什么,否则它将无法弄清楚它们。
如果您对细节感到好奇,这里是 JLS 的相关部分:
关于java - 无法将泛型方法的结果传递给另一个方法?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/17262199/
我是一名优秀的程序员,十分优秀!