从lombok的val和var到JDK的var关键字方式

 更新时间:2024年05月21日 08:54:59   作者:初心绘流年  
这篇文章主要介绍了从lombok的val和var到JDK的var关键字方式,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,望不吝赐教

前言

近期因项目中的开源框架版本升级导致项目的整体jdk版本被迫从万年的java8升级到了java11

于是我们也从该开源框架中看到了对于我来说一个比较陌生的身影—val,于是便开始一小波的学习

在这里插入图片描述

一、Lombok中的val和var

1.1 lombok.val

首先看官方文档介绍:

You can use val as the type of a local variable declaration instead of actually writing the type. When you do this, the type will be inferred from the initializer expression. The local variable will also be made final. This feature works on local variables and on foreach loops only, not on fields. The initializer expression is required.

val is actually a ‘type’ of sorts, and exists as a real class in the lombok package. You must import it for val to work (or use lombok.val as the type). The existence of this type on a local variable declaration triggers both the adding of the final keyword as well as copying the type of the initializing expression which overwrites the ‘fake’ val type.

WARNING: This feature does not currently work in NetBeans.

大致的意思就是val是用于声明局部变量的,它会根据初始化的表达式来对变量类型进行推断。使用val的局部变量会被声明为final的,它可以使用与foreach的循环中,val不可以用于成员变量,并且它的初始化表达式是必须的(即必须在声明的时候给出初始化的表达式)。

使用示例:

public static void main(String[] args){
    val map = new HashMap<>();
    map.put("name","dachengcheng");
    map.put("gender","boy");
    map.put("obj", new Object());

    for (val entry:map.entrySet()){
        System.out.println(entry.getKey()+":"+entry.getValue());
    }
}

其实val就是一种类型推断的语法糖,在编译之后会进行desugar的,我们来看一下以上代码经过编译之后变成什么样子

// 以下是JDK11反编译出来的
public static void main(String[] args) {
    HashMap<Object, Object> map = new HashMap();
    map.put("name", "dachengcheng");
    map.put("gender", "boy");
    map.put("obj", new Object());
    Iterator var2 = map.entrySet().iterator();

    while(var2.hasNext()) {
        Entry<Object, Object> entry = (Entry)var2.next();
        PrintStream var10000 = System.out;
        ((PrintStream)entry.getKey()).println((String)entry.getValue());
    }

}

因为我们在泛型中并未指定具体的类型,所以类型推断出来的就是HashMap<Object,Object>的类型了,我们可以看到在循环中,也是很正确的推断出了Entry类型。

上面不是提到val代表的是final类型的局部变量吗?为啥反编译出来的没有看到final的字样?

这一点其实我也很疑惑,不知道是不是因为IDEA的工具反编译问题,或者是因为Java8以上的Effective final的特性导致的没有final修饰,但实际是final类型呢?

我们降低一下jdk版本(JDK6)试了一下,发现结果仍然一样,资料找了大半圈没找到一个人有合适的说法。于是我试了一下直接用final关键字修饰局部变量

在这里插入图片描述

在这里插入图片描述

才发现是局部变量的final并没有写入class文件中,至于为什么,大概是优化吧,具体的可能得去看看虚拟机相关的知识了,此处暂且不深入了。

局部变量以及参数中的final,同样不能提升我们的性能,它甚至不会被写进字节码中

1.2 lombok.var

还是来看官方文档的介绍

var works exactly like val, except the local variable is not marked as final.

The type is still entirely derived from the mandatory initializer expression, and any further assignments, while now legal (because the variable is no longer final), aren’t looked at to determine the appropriate type.For example, var x = "Hello"; x = Color.RED; does not work; the type of x will be inferred to be java.lang.String and thus, the x = Color.RED assignment will fail. If the type of x was inferred to be java.lang.Object this code would have compiled, but that’s not howvar works.

大致意思就是varval很像,只不过它标记的局部变量并不是final的。

二、Java中的var关键字

2.1 如何使用?

var关键字其实作用和上面提到的lombok.vallombok.var是一样的,也是用于局部变量的类型推断;var修饰的变量是非final的,如果需要final可以加上final修饰符。

还是一样我们来看一下源码和编译之后的class文件内容

源码

public class ValDemo {
    final String bbb ="111";

    public static void main(String[] args){
        var map = new HashMap<String,String>();
        map.put("aaa","dachengcheng");
        var obj = getObj();
    }
    private static List<List<Map<String, List<Map<String,String>>>>> getObj(){
        // 当然现实当中这种返回类型容易被打死,此处只是为了效果演示
        return null;
    }
}

反编译

public class ValDemo {
    final String bbb = "111";

