public class Example{
public static void main(String[] args){
List<String> list=new ArrayList<String>();
list.add("Rick");
list.add("Negan");
list.add("carl");
list.forEach(
(names)->System.out.println(names)
);
}
}
在此示例中,如何推断names
的类型。
如果我们添加具有不同数据类型的项目,将会发生什么。
例如:
list.add(new Person());
list.add(new Integer(3);
答案 0 :(得分:1)
如果我理解正确的话,我认为这更多是通用问题。
当您声明List<String> namesList
时,您只能在namesList
中添加字符串及其子类型。如果尝试添加其他内容,则编译会抱怨,从namesList
的声明中得知,它可以具有String类型的值。
答案 1 :(得分:0)
仅当您创建通用对象类型的列表时,这种情况才可能发生:
public class Example {
public static void main(String[] args){
List<Object> list= new ArrayList<>();
list.add("Rick");
list.add(new Person());
list.add(new Integer(3);
list.forEach(name->System.out.println(name));
}
}
System.out.println(Object)方法将被调用,因此根据doc:
打印一个对象,然后终止该行。此方法首先调用String.valueOf(x)来获取打印对象的字符串值,然后像先调用print(String)然后调用println()一样操作。
通常,Java从来没有像动态语言这样的真类型推断。
答案 2 :(得分:0)
在此示例中,如何推断
names
的类型
幕后发生的事情是 javac 从其上下文即{{1}的签名中推断出变量names
的类型。 }(在您的特定示例中为Consumer
)消耗了forEach
。
因此,您可能会问 javac 是如何做到的? javac 会在不太多细节的情况下查找与您的lambda表达式接近的信息,并使用此信息来确定正确的类型。
也就是说, javac 不能总是推断类型,在这种情况下,您需要提供类型提示。
如果我们添加其他数据类型的项目,会发生什么情况。
您将收到编译错误。这是泛型在编译时提供更强类型检查的好处之一。
即Consumer<String>
将强类型检查应用于通用代码,如果代码违反类型安全,则会发出错误。这样做的好处是,修复编译时错误比修复运行时错误容易得多。