Java 10 局部变量类型推断

喜欢而已 提交于 2020-03-06 23:50:25

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不被支持

    var foo = () -> {},不能用lambda表达式非常遗憾,但是我们需要来思考一个问题:为什么lambda不被支持?

    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的时候,因为少了类型帮助我们理解代码,所以变量名成了非常重要的东西。

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!