美文网首页
初探JAVA 10之var

初探JAVA 10之var

作者: Roger_黄 | 来源:发表于2018-03-11 17:20 被阅读0次

当我们看到var的时候,首先想到的会是javascript。如果我像下面这样写,会不会觉得有编译错误?

var users = new ArrayList<User>();

JAVA 10引入了var,这种写法已经合法。那为什么JAVA要引入var呢?这种写法到底好不好?我们探讨下。

一般我们在定义一个变量的时候,会在左右两边都写一遍类型,比如:

URL url = new URL("www.baidu.com");

接下来会是这种代码:

URL baidu = new URL("http://www.baidu.com");

URLConnection connection = baidu.openConnection();

Reader reader = new BufferedReader(new InputStreamReader(connection.getInputStream()));

我们定义这些只使用一次的中间变量/临时变量,还得把它的类型完整写出来,会不会觉得有点多余?可不可以省略这一步,让编译器来帮我们做?可以的。从JAVA 10开始,编译器可以推导这些类型,只要你使用var关键字。

var baidu = new URL("http://www.baidu.com");

var connection = baidu.openConnection();

var reader = new BufferedReader(new InputStreamReader(connection.getInputStream()));

想想编译器会怎么做?很简单。对比上面的两个代码块,区别就在于一个有类型,一个只有var。编译器会根据等号右边的类型推导出左边的类型,替换掉var,并且写入字节码。实际上,最后上面两个代码块的字节码是一样的。

这样带给我们什么样的便利呢?首先肯定是少打了几个字母。其次,阅读起来很简洁。当然也有不好的地方:没法直观知道变量的类型。当然,你说不是还有IDE可以帮我们么?那我们做code review的时候呢?

另外,你可能会想,是不是JAVA 10之后方法名或者变量都不能定义成var了?不会的。var在JAVA 10中并不是一个关键字,而只是一个保留的通用类型名。什么意思呢?只要你不把类名定义成var,其他场景你随便用。

对于前后端都精通的人,代入感不要太强。这写的不是js,js的神奇在JAVA语言里是不存在的,比如下面这幅图。

javascript

好了,上面说的都懂了吧?懂了的话,我们来想想下面几个问题:

1. 什么时候可以用var?什么时候不能用?

大家先看看JEP286。如果觉得看的麻烦,我解释一下:定义一个有初始值的局部变量时就可以用。像下面这种写法就是不行的:

var foo;

foo = "foo";

即便它是等价于var foo = "foo"也是不行的。下面这些写法也是不行的,包括lamda表达式方法引用:

var ints = {0, 1, 2}; //要使用new int[] {0, 1, 2}

var appendSpace = a -> a + " ";

var compareString = String::compareTo;

private var getFoo() {    

    return "foo";

}

写成下面这样是可以的:

var numbers = List.of("a", "b", "c");

for (var nr : numbers)    //for遍历时使用var声明变量

   System.out.print(nr + " ");

for (var i = 0; i < numbers.size(); i++)    //for遍历时使用var代表索引

    System.out.print(numbers.get(i) + " ");

另外,var也可以用于编程结构的改变。想象一下下面这种场景:

(new Object(){

    void foo(){

        System.out.println("I am in foo");

    }

}).foo();

定义了一个匿名对象,有一个方法叫foo。以前如果我们用Object接住这个类,那foo没有办法调用,因为它不是Object的方法。如果我们用var还可以这样写:

var obj = new Object(){

    public void foo(){

        System.out.println("I am in foo");

    }

};

......

obj.foo();

这里定义的匿名对象,编译器推断它有一个foo方法,使用var保留推断的类型信息,在后面调用foo方法都是没问题的。

所以,在以下场景使用var是完全没有问题的:

a. 局部变量。

b. for循环声明变量。

c. for循环索引变量。

2. 为什么成员变量和方法不能使用var?

这里的方法包括构造方法和一般性的方法。方法的参数和返回值都是不能使用var的。

成员变量和方法相对于局部变量来说,作用范围更大,使用var更容易出错,比如在方法中修改var变量的类型导致运行时异常。还有,对于使用var的地方,编译器都必须能够准确推断出类型信息,而成员变量和方法都是很难推断的。

3. 以后是不是本地变量都要用var呢?

未必。使用var确实能给我们带来便利,但是随之而来的是代码可读性变差。如果太多的var,看代码的人可能会很困惑,花不少时间在看类型上面。所以使用要适度,毕竟代码要给人看的,要是只有你一个人,那当我没说。Oracle JAVA架构师Brian Goetz这样说:

Use the var construct when it makes the code clearer and more concise and you’re not loosing essential information.

他的意思其实就是我们要把握好尺度,既要保证代码清爽精练,还要不能丢掉必要的信息。

好了,本次介绍var就到这里。如有介绍不清的地方,尽管拍砖。

相关文章

网友评论

      本文标题:初探JAVA 10之var

      本文链接:https://www.haomeiwen.com/subject/okhvfftx.html