Java新特性:数据类型可以扔掉了?


枚举:尽管在 JDK 5 中增加了枚举类型,但是 Class 文件常量池的 CONSTANT_Class_info 类型常量并没有发生任何语义变化,仍然是代表一个类或接口的符号引用,没有加入枚举,也没有增加过“CONSTANT_Enum_info”之类的“枚举符号引用”常量。所以使用 enum 关键字定义常量,尽管从 Java 语法上看起来与使用 class 关键字定义类、使用 interface 关键字定义接口是同一层次的,但实际上这是由 Javac 编译器做出来的假象,从字节码的角度来看,枚举仅仅是一个继承于 java.lang.Enum、自动生成了 values() 和 valueOf() 方法的普通 Java 类而已,因此枚举也归为引用类型了。
使用对比
场景一:定义字符串
String str = "Hello, Java.";
var s = "Hello, Java.";
PS:这里的旧写法指的是 JDK 10 之前的版本,而新写法指的是 JDK 10 以后(包含 JDK 10)的版本。
场景二:数值相加
int num1 = 111;
double num2 = 555.666d;
double num3 = num1 + num2;
System.out.println(num3);
PS:当遇到不同类型相加时(int+ double)会发生数据类型向上转型,因此 num3 就会升级为 double 类型。
var n1 = 111L;
var n2 = 555.666;
var n3 = n1 + n2;
System.out.println(n3);
场景三:集合
List<Object> list = new ArrayList<>();
list.add("Hello");
list.add("Java");
var list = new ArrayList<>();
list.add("Hello");
list.add("Java");
场景四:循环
for (Object item : list) {
System.out.println("item:" + item);
}
for (int i = 0; i < 10; i++) {
// do something...
}
for (var item : list) {
System.out.println("item:" + item);
}
for (var i = 0; i < 10; i++) {
// do something...
}
场景五:配合 Lambda 使用
List<Object> flist = list.stream().filter(v ->
v.equals("Java")).collect(Collectors.toList());
System.out.println(flist);
var flist = list.stream().filter(v ->
v.equals("Java")).collect(Collectors.toList());
System.out.println(flist);
优点分析
① 提高了可读性
InternationalCustomerOrderProcessor<AnonymousCustomer, SimpleOrder<Book>> orderProcessor =
createInternationalOrderProcessor(customer, order);
var orderProcessor = createInternationalOrderProcessor(customer, order);
② 命名对齐
// 显式类型
No no = new No();
AmountIncrease<BigDecimal> more = new BigDecimalAmountIncrease();
HorizontalConnection<LinePosition, LinePosition> jumping =
new HorizontalLinePositionConnection();
Variable variable = new Constant(6);
List<String> names = List.of("Java", "中文社群");
var no = new No();
var more = new BigDecimalAmountIncrease();
var jumping = new HorizontalLinePositionConnection();
var variable = new Constant(6);
var names = List.of("Java", "中文社群");
使用规则 & 反例
它只能用于局部变量上; 声明时必须初始化; 不能用作方法参数和全局变量(类变量)。
PS:因为 var 的实现必须根据等会右边的代码进行类型推断,因此它不能被赋值 null 或不被初始化。
反例一:未初始化和赋值 null
反例二:中途类型更改

反例三:全局变量

反例四:作为返回值

原理分析
然后我们再用反编译工具打开被编译的类发现:var 竟然被替换成一个个确定的数据类型了,如下图所示:
由此我们可以得出结论:var 关键字的实现和它的名字密切相关, var 只是局部类型推断,它只会在 Java 编码期和编译期有效,当类被编译为 class 文件时,var 就会变成一个个确定的数据类型(通过推断得出)。所以我们可以把 var 通俗的理解为 Java 的语法糖,使用它可以让我们快速优雅的实现业务代码,但 var 在字节码层面是不存在的。
总结
更多精彩推荐
☞荣耀与美团合作推出 “共享笔记本”;传腾讯建议推出美国版微信,已被否;Debian 10.6 稳定版发布|极客头条
☞秋天的第一杯奶茶该买哪家?Python 爬取美团网红奶茶店告诉你
☞区块链+生鲜:杜绝“偷梁换柱”和“以次充好”
点分享 点点赞 点在看
关注公众号:拾黑(shiheibook)了解更多
[广告]赞助链接:
四季很好,只要有你,文娱排行榜:https://www.yaopaiming.com/
让资讯触达的更精准有趣:https://www.0xu.cn/

随时掌握互联网精彩
- 1 让乡亲们的生活芝麻开花节节高 7923374
- 2 中央一号文件:推进农村高额彩礼治理 7978930
- 3 不允许城镇居民到农村买农房、宅基地 7816889
- 4 以“真金白银”为企业加油 7730760
- 5 黄子琪因《消失的她》患深海恐惧症 7649317
- 6 DeepSeek预测《哪吒2》最终票房 7515683
- 7 95后情侣夜市摆摊卖麻糍日入4000元 7465961
- 8 塌房大主播集体“复活” 7342057
- 9 姚晨闷声干大事 7208110
- 10 王曼昱4比0胜孙颖莎 首夺亚洲杯冠军 7103051