在本教程中,请结合实例学习Java 10的特性Local variables Type。推理JDK增强建议(JEP-286)是Java 10中的一项新功能。
什么是java10中的局部变量类型推断?
type inference 是指编译器根据初始化值自动检测数据类型。
它在Java 10中引入了局部变量。
这个功能在其他语言中已经存在,比如Scala、javascript和c#。
让我们看看这个功能在以前的Java版本中是如何工作的。
通常情况下,局部变量的声明方式如下。
在下面的例子中,创建了一个ArrayList ,在Java 5和6版本中持有字符串。
List lists=new ArrayList();
这里有两个部分,Left-hand side 和right-hand side 的相等运算符
left-hand side 是一个变量声明,有一个变量持有的数据类型。
Right-hand side 是初始化,变量被初始化时,可能持有的数据类型。
在这篇文章中,我们将讨论如何用更短、更简单的语法定义局部变量声明。
在Java 7中,Diamond operators ,允许在没有类型的情况下使用空括号,变量的声明方式如下 在Java 7之前,字符串的ArrayList ,可以声明如下
List lists=new ArrayList();
在Java 7中,使用Diamond运算符,以这样的方式减少了代码,即右边的初始化没有数据类型,数据类型从左边的推断而来。
List lists=new ArrayList<>();
在Java 10中,这种简化和减少的代码,以及类型安全,仍然有效。
var lists=new ArrayList();
编译器假设左边的类型是inferred ,作为右边的一个类型,如果右边没有类型,它将把类型视为一个对象。
编译器如何解释var类型?
每当遇到一个本地类型的变量时,它首先检查右侧的等价符号,即初始化器,找出初始化器的类型,并将这个类型分配给一个变量。
让我们看看var的例子和用法。
基本类型推理的例子 -var 关键字
在下面的例子中,本地字符串被声明并以字符串常数字面值初始化。
另一个局部变量被声明并用于存储字符串的小写字母的结果。
类型没有被声明。编译器从其值中自动推断出类型。
public class LocalVariableTypeInferenceHelloWorld {
public static void main(String[] args) {
var str = "THIS IS STRING"; // equals to String str= "THIS IS STRING";
var lowerCaseString = str.toLowerCase(); // equals to String lowerCaseString = str.toLowerCase();
System.out.println(lowerCaseString);
System.out.println(lowerCaseString.getClass().getTypeName());
}
}
和输出:
this is string
java.lang.String
在java10中使用var的类型安全例子
在下面的例子中,创建了本地的String变量,并给同一个本地变量分配了一个整数。
这给出了一个编译错误
var str = "test string"; // equals to String str= "test string";
str=10;
编译器仍在使用类型安全索引工作。
java10中的循环局部变量类型推理例子
在for循环中声明index 变量,如下所示。
public class Test {
public static void main(String[] args) {
for (var i = 1; i <= 10; i++) {
var temp= i* 2; // equals to Integer temp=i* 2;
System.out.println(temp);
}
}
}
对于每个局部变量类型推断的例子
本地变量可以用var 保留字来推断,如下所示。
在每个迭代过程中为迭代声明变量
import java.util.ArrayList;
public class ForEachVarDemo {
public static void main(String[] args) {
var list = new ArrayList();
list.add("abc");
list.add("def");
list.add("ggg");
for (var str : list) {
var upperString = str.toUpperCase(); // equal to String upperString = str.toUpperCase();
System.out.println(upperString);
}
}
}
java10中方法中的var变量和返回值
在一个方法中,声明了一个局部变量并将其返回给调用者。同时,返回值也被存储在另一个局部变量中。
public class MethodLocalVarDemo {
public static void main(String[] args) {
var number1 = 30;
var number2 = 50;
var output = sum(number1, number2);
System.out.println(output);
}
private static Integer sum(Integer number1, Integer number2) {
var result = number1 + number2;
return result;
}
}
用于存储三元运算结果的局部变量
局部变量存储了ternary operator 评估的结果。在下面的例子中,结果被推断为String。
var result = true? "true": "false";
System.out.println(result);
声明一个用于流的局部变量
var 不仅指定了数据类型,而且还推断了流。
下面是var stream的例子。
var list = new ArrayList();
list.add("abc");
list.add("def");
list.add("ggg");
var stream = list.stream();
stream.forEach((string) -> {
System.out.println(string);
});
本地变量类型推断编译错误
本地变量在使用上也有很多的限制和约束。
下面的情况都会出现编译错误。
- 没有初始化器的局部变量
这里的局部变量声明了,但没有初始化,它给出的编译错误是:Cannot use 'var' on a variable without initializer 。
- 没有用空值初始化的变量
如果var变量被初始化为空值,编译器会给出错误--无法推断初始化为'null'的局部变量的类型。
- 没有多变量或复合变量声明
不允许声明多个局部变量
var m=5,n=2,p=3; // not allowed
int m=5,n=2,p=3; // allowed
如果我们声明多个局部变量,它会给出var'在复合声明中是不允许的'。
- 不允许本地var数组初始化
像下面这样声明的数组是不允许用于局部变量的。
上面这行代码给出的错误是阵列初始化器需要一个明确的目标类型
- 不是类实例变量
不允许用局部变量声明的实例变量或类变量。
public class ClassLocalDemo {
var memberVariable=10;
public static void main(String[] args) {
}
}
- 没有方法参数/参数
本地变量不在方法签名中声明。
public class ClassLocalDemo {
public static void main(String[] args) {
}
public static void method(var parame) {
}
}
- 方法返回类型中没有var
方法的返回类型不应该是var字样,并且会抛出一个编译错误。
public static var method() {
}
- 在catch块中没有var声明
var是不允许出现在catch块中的,如下图所示
public class Test {
public static void main(String[] args) {
try {
// code
} catch (var e) {
}
}
}
- Lambda表达式需要一个明确的目标类型
下面的lambda表达式的var初始化引发了一个错误。
像钻石运算符,在右侧,需要目标数据类型才能工作
var helloString = () -> "teststring";
-构造函数参数不允许
var不应该与构造函数参数一起使用,如下图所示
public class Demo {
public Demo(var a) {
}
}
Java 10局部变量的干扰 优点 缺点
- 冗长的代码
- 可读性和更少的类型化
缺点
Java 7中的局部变量声明和钻石运算符发生冲突,使开发人员感到困惑。
var保留字
var不是一个关键词,是保留字。我们不能用'var'这个词来给变量和方法命名,这些是无效的。
总结
学习了局部变量的推理类型和在不同Java版本中的例子