java 10引入了var关键字,用于类型推断。
var userChannels = new HashMap<User, List<String>>();
userChannels会被判断为HashMap<User, List>类型。
var的局限性
var被oracle称为 Local variable Type inference(局部变量类型推断)
,从名字来看,它是有限制的。
-
不能用在类的字段(fields)和方法签名(method signatures)。
也就是说,它只能用于方法的局部变量。
public void method(var temp)
-
声明的同时必须要有初始化表达式。
或者var x;
都不被允许,因为没有规定需要推断的类型。var x = null;
令人困惑的是
var x = ArrayList<>()
居然是正确的代码,x会被判断为ArrayList< Object >
。 -
lambda不被支持。
,不能用lambda表达式非常遗憾,但是我们需要来思考一个问题:为什么lambda不被支持?var foo = () -> {}
从lambda的实现方式说起,lambda表达式是一个模版,JVM会根据lambda表达式生成一个私有静态方法和一个内部类,而内部类实现了函数式接口,然后再在内部类实现接口的方法中,调用私有静态方法。
为此,lambda必须于一个函数式接口绑定,而在上面var的代码中,并没有显示地说明lambda要和哪个函数式接口绑定。
var解决的问题
匿名类字段和方法访问
过去,面对一个匿名类(anonymous class),如果我们需要它的方法,一种做法是用Object接住这个对象,然后再通过反射机制去找到需要调用的函数。因为Object父类无法调用子类的方法。
//创建匿名类,并用Object接收
Object obj = new Object() {
public void hello() {
System.out.println("hello");
}
};
try {
obj.getClass().getMethod("hello")invoke(obj); //利用发射调用
} catch (Exception e) {
/*具体需要捕捉的异常:
NoSuchMethodException,
InvocationTargetException,
IllegalAccessException*/
e.getStackTrace();
}
这方法因为涉及到反射,还被强制要求捕捉三种异常,不捕捉不能通过编译,导致代码看起来非常冗长。来看看var是怎么优化它的。
//创建匿名类,并用var接收
System.out.println("invokeMethodVar()");
var obj = new Object() {
public void hello() {
System.out.println("hello");
}
};
obj.hello(); //简单调用
非常自然、简单,而且还少了反射的消耗。
作为循环的临时变量
public static void varInLoop(Map<String, List<City>> data) {
for (var item : data.entrySet()) {
doSomething(item);
}
}
var搭配增强for语法真的舒服。
产生的新问题
var虽然简化了变量的类型声明,但是不要忘了,在传统的代码中,我们经常依赖于变量类型去传递一些信息。
比如这个对象是什么,想象一下,在大量代码中,大量的var出现,你还能知道这行的这个类型是什么吗?
这似乎产生了混乱,但是oracle建议使用合理的变量名,在使用var的时候,因为少了类型帮助我们理解代码,所以变量名成了非常重要的东西。
来源:CSDN
作者:真实的hello world
链接:https://blog.csdn.net/qq_33384402/article/details/104703593