|
|
51CTO旗下网站
|
|
移步端
  • Java 14通告了,不采取"class"也能定义类了?还顺手要结果Lombok!

    2020年3月17日宣布,Java专业通告了JDK 14 ,脚下已经足以开放下载。在JDK 14官方,共有16个新特点,本文主要来介绍其中的一个特性:JEP 359: Records 。

    笔者:Hollis 来源:Hollis| 2020-03-25 18:15

    2020年3月17日宣布,Java专业通告了JDK 14 ,脚下已经足以开放下载。在JDK 14官方,共有16个新特点,本文主要来介绍其中的一个特性:JEP 359: Records

    法定吐槽最为致命

    早在必发娱乐手机版2岁首,Java 语言架构师 Brian Goetz,曾经写过一篇文章(http://cr.openjdk.java.net/~briangoetz/amber/datum.html ),详尽的说明了并吐槽了Java语言,她和众多程序员一样抱怨“Java太��嗦”或有太多的“繁文缛节”,她提出:付出人员想要创造纯数据载体类(plain data carriers)普通都不能不编写大量低价值、重温的、轻而易举出错的编码。如:结构函数、getter/setter、equals()、hashCode()以及toString()等。

    以至于许多人口选择使用IDE的效应来自动生成这些代码。还有部分开发会选择使用一些次三方类库,如Lombok等来生成这些办法,故而会导致了令人震惊的显示(surprising behavior)和糟糕的可调试性(poor debuggability)。

    这就是说,Brian Goetz 大神提到的纯数据载体到底指的是什么呢。她举了一番简单的例证:

          
    1. final class Point {  
    2.         public final int x;  
    3.         public final int y;   
    4.         public Point(int x, int y) {  
    5.             this.x = x;  
    6.             this.y = y;  
    7.         }   
    8.         // state-based implementations of equals, hashCode, toString  
    9.         // nothing else  
    10.     } 

    这其中的Piont其实就是一番纯数据载体,她表示一下"点"官方包含x坐标和y坐标,并且只提供了结构函数,以及部分equals、hashCode等方式。

    于是乎,BrianGoetz大神提出一种想法,她提出,Java总体可以对于这种纯数据载体通过另外一种方法表示。

    其实在任何的面向对象语言中,早就针对这种纯数据载体有单独的概念了,如Scala中的case、Kotlin中的data以及C#中的record。该署定义,尽管在语义上有所不同,但是它们的结合点是类的一部分或全部状态可以直接在类头中描述,并且这个类中只包含了纯数据而已。

    于是乎,她提出Java官方是否也得以通过如下方式定义一个纯数据载体呢?

          
    1. record Point(int x, int y) { } 

    神说要用record,于是乎就有了

    就像大神吐槽的那样,咱们常见需要编写大量代码才能使类变得有用。如以下内容:

  •  toString()办法
  •  hashCode() and equals()办法
  •  Getter 办法
  •  一度共有的结构函数
  • 对于这种概括的类,该署办法通常是无聊之、重温的,而且是可以很容易地机械地转移的某种东西(ide普通提供这种效益)。

    顶你读书别人的编码时,可能会更加头大。例如,人家可能行使用IDE浮动的hashCode()和equals()来处理类的一切字段,但是如何才能在不反省实现的每一行的情况下确定他写的对呢?如果在重构过程中添加了字段而没有重新生成方法,会发生什么情况呢?

    大神Brian Goetz谈起了动用record定义一个纯数据载体的想法,于是乎,Java 14 官方便包含了一番新特点:EP 359: Records ,笔者正是 Brian Goetz

    Records的对象是扩大Java语言语法,Records为声明类提供了一种紧凑的语法,用于创建一种类中是“字段,是不是字段,除了字段什么都没有”的类。穿过对类做这样的声明,玉器可以通过自动创建所有方法并让所有字段参与hashCode()等方式。这是JDK 14中的一个预览特性。

    一言不合反编译

    Records的用法比较简便,和概念Java类一样: 

          
    1. record Person (String firstName, String lastName) {}   

    以上,咱们定义了一番Person记录,其中包含两个零件:firstName和lastName,以及一个空的类体。

    这就是说,其一东西看上去也是个语法糖,那他到底是怎么实现的那?

    咱们先尝试对她开展编译,记得使用--enable-preview数,因为records效益目前在JDK 14官方还是一番预览(preview)效益。

          
    1. javac --enable-preview --release 14 Person.java  
    2. Note: Person.java uses preview language features.  
    3. Note: Recompile with -Xlint:preview for details. 

    如前所述,Record只是一番类,他目的是保存和公开数据。让咱看看用javap拓展反编译,名将会得到以下代码:

          
    1. public final class Person extends java.lang.Record {  
    2.       private final String firstName; 
    3.        private final String lastName;  
    4.       public Person(java.lang.String, java.lang.String);  
    5.       public java.lang.String toString();  
    6.       public final int hashCode();  
    7.       public final boolean equals(java.lang.Object);  
    8.       public java.lang.String firstName();  
    9.       public java.lang.String lastName();  
    10.      }   

    穿过反编译得到的类,咱们可以得到以下信息:

    1、浮动了一番final品种的Person类(class),表明这个类不能再有子类了。

    2、其一类继承了java.lang.Record类,其一我们采用enum创造出来的枚举都默认继承java.lang.Enum有点类似

    3、类中有两个private final 品种的习性。故此,record定义之类中的属性都应当是private final品种的。

    4、有一度public的结构函数,入参就是两个第一的习性。如果通过字节码查看其艺术体的话,他内容就是以下代码,你一贯很熟悉:

          
    1. public Person(String firstName, String lastName) {  
    2.         this.firstName = firstName;  
    3.         this.lastName = lastName;  
    4.     }  

    5、有两个getter办法,离别叫做firstName和lastName。这和JavaBean官方定义之命名方式有区别,或许大神想通过这种办法告诉我们record定义出来的并不是一番JavaBean吧。

    6、还起咱机关生成了toString(), hashCode() 和 equals()办法。值得一提的是,这三个办法依赖invokedynamic来动态调用包含隐式实现的适龄方式。

    还可以这样玩

    眼前的例证中,咱们简单的创造了一番record,这就是说,record官方还能有其它的积极分子变量和方式吗?咱们来看下。

    1、咱们决不能将老字段添加到record官方。但是,咱们可以添加静态字段。   

          
    1. record Person (String firstName, String lastName) {  
    2.         static int x;  
    3.     }   

    2、咱们可以定义静态方法和案例方法,可以借鉴对象的状态。 

          
    1. record Person (String firstName, String lastName) {  
    2.         static int x;     
    3.         public static void doX(){  
    4.             x++;  
    5.         }     
    6.         public String getFullName(){  
    7.             return firstName + " " + lastName;  
    8.         }  
    9.     } 

    3、咱们还可以添加构造函数。  

          
    1. record Person (String firstName, String lastName) {  
    2.         static int x;     
    3.         public Person{  
    4.             if(firstName == null){  
    5.                 throw new IllegalArgumentException( "firstName can not be null !");  
    6.             }  
    7.         }     
    8.         public Person(String fullName){  
    9.             this(fullName.split(" ")[0],this(fullName.split(" ")[1])  
    10.         }  
    11.     }   

    故此,咱们是可以在record官方添加静态字段/办法的,但是问题是,咱们应有这么做吗?

    请记住,record生产背后的对象是使开发人员能够将相关字段作为基数不可变数据项组合在总共,而不需要编写冗长的编码。这意味着,每当您想要向您的记录添加更多的字段/办法时,请考虑是否应当使用完整的类来代替它。

    总结

    record 消灭了动用类作为数据包装器的一个常见问题。纯数据类从几列代码显著地简化为一行代码。

    但是,record脚下是一种预览语言特性,这意味着,尽管他已经完全落实,但在JDK官方还没有条件。

    这就是说问题来了,如果你用上了Java 14后,你还会使用Lombok吗?哦不,你可能短时间内都用不上,因为你可能Java 8都还没用熟~

    【义务编辑: 庞桂玉 TEL:(010)68476606】

    点赞 0
  • Java  class  Lombok
  • 分享:
    大家都在看
    猜你喜欢
  • 订阅专栏+更多

     迅速无敌之 Gitlab CI 接轨集成

    迅速无敌之 Gitlab CI 接轨集成

    打破运维与科研壁垒
    共5章 | KaliArch

    91人口订阅学习

    秒杀高并发白话实战

    秒杀高并发白话实战

    主流高并发架构
    共15章 | 51CTO崔皓

    59人口订阅学习

    网络排障一点通

    网络排障一点通

    网络排障及优化调整案例
    共20章 | 捷哥CCIE

    465人口订阅学习

    订阅51CTO邮刊

    点击这里查看样刊

    订阅51CTO邮刊

    51CTO劳务号

    51CTO官微


    
       
       
       
  • 
       
    1.