【软件构造】-- 有关Java学习

【软件构造】-- 有关Java学习,第1张


var 前言一、varvar是什么? var什么时候能用?什么时候不能用!简单问题小结 var 类型和继承var 和编译时安全性var 与集合和泛型 二、几个问题为什么成员变量和方法不能使用var?以后是不是本地变量都要用var呢? 总结


前言

有关JAVA的学习记录,随时补充


一、var var是什么?

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

 var sb = new StringBuilder();

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

 StringBuilder sb = new StringBuilder();

 但如果定义那些只使用一次的中间变量/临时变量,还得把它的类型完整写出来,会不会觉得有点多余?可不可以省略这一步,让编译器来帮我们做?可以的。从JAVA 10开始,编译器可以推导这些类型,只要你使用var关键字。
 Java中var是Java10版本新出的特性,用它来定义局部变量。
使用var 定义变量的语法:var 变量名 = 初始值
关于编译器会怎么做?很简单。对比上面的两个代码块,区别就在于一个有类型,一个只有var。编译器会根据等号右边的类型推导出左边的类型,替换掉var,并且写入字节码。实际上,最后上面两个代码块的字节码是一样的。


var什么时候能用?什么时候不能用!

有关更详细介绍可以在http://openjdk.java.net/jeps/286阅读;

简单问题

定义一个有初始值的局部变量时就可以用:

var foo = “foo";

像下面这种写法就是不行的:

var foo;
foo = "foo";

即便它是等价于var foo = "foo"也是不行的。下面这些写法也是不行的。


还有就是如果代码:

var a = 20;
var a =8.9;

这样的代码会报错 显示int到double的转换;
这是因为Java是强类型语言,每个变量都有固定的变量类型。


小结

什么时候该用var定义变量:
如果你定义变量时,给变量赋给一个直观的值,这时就可以使用var定义变量,
最不能使用var定义变量:
1,给var定义的变量赋给一个很复杂的表达式时,这样使表达式的返回值不直观,不能用var定义变量。
2,var定义的变量作用域很长时,方法长和var变量影响较大时,不用var定义变量。
用var声明的注意事项:
1.var 和数组初始化;并非所有数组初始化都有效,

让我们看看什么时候 var 与 [] 不起作用:
var numbers[] = new int[]{2, 4, 6}
以下也不起作用:
var numbers = {2, 4, 6}
抛出的错误是: “array initializer needs an explicit target-type”。
就像上一个例子一样,var 和 [] 不能同时用在 LHS 一边:
var numbers[] = {2, 4, 6}
错误: ‘var’ is not allowed as an element type of an array。

只有以下数组初始化是有效的:
var numbers = new int[]{2, 4, 6}
var number = numbers[1]
number = number + 3

2.var 定义变量必须赋初始值,以后不能在赋初始值。特别注意赋NULL也不行

不允许进行 null 赋值,如下所示:
var name = null;
这将抛出异常“variable initializer is ‘null’”。因为 null 不是一个类型。

3.var每次只能定义一个变量,不能复合声明变量。

例如:var x = 1, y = 3, z = 4 //是不允许的

4.不能把定义的一个var赋值给另外一个var。

例子如下var 类型和继承

5.不允许使用 var 字段

class Clazz {
  private var name;
}

6.不允许使用 var 方法参数

void doAwesomeStuffHere(var salary){....}

7.不能将 var 作为方法返回类型

var getAwesomeStuff(){ return salary; }

catch 子句中不能使用 var

try {
   Files.readAllBytes(Paths.get("c:\temp\temp.txt"));
} catch (var e) {}
var abs = BigDecimal::abs

将抛出异常:“method reference needs an explicit target-type”。


var 类型和继承

在使用 var 时,多态仍然有效。在继承的世界中,var 类型的子类型可以像平常一样赋值给超类型的 var 类型,如下所示:

import javax.swing.*
var password = new JPasswordField("Password text")
String.valueOf(password.getPassword()) // // 将密码的字符数组转换成字符串 
var textField = new JTextField("Hello text")
textField = password
textField.getText()

但不能将超类型 var 赋值给子类型 var,如下所示:

password = textField

这是因为 JPasswordField JTextField的子类。


var 和编译时安全性

如果出现错误的赋值 *** 作会怎样?不兼容的变量类型不能相互赋值。一旦编译器推断出实际类型的 var,就不能将错误的值赋值给它,如下所示:

var number = 10
number = "InfoQ"

这里发生了什么?编译器将“var number = 10”替换为“int number = 10”,所以仍然可以保证安全性。


var 与集合和泛型

现在让我们来看看 var 与集合和泛型一起使用时如何进行类型推断。我们先从集合开始。在下面的情况中,编译器可以推断出集合元素的类型是什么:

var list = List.of(10);

这里没有必要进行类型转换,因为编译器已经推断出正确的元素类型为 int。

int i = list.get(0); // 等效于: var i = list.get(0);

下面的情况就不一样了,编译器只会将其作为对象集合(而不是整数),因为在使用菱形运算符时,Java 需要 LHS(左侧)的类型来推断 RHS 的类型:

var list2 = new ArrayList<>(); list2.add(10); list2
int i = list2.get(0) // 编译错误 
int i = (int) list2.get(0) // 需要进行转换,获得 int

对于泛型,最好在 RHS 使用特定类型(而不是菱形运算符),如下所示:

var list3 = new ArrayList(); list3.add(10); System.out.println(list3)
int i = list3.get(0)


二、几个问题 为什么成员变量和方法不能使用var?

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

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

以后是不是本地变量都要用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声明可以通过减少混乱来改善代码,从而让更重要的信息脱颖而出。另一方面,不加选择地使用var也会让事情变得更糟。使用 得当,var有助于改善良好的代码,使其更短更清晰,同时又不影响可理解性。

除此之外;还有var在使用时还有很多细节,自己也就不一一罗列
有兴趣可以读这篇博客var细节的博客点这里!

欢迎分享,转载请注明来源:内存溢出

原文地址: https://outofmemory.cn/web/1324575.html

(0)
打赏 微信扫一扫 微信扫一扫 支付宝扫一扫 支付宝扫一扫
上一篇 2022-06-12
下一篇 2022-06-12

发表评论

登录后才能评论

评论列表(0条)

保存