javavar类型_探索新的Java10“var”类型:简介和动⼿教程java var类型
重要要点
Java 10引⼊了⼀个闪亮的新功能:局部变量的类型推断。 对于局部变量,您现在可以使⽤特殊的保留类型名称“ var”,⽽不是实际类型。
提供此功能是为了增强Java语⾔并将类型推断扩展到使⽤初始化程序声明的局部变量。 这减少了所需的样板代码,同时仍保持Java的编译时类型检查。
由于编译器需要通过查看右侧(RHS)来推断var实际类型,因此此功能在某些情况下具有局限性,例如在初始化数组和流时。
在本动⼿教程中进⾏实验,以了解如何使⽤新的“ var”类型减少样板代码。
在本⽂中,我将通过⽰例介绍新的Java SE 10功能“ var”类型。 您将学习如何在代码中正确使⽤它,以及何时不能使⽤它。
介绍
Java 10引⼊了⼀个闪亮的新功能:局部变量的类型推断。 对于局部变量,您现在可以使⽤特殊的保留类型名称“ var”,⽽不是实际类型,如下所⽰:
var name = “Mohamed Taman”;
提供此功能是为了增强Java语⾔并将类型推断扩展到使⽤初始化程序声明的局部变量。 这减少了所需的样板代码,同时仍保持Java的编译时类型检查。
由于编译器需要通过观察将R ight- H和S IDE(RHS)推断出VAR实际类型,此功能在某些情况下限制。 过⼀会⼉我要提⼀下,继续阅读。 现在让我们来看⼀些简单的例⼦。
嘿,等等,等等 ! 在跳⼊代码之前,您将需要使⽤IDE像往常⼀样尝试新功能。 好消息是市场上有很多,所以您可以在许多IDE(例如Apache NetBeans 9,IntelliJ IDEA 2018或新的Eclipse)中选择⾃⼰喜欢的,⽀持Java SE 10的IDE。
就我个⼈⽽⾔,我始终喜欢使⽤交互式编程环境⼯具来快速学习Java语⾔语法,探索新的Java API及其功能,甚⾄⽤于复杂代码的原型设计。 这不是繁琐的编辑,编译和执⾏代码的过程,该过程通常涉及以下过程:
1. 编写⼀个完整的程序。
2. 编译并修复所有错误。
3. 运⾏程序。
4. 出问题所在。
5. 编辑它。
6. 重复该过程。
再次好消息是,您将使⽤⾃Java SE 9以来Java SE JDK内置和随附的JShell⼯具,该⼯具是该版本的旗舰功能。
什么是JShell
现在,Java使⽤JShell⼯具实现了丰富的REPL ( R e- E valuate - Pint- L oop)实现,称为J ava S hell,它是⼀种交互式编程环境 。那么,什么是魔术呢? 这很简单。 JShell提供了⼀个快速友好的环境,使您可以快速探索,发现和试验Java语⾔功能及其⼴泛的库。
使⽤JShell,您可以⼀次输⼊⼀个程序元素,⽴即查看结果,并根据需要进⾏调整。 因此,JShell⽤
其read-evaluate-print循环代替了繁琐的编辑,编译和执⾏循环。 在JShell中,您不是编写完整的程序,⽽是编写JShell命令和Java代码段。
输⼊代码段时,JShell会⽴即读取,评估并打印其结果。 然后循环执⾏以针对下⼀个⽚段再次执⾏此过程。 因此,JShell及其即时反馈可以吸引您的注意⼒,提⾼您的性能,并加快学习和软件开发过程。
这对于JShell来说已经⾜够了,InfoQ最近已经发布了对该⼯具的详尽介绍。 为了深⼊学习并了解有关JShell的所有功能的更多信息,我已经录制了有关此主题的完整视频培训,标题为“ 使⽤JShell进⾏Java 10编程实践[视频] ”,它可以帮助您精通该主题,并且可以通过以下途径获得或 。
现在,让我们来看⼀些简单的⽰例,以了解使⽤JShell可以使⽤此新的var类型功能来完成的⼯作 。
必备软件
为了可能与JShell⼀起使⽤,我假设您已经安装了Java SE或JDK 10+,并且JDK bin⽂件夹中的⼯具被配置为可以从系统中的任何位置访问,如果没有,这⾥是安装JDK 10+ 的链接。 。
启动JShell会话
要在以下位置启动JShell会话:
1. Microsoft Windows打开命令提⽰符,然后键⼊jshell并按Enter。
2. 在Linux上,打开⼀个shell窗⼝,然后键⼊jshell并按Enter。
3. 在macOS(以前称为OS X)上时,打开⼀个Terminal窗⼝,然后键⼊以下命令“ jshell ”并按Enter。
塔拉阿! 此命令执⾏⼀个新的JShell会话,并在jshell>提⽰符下显⽰此消息:
|  Welcome to JShell -- Version 10.0.1
|  For an introduction type: /help intro
jshell>
使⽤“ var”类型。
现在,您已经安装了JDK 10,让我们开始使⽤JShell,让我们直接跳到终端以通过⽰例开始破解var类型功能。 只需在jshell提⽰符下输⼊接下来要介绍的每个⽚段,我将把结果留给您练习。 如果您先偷偷摸摸地看⼀下代码,您会发现它看起来错了,因为没有分号。 尝试⼀下,看看它是否有效。
简单类型推断案例
这是var类型的基本⽤法,在下⾯的⽰例中,编译器可以将RHS推断为String⽂字:
var name = "Mohamed Taman"
var lastName = str.substring(8)
System.out.println("Value: "+lastName +" ,and type is: "+ Class().getTypeName())
不需要分号,因为JShell是⼀个交互式环境。 仅当同⼀⾏上有多个语句,或者声明的类型或⽅法中包含多个语句时才需要分号,并且您将在以下⽰例中看到分号。
var类型和继承
同样,多态仍然有效。 在继承的世界中,可以将var type的⼦类型分配给var type的超类型,这是通常情况,如下所⽰:
import javax.swing.*
var password = new JPasswordField("Password text")
String.Password()) // To convert password char array to string to see the value
var textField = new JTextField("Hello text")
textField = password
但是不能将超类型var分配给⼦类型var,如下所⽰:
password = textField
这是因为JPasswordField是JTextField类的⼦类。
var和编译时安全
那么现在,错误的分配⼜如何呢? 不兼容的变量类型不能互相分配。 ⼀旦编译器推断出var的实际类型,就不能为以下内容分配错误的值:
var number = 10
number = "InfoQ"
那么,这⾥发⽣了什么? 此处的编译器只是将“ var number = 10 ”替换为“ int number = 10 ”以进⾏进⼀步检查,因此仍保持安全性。
带有集合和泛型的var
好吧,让我们看看var如何与Collection元素类型推断和泛型⼀起⼯作。 让我们从集合开始。 在以下情况下,编译器可以推断集合元素的类型:
var list = List.of(10);
此处⽆需进⾏强制转换,因为编译器已推断出正确的元素类型int
int i = (0); //equivalent to: var i = (0);
在以下情况下,情况有所不同,编译器将其视为对象(不是整数)的集合,这是因为当您使⽤菱形运算符时,Java已经需要LHS (左⼿侧)上的类型来推断RHS上的类型。 ,让我们看看如何;
var list2 = new ArrayList<>(); list2.add(10); list2
int i = (0) //Compilation error
int i = (int) (0) //need to cast to get int back
对于泛型,最好在RHS上使⽤特定类型(⽽不是菱形运算符),如下所⽰:
var list3 = new ArrayList<Integer>(); list3.add(10); System.out.println(list3)
int i = (0)
让我们跳下去看看var类型如何在不同类型的循环中⼯作:
var类型⽤于循环
我们⾸先检查基于索引的普通For Loop
for (var x = 1; x <= 5; x++) {
var m = x * 2; //equivalent to: int m = x * 2;
System.out.println(m);
}
这是它与For Each循环⼀起使⽤的⽅式
var list = Arrays.asList(1,2,3,4,5,6,7,8,9,10)
for (var item : list) {
var m = item + 2;
System.out.println(m);
}
所以现在我在这⾥有⼀个问题,var是否可以与Java 8 Stream⼀起使⽤? 让我们看下⾯的例⼦;
var list = List.of(1, 2, 3, 4, 5, 6, 7)
java安装完整教程
var stream = list.stream()
stream.filter(x ->  x % 2 == 0).forEach(System.out::println)
三元运算符的var类型
三元运算符呢?
var x = 1 > 0 ? 10 : -10
int i = x
现在,如果您在三元运算符的RHS上使⽤不同类型的操作数,该怎么办? 让我们来看看:
var x = 1 > 0 ? 10 : "Less than zero"; System.out.Class()) //Integer
var x = 1 < 0 ? 10 : "Less than zero"; System.out.Class()) // String
这两个例⼦是否表明var的类型是在运⾏时确定的? 让我们以旧的⽅式做同样的事情:
Serializable x = 1 < 0 ? 10 : "Less than zero"; System.out.Class())
Serializable ,它是两个不同操作数的通⽤兼容且最专业的类型(最不专业的类型为java.lang.Object )。
String和Integer都实现Serializable。 整数从int⾃动装箱。 换句话说,序列化是两个操作数的LUB(L东ûPPER ⼄ ound)。 因此,这表明在我们的第三个⽰例中,var类型也是Serializable 。
让我们进⼊另⼀个主题:将var类型传递给⽅法。
带有⽅法的var类型
我们⾸先声明⼀个名为squareOf的⽅法,该⽅法的⼀个参数为BigDecimal类型,该⽅法将按如下所⽰返回此参数的平⽅:
BigDecimal squareOf(BigDecimal number) {
var result= number.multiply(number);
return result;
}
var number = new BigDecimal("2.5")
number = squareOf(number)
现在让我们看看它如何与泛型⼀起⼯作。 再次让我们声明⼀个名为toIntgerList的⽅法,该⽅法的⼀个参数类型为T类型的List (泛型类型),它使⽤Streams API如下返回该参数的基于整数的列表:
<T extends Number> List<Integer> toIntgerList(List<T> numbers) {
var integers = numbers.stream()
.map(Number::intValue)
.List());
return integers;
}
var numbers = List.of(1.1, 2.2, 3.3, 4.4, 5.5)
var integers = toIntgerList(numbers)
带有匿名类的var
最后,让我们看看将var与匿名类⼀起使⽤。 让我们通过实现Runnable接⼝来利⽤线程,如下所⽰:
var message = "" //effectively final
var runner = new Runnable(){
@Override
public void run() {
System.out.println(message);
}}
runner.run()
到⽬前为⽌,我已经介绍了闪亮的新Java 10功能“ var”类型,它减少了样板代码,同时保持了Java的编译时类型检查。 您通过⽰例展⽰了可以完成的⼯作。 现在,您将了解var类型的局限性以及不允许使⽤的类型。
“⽆限制”限制
现在,您将看⼀些简单的⽰例,以了解使⽤var类型功能⽆法完成的⼯作。 因此,让我们跳到终端,通过⼀些⽰例来破解限制。
jshell提⽰的结果将说明代码有什么问题,因此您可以利⽤交互式即时反馈。
您应该使⽤⼀个值进⾏初始化
⾸先,也是最简单的事情是,此处不允许使⽤没有初始化程序的变量。
var name;
您将得到⼀个编译错误; 因为编译器⽆法推断此局部变量x的类型。
不允许复合声明
尝试运⾏此⾏;
var x = 1, y = 3, z = 4
您将收到此错误消息,复合声明中不允许使⽤“ var”。
没有明确的分配
尝试如下创建⼀个称为testVar的⽅法,只需将其复制并粘贴到JShell中:
void testVar(boolean b) {
var x;
if (b) {
x = 1;
} else {
x = 2;
}
System.out.println(x);
}
它不会创建⽅法,⽽是会引发编译错误。 如果没有初始化程序,则不能在变量上使⽤“ var”。 即使是类似以下的赋值(称为“ 确定性赋值” ),也不适⽤于var。
空分配
不允许空分配,如下所⽰;
var name = null;

版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系QQ:729038198,我们将在24小时内删除。