<kbd id="afajh"><form id="afajh"></form></kbd>
<strong id="afajh"><dl id="afajh"></dl></strong>
    <del id="afajh"><form id="afajh"></form></del>
        1. <th id="afajh"><progress id="afajh"></progress></th>
          <b id="afajh"><abbr id="afajh"></abbr></b>
          <th id="afajh"><progress id="afajh"></progress></th>

          一份不可多得的 Lombok 學(xué)習(xí)指南

          共 21664字,需瀏覽 44分鐘

           ·

          2021-03-14 23:16

          點(diǎn)擊上方 好好學(xué)java ,選擇 星標(biāo) 公眾號(hào)

          重磅資訊,干貨,第一時(shí)間送達(dá)

          今日推薦:14 個(gè) github 項(xiàng)目!

          個(gè)人原創(chuàng)100W +訪問量博客:點(diǎn)擊前往,查看更多

          本文作者:semlinker

          本文地址:segmentfault.com/a/1190000020864572

          松哥注:對(duì)于 Lombok 這樣的工具,愛它的人覺得這簡直就是 Java 猿的救星,討厭它的的人會(huì)覺得這是什么垃圾?今天我們不討論該不該用這個(gè)東西,我們僅僅從技術(shù)角度來探討一下它的用法。

          一、Lombok 簡介

          Lombok 是一款 Java 開發(fā)插件,使得 Java 開發(fā)者可以通過其定義的一些注解來消除業(yè)務(wù)工程中冗長和繁瑣的代碼,尤其對(duì)于簡單的 Java 模型對(duì)象(POJO)。在開發(fā)環(huán)境中使用 Lombok 插件后,Java 開發(fā)人員可以節(jié)省出重復(fù)構(gòu)建,諸如 hashCode 和 equals 這樣的方法以及各種業(yè)務(wù)對(duì)象模型的 accessor 和 toString 等方法的大量時(shí)間。對(duì)于這些方法,Lombok 能夠在編譯源代碼期間自動(dòng)幫我們生成這些方法,但并不會(huì)像反射那樣降低程序的性能。

          二、Lombok 安裝

          2.1 構(gòu)建工具

          • Gradle

          在 build.gradle 文件中添加 Lombok 依賴:

          dependencies {
          compileOnly 'org.projectlombok:lombok:1.18.10'
          annotationProcessor 'org.projectlombok:lombok:1.18.10'
          }
          • Maven

          在 Maven 項(xiàng)目的 pom.xml 文件中添加 Lombok 依賴:

          <dependency>
          <groupId>org.projectlombok</groupId>
          <artifactId>lombok</artifactId>
          <version>1.18.10</version>
          <scope>provided</scope>
          </dependency>
          • Ant

          假設(shè)在 lib 目錄中已經(jīng)存在 lombok.jar,然后設(shè)置 javac 任務(wù):

          <javac srcdir="src" destdir="build" source="1.8">
          <classpath location="lib/lombok.jar" />
          </javac>

          2.2 IDE

          由于 Lombok 僅在編譯階段生成代碼,所以使用 Lombok 注解的源代碼,在 IDE 中會(huì)被高亮顯示錯(cuò)誤,針對(duì)這個(gè)問題可以通過安裝 IDE 對(duì)應(yīng)的插件來解決。這里不詳細(xì)展開,具體的安裝方式可以參考:https://www.baeldung.com/lombok-ide。

          三、Lombok 詳解

          注意:以下示例所使用的 Lombok 版本是 1.18.10

          3.1 @Getter and @Setter

          你可以使用 @Getter@Setter 注釋任何類或字段,Lombok 會(huì)自動(dòng)生成默認(rèn)的 getter/setter 方法。

          • @Getter 注解
          @Target({ElementType.FIELD, ElementType.TYPE})
          @Retention(RetentionPolicy.SOURCE)
          public @interface Getter {
          // 若getter方法非public的話,可以設(shè)置可訪問級(jí)別
          lombok.AccessLevel value() default lombok.AccessLevel.PUBLIC;
          AnyAnnotation[] onMethod() default {};
          // 是否啟用延遲初始化
          boolean lazy() default false;
          }
          • @Setter
          @Target({ElementType.FIELD, ElementType.TYPE})
          @Retention(RetentionPolicy.SOURCE)
          public @interface Setter {
          // 若setter方法非public的話,可以設(shè)置可訪問級(jí)別
          lombok.AccessLevel value() default lombok.AccessLevel.PUBLIC;
          AnyAnnotation[] onMethod() default {};
          AnyAnnotation[] onParam() default {};
          }

          使用示例

          @Getter
          @Setter
          public class GetterAndSetterDemo {
          String firstName;
          String lastName;
          LocalDate dateOfBirth;
          }

          以上代碼經(jīng)過 Lombok 編譯后,會(huì)生成如下代碼:

          public class GetterAndSetterDemo {
          String firstName;
          String lastName;
          LocalDate dateOfBirth;

          public GetterAndSetterDemo() {
          }

          // 省略其它setter和getter方法
          public String getFirstName() {
          return this.firstName;
          }

          public void setFirstName(String firstName) {
          this.firstName = firstName;
          }
          }
          • Lazy Getter

          @Getter 注解支持一個(gè) lazy 屬性,該屬性默認(rèn)為 false。當(dāng)設(shè)置為 true 時(shí),會(huì)啟用延遲初始化,即當(dāng)首次調(diào)用 getter 方法時(shí)才進(jìn)行初始化。

          示例

          public class LazyGetterDemo {
          public static void main(String[] args) {
          LazyGetterDemo m = new LazyGetterDemo();
          System.out.println("Main instance is created");
          m.getLazy();
          }

          @Getter
          private final String notLazy = createValue("not lazy");

          @Getter(lazy = true)
          private final String lazy = createValue("lazy");

          private String createValue(String name) {
          System.out.println("createValue(" + name + ")");
          return null;
          }
          }

          以上代碼經(jīng)過 Lombok 編譯后,會(huì)生成如下代碼:

          public class LazyGetterDemo {
          private final String notLazy = this.createValue("not lazy");
          private final AtomicReference<Object> lazy = new AtomicReference();

          // 已省略部分代碼
          public String getNotLazy() {
          return this.notLazy;
          }

          public String getLazy() {
          Object value = this.lazy.get();
          if (value == null) {
          synchronized(this.lazy) {
          value = this.lazy.get();
          if (value == null) {
          String actualValue = this.createValue("lazy");
          value = actualValue == null ? this.lazy : actualValue;
          this.lazy.set(value);
          }
          }
          }

          return (String)((String)(value == this.lazy ? null : value));
          }
          }

          通過以上代碼可知,調(diào)用 getLazy 方法時(shí),若發(fā)現(xiàn) value 為 null,則會(huì)在同步代碼塊中執(zhí)行初始化操作。

          3.2 Constructor Annotations

          • @NoArgsConstructor

          使用 @NoArgsConstructor 注解可以為指定類,生成默認(rèn)的構(gòu)造函數(shù),@NoArgsConstructor 注解的定義如下:

          @Target(ElementType.TYPE)
          @Retention(RetentionPolicy.SOURCE)
          public @interface NoArgsConstructor {
          // 若設(shè)置該屬性,將會(huì)生成一個(gè)私有的構(gòu)造函數(shù)且生成一個(gè)staticName指定的靜態(tài)方法
          String staticName() default "";
          AnyAnnotation[] onConstructor() default {};
          // 設(shè)置生成構(gòu)造函數(shù)的訪問級(jí)別,默認(rèn)是public
          AccessLevel access() default lombok.AccessLevel.PUBLIC;
          // 若設(shè)置為true,則初始化所有final的字段為0/null/false
          boolean force() default false;
          }

          示例

          @NoArgsConstructor(staticName = "getInstance")
          public class NoArgsConstructorDemo {
          private long id;
          private String name;
          private int age;
          }

          以上代碼經(jīng)過 Lombok 編譯后,會(huì)生成如下代碼:

          public class NoArgsConstructorDemo {
          private long id;
          private String name;
          private int age;

          private NoArgsConstructorDemo() {
          }

          public static NoArgsConstructorDemo getInstance() {
          return new NoArgsConstructorDemo();
          }
          }
          • @AllArgsConstructor

          使用 @AllArgsConstructor 注解可以為指定類,生成包含所有成員的構(gòu)造函數(shù),@AllArgsConstructor 注解的定義如下:

          @Target(ElementType.TYPE)
          @Retention(RetentionPolicy.SOURCE)
          public @interface AllArgsConstructor {
          // 若設(shè)置該屬性,將會(huì)生成一個(gè)私有的構(gòu)造函數(shù)且生成一個(gè)staticName指定的靜態(tài)方法
          String staticName() default "";
          AnyAnnotation[] onConstructor() default {};
          // 設(shè)置生成構(gòu)造函數(shù)的訪問級(jí)別,默認(rèn)是public
          AccessLevel access() default lombok.AccessLevel.PUBLIC;
          }

          示例

          @AllArgsConstructor
          public class AllArgsConstructorDemo {
          private long id;
          private String name;
          private int age;
          }

          以上代碼經(jīng)過 Lombok 編譯后,會(huì)生成如下代碼:

          public class AllArgsConstructorDemo {
          private long id;
          private String name;
          private int age;

          public AllArgsConstructorDemo(long id, String name, int age) {
          this.id = id;
          this.name = name;
          this.age = age;
          }
          }
          • @RequiredArgsConstructor

          使用 @RequiredArgsConstructor 注解可以為指定類必需初始化的成員變量,如 final 成員變量,生成對(duì)應(yīng)的構(gòu)造函數(shù),@RequiredArgsConstructor 注解的定義如下:

          @Target(ElementType.TYPE)
          @Retention(RetentionPolicy.SOURCE)
          public @interface RequiredArgsConstructor {
          // 若設(shè)置該屬性,將會(huì)生成一個(gè)私有的構(gòu)造函數(shù)且生成一個(gè)staticName指定的靜態(tài)方法
          String staticName() default "";
          AnyAnnotation[] onConstructor() default {};
          // 設(shè)置生成構(gòu)造函數(shù)的訪問級(jí)別,默認(rèn)是public
          AccessLevel access() default lombok.AccessLevel.PUBLIC;
          }

          示例

          @RequiredArgsConstructor
          public class RequiredArgsConstructorDemo {
          private final long id;
          private String name;
          private int age;
          }

          以上代碼經(jīng)過 Lombok 編譯后,會(huì)生成如下代碼:

          public class RequiredArgsConstructorDemo {
          private final long id;
          private String name;
          private int age;

          public RequiredArgsConstructorDemo(long id) {
          this.id = id;
          }
          }

          3.3 @EqualsAndHashCode

          使用 @EqualsAndHashCode 注解可以為指定類生成 equals 和 hashCode 方法, @EqualsAndHashCode 注解的定義如下:

          @Target(ElementType.TYPE)
          @Retention(RetentionPolicy.SOURCE)
          public @interface EqualsAndHashCode {
          // 指定在生成的equals和hashCode方法中需要排除的字段列表
          String[] exclude() default {};

          // 顯式列出用于identity的字段,一般情況下non-static,non-transient字段會(huì)被用于identity
          String[] of() default {};

          // 標(biāo)識(shí)在執(zhí)行字段計(jì)算前,是否調(diào)用父類的equals和hashCode方法
          boolean callSuper() default false;

          boolean doNotUseGetters() default false;

          AnyAnnotation[] onParam() default {};

          @Deprecated
          @Retention(RetentionPolicy.SOURCE)
          @Target({})
          @interface AnyAnnotation {}

          @Target(ElementType.FIELD)
          @Retention(RetentionPolicy.SOURCE)
          public @interface Exclude {}

          @Target({ElementType.FIELD, ElementType.METHOD})
          @Retention(RetentionPolicy.SOURCE)
          public @interface Include {
          String replaces() default "";
          }
          }

          示例

          @EqualsAndHashCode
          public class EqualsAndHashCodeDemo {
          String firstName;
          String lastName;
          LocalDate dateOfBirth;
          }

          以上代碼經(jīng)過 Lombok 編譯后,會(huì)生成如下代碼:

          public class EqualsAndHashCodeDemo {
          String firstName;
          String lastName;
          LocalDate dateOfBirth;

          public EqualsAndHashCodeDemo() {
          }

          public boolean equals(Object o) {
          if (o == this) {
          return true;
          } else if (!(o instanceof EqualsAndHashCodeDemo)) {
          return false;
          } else {
          EqualsAndHashCodeDemo other = (EqualsAndHashCodeDemo)o;
          if (!other.canEqual(this)) {
          return false;
          } else {
          // 已省略大量代碼
          }
          }

          public int hashCode() {
          int PRIME = true;
          int result = 1;
          Object $firstName = this.firstName;
          int result = result * 59 + ($firstName == null ? 43 : $firstName.hashCode());
          Object $lastName = this.lastName;
          result = result * 59 + ($lastName == null ? 43 : $lastName.hashCode());
          Object $dateOfBirth = this.dateOfBirth;
          result = result * 59 + ($dateOfBirth == null ? 43 : $dateOfBirth.hashCode());
          return result;
          }
          }

          3.4 @ToString

          使用 @ToString 注解可以為指定類生成 toString 方法, @ToString 注解的定義如下:

          @Target(ElementType.TYPE)
          @Retention(RetentionPolicy.SOURCE)
          public @interface ToString {
          // 打印輸出時(shí)是否包含字段的名稱
          boolean includeFieldNames() default true;

          // 列出打印輸出時(shí),需要排除的字段列表
          String[] exclude() default {};

          // 顯式的列出需要打印輸出的字段列表
          String[] of() default {};

          // 打印輸出的結(jié)果中是否包含父類的toString方法的返回結(jié)果
          boolean callSuper() default false;

          boolean doNotUseGetters() default false;

          boolean onlyExplicitlyIncluded() default false;

          @Target(ElementType.FIELD)
          @Retention(RetentionPolicy.SOURCE)
          public @interface Exclude {}

          @Target({ElementType.FIELD, ElementType.METHOD})
          @Retention(RetentionPolicy.SOURCE)
          public @interface Include {
          int rank() default 0;
          String name() default "";
          }
          }

          示例

          @ToString(exclude = {"dateOfBirth"})
          public class ToStringDemo {
          String firstName;
          String lastName;
          LocalDate dateOfBirth;
          }

          以上代碼經(jīng)過 Lombok 編譯后,會(huì)生成如下代碼:

          public class ToStringDemo {
          String firstName;
          String lastName;
          LocalDate dateOfBirth;

          public ToStringDemo() {
          }

          public String toString() {
          return "ToStringDemo(firstName=" + this.firstName + ", lastName=" +
          this.lastName + ")";
          }
          }

          3.5 @Data

          @Data 注解與同時(shí)使用以下的注解的效果是一樣的:

          @ToString
          @Getter
          @Setter
          @RequiredArgsConstructor
          @EqualsAndHashCode

          @Data 注解的定義如下:

          @Target(ElementType.TYPE)
          @Retention(RetentionPolicy.SOURCE)
          public @interface Data {
          String staticConstructor() default "";
          }

          示例

          @Data
          public class DataDemo {
          private Long id;
          private String summary;
          private String description;
          }

          以上代碼經(jīng)過 Lombok 編譯后,會(huì)生成如下代碼:

          public class DataDemo {
          private Long id;
          private String summary;
          private String description;

          public DataDemo() {
          }

          // 省略summary和description成員屬性的setter和getter方法
          public Long getId() {
          return this.id;
          }

          public void setId(Long id) {
          this.id = id;
          }

          public boolean equals(Object o) {
          if (o == this) {
          return true;
          } else if (!(o instanceof DataDemo)) {
          return false;
          } else {
          DataDemo other = (DataDemo)o;
          if (!other.canEqual(this)) {
          return false;
          } else {
          // 已省略大量代碼
          }
          }
          }

          protected boolean canEqual(Object other) {
          return other instanceof DataDemo;
          }

          public int hashCode() {
          int PRIME = true;
          int result = 1;
          Object $id = this.getId();
          int result = result * 59 + ($id == null ? 43 : $id.hashCode());
          Object $summary = this.getSummary();
          result = result * 59 + ($summary == null ? 43 : $summary.hashCode());
          Object $description = this.getDescription();
          result = result * 59 + ($description == null ? 43 : $description.hashCode());
          return result;
          }

          public String toString() {
          return "DataDemo(id=" + this.getId() + ", summary=" + this.getSummary() + ", description=" + this.getDescription() + ")";
          }
          }

          3.6 @Log

          若你將 @Log 的變體放在類上(適用于你所使用的日志記錄系統(tǒng)的任何一種);之后,你將擁有一個(gè)靜態(tài)的 final log 字段,然后你就可以使用該字段來輸出日志。

          @Log
          private static final java.util.logging.Logger log = java.util.logging.Logger.getLogger(LogExample.class.getName());
          @Log4j
          private static final org.apache.log4j.Logger log = org.apache.log4j.Logger.getLogger(LogExample.class);
          @Log4j2
          private static final org.apache.logging.log4j.Logger log = org.apache.logging.log4j.LogManager.getLogger(LogExample.class);
          @Slf4j
          private static final org.slf4j.Logger log = org.slf4j.LoggerFactory.getLogger(LogExample.class);
          @XSlf4j
          private static final org.slf4j.ext.XLogger log = org.slf4j.ext.XLoggerFactory.getXLogger(LogExample.class);
          @CommonsLog
          private static final org.apache.commons.logging.Log log = org.apache.commons.logging.LogFactory.getLog(LogExample.class);

          3.7 @Synchronized

          @Synchronized 是同步方法修飾符的更安全的變體。與 synchronized 一樣,該注解只能應(yīng)用在靜態(tài)和實(shí)例方法上。它的操作類似于 synchronized 關(guān)鍵字,但是它鎖定在不同的對(duì)象上。synchronized 關(guān)鍵字應(yīng)用在實(shí)例方法時(shí),鎖定的是 this 對(duì)象,而應(yīng)用在靜態(tài)方法上鎖定的是類對(duì)象。對(duì)于 @Synchronized 注解聲明的方法來說,它鎖定的是 lock。@Synchronized 注解的定義如下:

          @Target(ElementType.METHOD)
          @Retention(RetentionPolicy.SOURCE)
          public @interface Synchronized {
          // 指定鎖定的字段名稱
          String value() default "";
          }

          示例

          public class SynchronizedDemo {
          private final Object readLock = new Object();

          @Synchronized
          public static void hello() {
          System.out.println("world");
          }

          @Synchronized
          public int answerToLife() {
          return 42;
          }

          @Synchronized("readLock")
          public void foo() {
          System.out.println("bar");
          }
          }

          以上代碼經(jīng)過 Lombok 編譯后,會(huì)生成如下代碼:

          public class SynchronizedDemo {
          private static final Object $LOCK = new Object[0];
          private final Object $lock = new Object[0];
          private final Object readLock = new Object();

          public SynchronizedDemo() {
          }

          public static void hello() {
          synchronized($LOCK) {
          System.out.println("world");
          }
          }

          public int answerToLife() {
          synchronized(this.$lock) {
          return 42;
          }
          }

          public void foo() {
          synchronized(this.readLock) {
          System.out.println("bar");
          }
          }
          }

          3.8 @Builder

          使用 @Builder 注解可以為指定類實(shí)現(xiàn)建造者模式,該注解可以放在類、構(gòu)造函數(shù)或方法上。@Builder 注解的定義如下:

          @Target({TYPE, METHOD, CONSTRUCTOR})
          @Retention(SOURCE)
          public @interface Builder {
          @Target(FIELD)
          @Retention(SOURCE)
          public @interface Default {}

          // 創(chuàng)建新的builder實(shí)例的方法名稱
          String builderMethodName() default "builder";
          // 創(chuàng)建Builder注解類對(duì)應(yīng)實(shí)例的方法名稱
          String buildMethodName() default "build";
          // builder類的名稱
          String builderClassName() default "";

          boolean toBuilder() default false;

          AccessLevel access() default lombok.AccessLevel.PUBLIC;

          @Target({FIELD, PARAMETER})
          @Retention(SOURCE)
          public @interface ObtainVia {
          String field() default "";
          String method() default "";
          boolean isStatic() default false;
          }
          }

          示例

          @Builder
          public class BuilderDemo {
          private final String firstname;
          private final String lastname;
          private final String email;
          }

          以上代碼經(jīng)過 Lombok 編譯后,會(huì)生成如下代碼:

          public class BuilderDemo {
          private final String firstname;
          private final String lastname;
          private final String email;

          BuilderDemo(String firstname, String lastname, String email) {
          this.firstname = firstname;
          this.lastname = lastname;
          this.email = email;
          }

          public static BuilderDemo.BuilderDemoBuilder builder() {
          return new BuilderDemo.BuilderDemoBuilder();
          }

          public static class BuilderDemoBuilder {
          private String firstname;
          private String lastname;
          private String email;

          BuilderDemoBuilder() {
          }

          public BuilderDemo.BuilderDemoBuilder firstname(String firstname) {
          this.firstname = firstname;
          return this;
          }

          public BuilderDemo.BuilderDemoBuilder lastname(String lastname) {
          this.lastname = lastname;
          return this;
          }

          public BuilderDemo.BuilderDemoBuilder email(String email) {
          this.email = email;
          return this;
          }

          public BuilderDemo build() {
          return new BuilderDemo(this.firstname, this.lastname, this.email);
          }

          public String toString() {
          return "BuilderDemo.BuilderDemoBuilder(firstname=" + this.firstname + ", lastname=" + this.lastname + ", email=" + this.email + ")";
          }
          }
          }

          3.9 @SneakyThrows

          @SneakyThrows 注解用于自動(dòng)拋出已檢查的異常,而無需在方法中使用 throw 語句顯式拋出。@SneakyThrows 注解的定義如下:

          @Target({ElementType.METHOD, ElementType.CONSTRUCTOR})
          @Retention(RetentionPolicy.SOURCE)
          public @interface SneakyThrows {
          // 設(shè)置你希望向上拋的異常類
          Class<? extends Throwable>[] value() default java.lang.Throwable.class;
          }

          示例

          public class SneakyThrowsDemo {
          @SneakyThrows
          @Override
          protected Object clone() {
          return super.clone();
          }
          }

          以上代碼經(jīng)過 Lombok 編譯后,會(huì)生成如下代碼:

          public class SneakyThrowsDemo {
          public SneakyThrowsDemo() {
          }

          protected Object clone() {
          try {
          return super.clone();
          } catch (Throwable var2) {
          throw var2;
          }
          }
          }

          3.10 @NonNull

          你可以在方法或構(gòu)造函數(shù)的參數(shù)上使用 @NonNull 注解,它將會(huì)為你自動(dòng)生成非空校驗(yàn)語句。@NonNull 注解的定義如下:

          @Target({ElementType.FIELD, ElementType.METHOD, ElementType.PARAMETER, ElementType.LOCAL_VARIABLE, ElementType.TYPE_USE})
          @Retention(RetentionPolicy.CLASS)
          @Documented
          public @interface NonNull {
          }

          示例

          public class NonNullDemo {
          @Getter
          @Setter
          @NonNull
          private String name;
          }

          以上代碼經(jīng)過 Lombok 編譯后,會(huì)生成如下代碼:

          public class NonNullDemo {
          @NonNull
          private String name;

          public NonNullDemo() {
          }

          @NonNull
          public String getName() {
          return this.name;
          }

          public void setName(@NonNull String name) {
          if (name == null) {
          throw new NullPointerException("name is marked non-null but is null");
          } else {
          this.name = name;
          }
          }
          }

          3.11 @Clean

          @Clean 注解用于自動(dòng)管理資源,用在局部變量之前,在當(dāng)前變量范圍內(nèi)即將執(zhí)行完畢退出之前會(huì)自動(dòng)清理資源,自動(dòng)生成 try-finally 這樣的代碼來關(guān)閉流。

          @Target(ElementType.LOCAL_VARIABLE)
          @Retention(RetentionPolicy.SOURCE)
          public @interface Cleanup {
          // 設(shè)置用于執(zhí)行資源清理/回收的方法名稱,對(duì)應(yīng)方法不能包含任何參數(shù),默認(rèn)名稱為close。
          String value() default "close";
          }

          示例

          public class CleanupDemo {
          public static void main(String[] args) throws IOException {
          @Cleanup InputStream in = new FileInputStream(args[0]);
          @Cleanup OutputStream out = new FileOutputStream(args[1]);
          byte[] b = new byte[10000];
          while (true) {
          int r = in.read(b);
          if (r == -1) break;
          out.write(b, 0, r);
          }
          }
          }

          以上代碼經(jīng)過 Lombok 編譯后,會(huì)生成如下代碼:

          public class CleanupDemo {
          public CleanupDemo() {
          }

          public static void main(String[] args) throws IOException {
          FileInputStream in = new FileInputStream(args[0]);

          try {
          FileOutputStream out = new FileOutputStream(args[1]);

          try {
          byte[] b = new byte[10000];

          while(true) {
          int r = in.read(b);
          if (r == -1) {
          return;
          }

          out.write(b, 0, r);
          }
          } finally {
          if (Collections.singletonList(out).get(0) != null) {
          out.close();
          }

          }
          } finally {
          if (Collections.singletonList(in).get(0) != null) {
          in.close();
          }
          }
          }
          }

          3.11 @With

          在類的字段上應(yīng)用 @With 注解之后,將會(huì)自動(dòng)生成一個(gè) withFieldName(newValue) 的方法,該方法會(huì)基于 newValue 調(diào)用相應(yīng)構(gòu)造函數(shù),創(chuàng)建一個(gè)當(dāng)前類對(duì)應(yīng)的實(shí)例。@With 注解的定義如下:

          @Target({ElementType.FIELD, ElementType.TYPE})
          @Retention(RetentionPolicy.SOURCE)
          public @interface With {
          AccessLevel value() default AccessLevel.PUBLIC;

          With.AnyAnnotation[] onMethod() default {};

          With.AnyAnnotation[] onParam() default {};

          @Deprecated
          @Retention(RetentionPolicy.SOURCE)
          @Target({})
          public @interface AnyAnnotation {
          }
          }

          示例

          public class WithDemo {
          @With(AccessLevel.PROTECTED)
          @NonNull
          private final String name;
          @With
          private final int age;

          public WithDemo(String name, int age) {
          if (name == null) throw new NullPointerException();
          this.name = name;
          this.age = age;
          }
          }

          以上代碼經(jīng)過 Lombok 編譯后,會(huì)生成如下代碼:

          public class WithDemo {
          @NonNull
          private final String name;
          private final int age;

          public WithDemo(String name, int age) {
          if (name == null) {
          throw new NullPointerException();
          } else {
          this.name = name;
          this.age = age;
          }
          }

          protected WithDemo withName(@NonNull String name) {
          if (name == null) {
          throw new NullPointerException("name is marked non-null but is null");
          } else {
          return this.name == name ? this : new WithDemo(name, this.age);
          }
          }

          public WithDemo withAge(int age) {
          return this.age == age ? this : new WithDemo(this.name, age);
          }
          }

          3.12 其它特性

          • val

          val 用在局部變量前面,相當(dāng)于將變量聲明為 final,此外 Lombok 在編譯時(shí)還會(huì)自動(dòng)進(jìn)行類型推斷。val 的使用示例:

          public class ValExample {
          public String example() {
          val example = new ArrayList<String>();
          example.add("Hello, World!");
          val foo = example.get(0);
          return foo.toLowerCase();
          }

          public void example2() {
          val map = new HashMap<Integer, String>();
          map.put(0, "zero");
          map.put(5, "five");
          for (val entry : map.entrySet()) {
          System.out.printf("%d: %s\n", entry.getKey(), entry.getValue());
          }
          }
          }

          以上代碼等價(jià)于:

          public class ValExample {
          public String example() {
          final ArrayList<String> example = new ArrayList<String>();
          example.add("Hello, World!");
          final String foo = example.get(0);
          return foo.toLowerCase();
          }

          public void example2() {
          final HashMap<Integer, String> map = new HashMap<Integer, String>();
          map.put(0, "zero");
          map.put(5, "five");
          for (final Map.Entry<Integer, String> entry : map.entrySet()) {
          System.out.printf("%d: %s\n", entry.getKey(), entry.getValue());
          }
          }
          }

          至此功能強(qiáng)大的 Lombok 工具就介紹完了。


          推薦文章
          更多項(xiàng)目源碼

          瀏覽 66
          點(diǎn)贊
          評(píng)論
          收藏
          分享

          手機(jī)掃一掃分享

          分享
          舉報(bào)
          評(píng)論
          圖片
          表情
          推薦
          點(diǎn)贊
          評(píng)論
          收藏
          分享

          手機(jī)掃一掃分享

          分享
          舉報(bào)
          <kbd id="afajh"><form id="afajh"></form></kbd>
          <strong id="afajh"><dl id="afajh"></dl></strong>
            <del id="afajh"><form id="afajh"></form></del>
                1. <th id="afajh"><progress id="afajh"></progress></th>
                  <b id="afajh"><abbr id="afajh"></abbr></b>
                  <th id="afajh"><progress id="afajh"></progress></th>
                  国外操逼视频 | 亚洲精品777 | 黑人大屌三 。p 黄片免费观看永久 | 男人天堂色色网 | 国产精品无码卡一卡二卡三 |