    public ValDemo() {
    }
    public static void main(String[] args) {
        HashMap<String, String> map = new HashMap();
        map.put("aaa", "dachengcheng");
        List<List<Map<String, List<Map<String, String>>>>> obj = getObj();
    }
    private static List<List<Map<String, List<Map<String, String>>>>> getObj() {
        return null;
    }
}

2.2 为什么推出var关键字?

Java作为一个强类型的静态类型语言,为啥要推出这么一个关键字呢?

我们知道在JavaScript这种弱类型的语言中有var关键字,我想大概是因为“偷懒”吧。

我们知道Java代码存在很多模版化的声明,如HasMap<String,String> map = new HashMap<String,String>(), 这种写法虽然给我们带来了好处的同时,也带来了一些书写上的繁琐,有些人可能觉得花时间在书写这种模板代码上是在浪费时间,为啥Java就不能帮我们完成这个事呢? 比如上面提到的List<List<Map<String, List<Map<String,String>>>>>返回类型,真正要写的那可是一长串,有了var关键字之后就简单多了,直接var obj = getObj();,在这种情况下相对来说代码更简单,至于易读性是相对的,有的时候提高了可读性,有的时候反而不方便。

当然官方对于这个关键字的由来,大概是因为关于 2016 年有一个 JDK 增强提议(JEP)在 Java 社区引起了轰动:JEP 286,感兴趣的可以去了解一下。

三、该如何抉择呢?

其实该使用谁那完全看个人喜好了,但是呢我们必须得了解清楚他们之间的区别,比如lombok.val在书写的时候,IDE可能还无法识别它的final特性,可以针对该局部变量进行修改,只会在编译或运行的时候发现报错。

而且有的团队可能会比较抵制lombok,理由大概是一人用lombok,所有人都得用,在某种程度上属于强买强卖。

所以如果在JDK版本允许的情况下(JDK10及以上),我们可以考虑用jdk自带的var关键字。

如果是万年java8的话,又想使用这种语法特性,那么就可以使用lombok.val了。

Reference:

总结

以上为个人经验,希望能给大家一个参考,也希望大家多多支持脚本之家。

相关文章

  • Java web xml文件读取解析方式

    Java web xml文件读取解析方式

    这篇文章主要介绍了Java web xml文件读取解析方式,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友可以参考下
    2020-03-03
  • java.lang.String类的使用

    java.lang.String类的使用

    这篇文章主要介绍了java.lang.String类的使用,以及字符串的相关知识,需要了解相关知识的小伙伴可以参考该篇文章
    2021-08-08
  • 深度解析Java中CountDownLatch的原理

    深度解析Java中CountDownLatch的原理

    在高并发编程中,AbstractQueuedSynchronizer(简称AQS)抽象的队列同步器是我们必须掌握的,本文将通过CountDownLatch底层实现原理来了解AQS共享锁模式的实现原理,快跟随小编一起学习学习吧
    2023-07-07
  • Java 程序设计总复习题(java基础代码)

    Java 程序设计总复习题(java基础代码)

    这篇文章主要介绍了Java 程序设计总复习题,主要是java基础代码,方便学习java的同学
    2021-05-05
  • Java单例模式的知识点详解

    Java单例模式的知识点详解

    在本篇文章里小编给大家整理的是关于Java单例模式的知识点详解,有兴趣的朋友们可以学习参考下。
    2020-02-02
  • Springboot整合camunda+mysql的集成流程分析

    Springboot整合camunda+mysql的集成流程分析

    本文介绍基于mysql数据库,如何实现camunda与springboot的集成,如何实现基于springboot运行camunda开源流程引擎,本文分步骤图文相结合给大家介绍的非常详细,需要的朋友参考下吧
    2021-06-06
  • Mac OS上安装Tomcat服务器的简单步骤

    Mac OS上安装Tomcat服务器的简单步骤

    这篇文章主要介绍了Mac OS上安装Tomcat服务器的简单步骤,包括简单的启动命令和查看Tomcat信息的方法,需要的朋友可以参考下
    2015-11-11
  • javaweb登录验证码的实现方法

    javaweb登录验证码的实现方法

    这篇文章主要为大家详细介绍了javaweb登录验证码的实现方法,文中示例代码介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们可以参考一下
    2017-11-11
  • Java在Excel中添加水印的实现(单一水印、平铺水印)

    Java在Excel中添加水印的实现(单一水印、平铺水印)

    这篇文章主要介绍了Java在Excel中添加水印的实现(单一水印、平铺水印),文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧
    2021-04-04
  • Java算法设计与分析分治算法

    Java算法设计与分析分治算法

    这篇文章主要介绍了Java算法设计与分析分治算法,一般分治算法在正文中分解为两个即以上的递归调用,并且子类问题一般是不想交的
    2022-07-07

最新评论