<ruby id="bdb3f"></ruby>

    <p id="bdb3f"><cite id="bdb3f"></cite></p>

      <p id="bdb3f"><cite id="bdb3f"><th id="bdb3f"></th></cite></p><p id="bdb3f"></p>
        <p id="bdb3f"><cite id="bdb3f"></cite></p>

          <pre id="bdb3f"></pre>
          <pre id="bdb3f"><del id="bdb3f"><thead id="bdb3f"></thead></del></pre>

          <ruby id="bdb3f"><mark id="bdb3f"></mark></ruby><ruby id="bdb3f"></ruby>
          <pre id="bdb3f"><pre id="bdb3f"><mark id="bdb3f"></mark></pre></pre><output id="bdb3f"></output><p id="bdb3f"></p><p id="bdb3f"></p>

          <pre id="bdb3f"><del id="bdb3f"><progress id="bdb3f"></progress></del></pre>

                <ruby id="bdb3f"></ruby>

                合規國際互聯網加速 OSASE為企業客戶提供高速穩定SD-WAN國際加速解決方案。 廣告
                [TOC] # Lombok的簡介 Lombok是一款Java開發插件,使得Java開發者可以通過其定義的一些注解來消除業務工程中冗長和繁瑣的代碼,尤其對于簡單的Java模型對象(POJO)。在開發環境中使用Lombok插件后,Java開發人員可以節省出重復構建,諸如hashCode和equals這樣的方法以及各種業務對象模型的accessor和ToString等方法的大量時間。對于這些方法,它能夠在編譯源代碼期間自動幫我們生成這些方法,并沒有如反射那樣降低程序的性能。 官方地址: https://plugins.jetbrains.com/plugin/6317-lombok-plugin **lombok??Enable annotation processing開啟** # IDEA安裝Lombok的插件 想要體驗一把Lombok的話,得先在自己的開發環境中安裝上對應的插件。下面先為大家展示下如何在Intellij中安裝上Lombok插件。 通過IntelliJ的插件中心尋找Lombok ![](https://box.kancloud.cn/42406103f19cdc034f57cea2bdc064f2_1296x1022.png) 另外需要注意的是,在使用lombok注解的時候記得要導入lombok.jar包到工程,如果使用的是Maven的工程項目的話,要在其pom.xml中添加依賴如下: ~~~ <dependency> <groupId>org.projectlombok</groupId> <artifactId>lombok</artifactId> <version>1.16.8</version> <!-- 編譯需要 --> <scope>provided</scope> </dependency> ~~~ # 注解使用 常用注解 ~~~ @Data :注解在類上;提供類所有屬性的 getting 和 setting 方法,此外還提供了equals、canEqual、hashCode、toString 方法 @Setter:注解在屬性上;為屬性提供 setting 方法 @Getter:注解在屬性上;為屬性提供 getting 方法 @Log4j :注解在類上;為類提供一個 屬性名為log 的 log4j 日志對象 @Slf4j :注解在類上;為類提供一個 屬性名為log 的 log4j 日志對象 @NoArgsConstructor:注解在類上;為類提供一個無參的構造方法 @AllArgsConstructor:注解在類上;為類提供一個全參的構造方法 @Clearup: 自動管理資源 @ToString: 用在類上可以自動撰寫toString方法 @EqualsAndHashCode: 用在類上自動生成equal方法和hashcode方法 @Synchronized: 用在方法上 ,則方法聲明是同步的,并自動加上鎖為為一個私有屬性同步鎖 @Builder: 可以用在類,構造,方法上,指定生成復雜的Builder模式的API方法 @val: 聲明局部變量為final類型 ~~~ # Lombok使用 ## val 如果對其他的語言有研究的會發現,很多語言是使用 var 作為變量申明,val作為常量申明。這里的val也是這個作用。 Val可以將變量申明是final類型。 ~~~ public String example() { val example = new ArrayList<String>(); example.add("Hello, World!"); val foo = example.get(0); return foo.toLowerCase(); } ~~~ 翻譯成 Java 程序是: ~~~ public String example() { final ArrayList<String> example = new ArrayList<String>(); example.add("Hello, World!"); final String foo = example.get(0); return foo.toLowerCase(); } ~~~ 也就是類型推導啦。 # @NonNull Null 即是罪惡 ~~~ public class NonNullExample extends Something { private String name; public NonNullExample(@NonNull Person person) { super("Hello"); this.name = person.getName(); } } ~~~ 翻譯成 Java 程序是: ~~~ public class NonNullExample extends Something { private String name; public NonNullExample(@NonNull Person person) { super("Hello"); if (person == null) { throw new NullPointerException("person"); } this.name = person.getName(); } } ~~~ # @Cleanup 自動化才是生產力 ~~~ public class CleanupExample { 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); } } } ~~~ 翻譯成 Java 程序是: ~~~ public class CleanupExample { public static void main(String[] args) throws IOException { InputStream in = new FileInputStream(args[0]); try { OutputStream out = new FileOutputStream(args[1]); try { byte[] b = new byte[10000]; while (true) { int r = in.read(b); if (r == -1) break; out.write(b, 0, r); } } finally { if (out != null) { out.close(); } } } finally { if (in != null) { in.close(); } } } } ~~~ JKD7里面就已經提供 `try with resource` ## @Getter/@Setter 再也不寫 `public int getFoo() {return foo;}` ~~~ public class GetterSetterExample { @Getter @Setter private int age = 10; @Setter(AccessLevel.PROTECTED) private String name; @Override public String toString() { return String.format("%s (age: %d)", name, age); } } ~~~ 翻譯成 Java 程序是: ~~~ public class GetterSetterExample { private int age = 10; private String name; @Override public String toString() { return String.format("%s (age: %d)", name, age); } public int getAge() { return age; } public void setAge(int age) { this.age = age; } protected void setName(String name) { this.name = name; } } ~~~~ ## @ToString 默認的toString格式為:ClassName(fieldName= fieleValue ,fieldName1=fieleValue)。 Debug Log 最強幫手 ~~~ @ToString(exclude="id") public class ToStringExample { private static final int STATIC_VAR = 10; private String name; private Shape shape = new Square(5, 10); private String[] tags; private int id; public String getName() { return this.getName(); } @ToString(callSuper=true, includeFieldNames=true) public static class Square extends Shape { private final int width, height; public Square(int width, int height) { this.width = width; this.height = height; } } } ~~~ 翻譯后: ~~~ public class ToStringExample { private static final int STATIC_VAR = 10; private String name; private Shape shape = new Square(5, 10); private String[] tags; private int id; public String getName() { return this.getName(); } public static class Square extends Shape { private final int width, height; public Square(int width, int height) { this.width = width; this.height = height; } @Override public String toString() { return "Square(super=" + super.toString() + ", width=" + this.width + ", height=" + this.height + ")"; } } @Override public String toString() { return "ToStringExample(" + this.getName() + ", " + this.shape + ", " + Arrays.deepToString(this.tags) + ")"; } } ~~~ 其實和 org.apache.commons.lang3.builder.ReflectionToStringBuilder 很像。 ## @NoArgsConstructor, @RequiredArgsConstructor and @AllArgsConstructor 這幾個注解分別為類自動生成了無參構造器、指定參數的構造器和包含所有參數的構造器。 ~~~ @RequiredArgsConstructor(staticName = "of") @AllArgsConstructor(access = AccessLevel.PROTECTED) public class ConstructorExample<T> { private int x, y; @NonNull private T description; @NoArgsConstructor public static class NoArgsExample { @NonNull private String field; } } ~~~ 翻譯后: ~~~ public class ConstructorExample<T> { private int x, y; @NonNull private T description; private ConstructorExample(T description) { if (description == null) throw new NullPointerException("description"); this.description = description; } public static <T> ConstructorExample<T> of(T description) { return new ConstructorExample<T>(description); } @java.beans.ConstructorProperties({"x", "y", "description"}) protected ConstructorExample(int x, int y, T description) { if (description == null) throw new NullPointerException("description"); this.x = x; this.y = y; this.description = description; } public static class NoArgsExample { @NonNull private String field; public NoArgsExample() { } } } ~~~ ## @Data 這個就相當的簡單啦,因為我們發現@ToString, @EqualsAndHashCode, @Getter 都很常用,這個一個注解就相當于 ~~~ @ToString @EqualsAndHashCode @Getter(所有字段) @Setter (所有非final字段) @RequiredArgsConstructor ~~~ ## @Value ~~~ @Value public class ValueExample { String name; @Wither(AccessLevel.PACKAGE) @NonFinal int age; double score; protected String[] tags; @ToString(includeFieldNames=true) @Value(staticConstructor="of") public static class Exercise<T> { String name; T value; } } ~~~ 翻譯后: ~~~ public final class ValueExample { private final String name; private int age; private final double score; protected final String[] tags; @java.beans.ConstructorProperties({"name", "age", "score", "tags"}) public ValueExample(String name, int age, double score, String[] tags) { this.name = name; this.age = age; this.score = score; this.tags = tags; } public String getName() { return this.name; } public int getAge() { return this.age; } public double getScore() { return this.score; } public String[] getTags() { return this.tags; } @java.lang.Override public boolean equals(Object o) { if (o == this) return true; if (!(o instanceof ValueExample)) return false; final ValueExample other = (ValueExample)o; final Object this$name = this.getName(); final Object other$name = other.getName(); if (this$name == null ? other$name != null : !this$name.equals(other$name)) return false; if (this.getAge() != other.getAge()) return false; if (Double.compare(this.getScore(), other.getScore()) != 0) return false; if (!Arrays.deepEquals(this.getTags(), other.getTags())) return false; return true; } @java.lang.Override public int hashCode() { final int PRIME = 59; int result = 1; final Object $name = this.getName(); result = result * PRIME + ($name == null ? 43 : $name.hashCode()); result = result * PRIME + this.getAge(); final long $score = Double.doubleToLongBits(this.getScore()); result = result * PRIME + (int)($score >>> 32 ^ $score); result = result * PRIME + Arrays.deepHashCode(this.getTags()); return result; } @java.lang.Override public String toString() { return "ValueExample(name=" + getName() + ", age=" + getAge() + ", score=" + getScore() + ", tags=" + Arrays.deepToString(getTags()) + ")"; } ValueExample withAge(int age) { return this.age == age ? this : new ValueExample(name, age, score, tags); } public static final class Exercise<T> { private final String name; private final T value; private Exercise(String name, T value) { this.name = name; this.value = value; } public static <T> Exercise<T> of(String name, T value) { return new Exercise<T>(name, value); } public String getName() { return this.name; } public T getValue() { return this.value; } @java.lang.Override public boolean equals(Object o) { if (o == this) return true; if (!(o instanceof ValueExample.Exercise)) return false; final Exercise<?> other = (Exercise<?>)o; final Object this$name = this.getName(); final Object other$name = other.getName(); if (this$name == null ? other$name != null : !this$name.equals(other$name)) return false; final Object this$value = this.getValue(); final Object other$value = other.getValue(); if (this$value == null ? other$value != null : !this$value.equals(other$value)) return false; return true; } @java.lang.Override public int hashCode() { final int PRIME = 59; int result = 1; final Object $name = this.getName(); result = result * PRIME + ($name == null ? 43 : $name.hashCode()); final Object $value = this.getValue(); result = result * PRIME + ($value == null ? 43 : $value.hashCode()); return result; } @java.lang.Override public String toString() { return "ValueExample.Exercise(name=" + getName() + ", value=" + getValue() + ")"; } } } ~~~ 我們發現了 @Value 就是 @Data 的不可變版本。 ## @Builder 提供了一種比較推崇的構建值對象的方式。 ~~~ @Builder public class BuilderExample { private String name; private int age; @Singular private Set<String> occupations; } ~~~ 翻譯后: ~~~ public class BuilderExample { private String name; private int age; private Set<String> occupations; BuilderExample(String name, int age, Set<String> occupations) { this.name = name; this.age = age; this.occupations = occupations; } public static BuilderExampleBuilder builder() { return new BuilderExampleBuilder(); } public static class BuilderExampleBuilder { private String name; private int age; private java.util.ArrayList<String> occupations; BuilderExampleBuilder() { } public BuilderExampleBuilder name(String name) { this.name = name; return this; } public BuilderExampleBuilder age(int age) { this.age = age; return this; } public BuilderExampleBuilder occupation(String occupation) { if (this.occupations == null) { this.occupations = new java.util.ArrayList<String>(); } this.occupations.add(occupation); return this; } public BuilderExampleBuilder occupations(Collection<? extends String> occupations) { if (this.occupations == null) { this.occupations = new java.util.ArrayList<String>(); } this.occupations.addAll(occupations); return this; } public BuilderExampleBuilder clearOccupations() { if (this.occupations != null) { this.occupations.clear(); } return this; } public BuilderExample build() { // complicated switch statement to produce a compact properly sized immutable set omitted. // go to https://projectlombok.org/features/Singular-snippet.html to see it. Set<String> occupations = ...; return new BuilderExample(name, age, occupations); } @java.lang.Override public String toString() { return "BuilderExample.BuilderExampleBuilder(name = " + this.name + ", age = " + this.age + ", occupations = " + this.occupations + ")"; } } } ~~~ builder是現在比較推崇的一種構建值對象的方式。 **生成器模式** ## @SneakyThrows to RuntimeException 小助手 ~~~ public class SneakyThrowsExample implements Runnable { @SneakyThrows(UnsupportedEncodingException.class) public String utf8ToString(byte[] bytes) { return new String(bytes, "UTF-8"); } @SneakyThrows public void run() { throw new Throwable(); } } ~~~ 翻譯后 ~~~ public class SneakyThrowsExample implements Runnable { public String utf8ToString(byte[] bytes) { try { return new String(bytes, "UTF-8"); } catch (UnsupportedEncodingException e) { throw Lombok.sneakyThrow(e); } } public void run() { try { throw new Throwable(); } catch (Throwable t) { throw Lombok.sneakyThrow(t); } } } ~~~ 很好的隱藏了異常,有時候的確會有這樣的煩惱,從某種程度上也是遵循的了 let is crash ## @Synchronized 類似Java中的Synchronized 關鍵字,但是可以隱藏同步鎖 ~~~ public class SynchronizedExample { 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"); } } ~~~ 翻譯后 ~~~ public class SynchronizedExample { private static final Object $LOCK = new Object[0]; private final Object $lock = new Object[0]; private final Object readLock = new Object(); public static void hello() { synchronized($LOCK) { System.out.println("world"); } } public int answerToLife() { synchronized($lock) { return 42; } } public void foo() { synchronized(readLock) { System.out.println("bar"); } } } ~~~ 這個就比較簡單直接添加了synchronized關鍵字就Ok啦。不過現在JDK也比較推薦的是 Lock 對象,這個可能用的不是特別多。 ## @Getter(lazy=true) 節約是美德 ~~~ public class GetterLazyExample { @Getter(lazy=true) private final double[] cached = expensive(); private double[] expensive() { double[] result = new double[1000000]; for (int i = 0; i < result.length; i++) { result[i] = Math.asin(i); } return result; } } ~~~ 翻譯后: ~~~ public class GetterLazyExample { private final java.util.concurrent.AtomicReference<java.lang.Object> cached = new java.util.concurrent.AtomicReference<java.lang.Object>(); public double[] getCached() { java.lang.Object value = this.cached.get(); if (value == null) { synchronized(this.cached) { value = this.cached.get(); if (value == null) { final double[] actualValue = expensive(); value = actualValue == null ? this.cached : actualValue; this.cached.set(value); } } } return (double[])(value == this.cached ? null : value); } private double[] expensive() { double[] result = new double[1000000]; for (int i = 0; i < result.length; i++) { result[i] = Math.asin(i); } return result; } } ~~~ ## @Log 再也不用寫那些差不多的LOG啦 ~~~ @Log public class LogExample { public static void main(String... args) { log.error("Something's wrong here"); } } ~~~ ~~~ @Slf4j public class LogExampleOther { public static void main(String... args) { log.error("Something else is wrong here"); } } ~~~ ~~~ @CommonsLog(topic="CounterLog") public class LogExampleCategory { public static void main(String... args) { log.error("Calling the 'CounterLog' with a message"); } } ~~~ 翻譯后: ~~~ public class LogExample { private static final java.util.logging.Logger log = java.util.logging.Logger.getLogger(LogExample.class.getName()); public static void main(String... args) { log.error("Something's wrong here"); } } public class LogExampleOther { private static final org.slf4j.Logger log = org.slf4j.LoggerFactory.getLogger(LogExampleOther.class); public static void main(String... args) { log.error("Something else is wrong here"); } } public class LogExampleCategory { private static final org.apache.commons.logging.Log log = org.apache.commons.logging.LogFactory.getLog("CounterLog"); public static void main(String... args) { log.error("Calling the 'CounterLog' with a message"); } } ~~~ # @Data編輯器底色警告 子類繼承基類后,使用@Data注解會有編輯器底色警告,告知你在生成hashcode等過程中,基類的內容不會被生成。此時,要添加@EqualsAndHashCode(callSuper=true)即可手動標記子類hash時要調用父類的hash方法對屬于父類的部分內容生成哈希值。此時就不會報警告了。(包括下面那句@ToString(callSuper = true)也是一樣) 如果覺得此方式比較麻煩的話(每個類都要),可設置lombok的配置文件lombok.config來解決: 1. lombok.config文件需要放在src/main/java文件夾下的目錄中(也可以放在實體同級目錄下),其它位置無效。內容如下: ~~~ config.stopBubbling=true lombok.equalsAndHashCode.callSuper=call ~~~ 2. 然后,在pom加入插件: ~~~ <plugin> <groupId>org.apache.maven.plugins</groupId> <artifactId>maven-compiler-plugin</artifactId> <configuration> <source>1.8</source> <target>1.8</target> </configuration> </plugin> ~~~ 此時,可見@Data編輯器警告底色消失。 # 原理 Lombok這款插件正是依靠可插件化的Java自定義注解處理API(JSR 269: Pluggable Annotation Processing API)來實現在Javac編譯階段利用“Annotation Processor”對自定義的注解進行預處理后生成真正在JVM上面執行的“Class文件”。有興趣的同學反編譯帶有Lombok注解的類文件也就一目了然了。其大致執行原理圖如下: ![](https://box.kancloud.cn/8cb5cf004c01aa7f341602ee1d3fcc7e_600x130.png) 從上面的這個原理圖上可以看出Annotation Processing是編譯器在解析Java源代碼和生成Class文件之間的一個步驟。其中Lombok插件具體的執行流程如下: ![](https://box.kancloud.cn/a09e8f2534663f4dc474d4867f4d9365_278x689.png) 從上面的Lombok執行的流程圖中可以看出,在Javac 解析成AST抽象語法樹之后, Lombok 根據自己編寫的注解處理器,動態地修改 AST,增加新的節點(即Lombok自定義注解所需要生成的代碼),最終通過分析生成JVM可執行的字節碼Class文件。使用Annotation Processing自定義注解是在編譯階段進行修改,而JDK的反射技術是在運行時動態修改,兩者相比,反射雖然更加靈活一些但是帶來的性能損耗更加大。
                  <ruby id="bdb3f"></ruby>

                  <p id="bdb3f"><cite id="bdb3f"></cite></p>

                    <p id="bdb3f"><cite id="bdb3f"><th id="bdb3f"></th></cite></p><p id="bdb3f"></p>
                      <p id="bdb3f"><cite id="bdb3f"></cite></p>

                        <pre id="bdb3f"></pre>
                        <pre id="bdb3f"><del id="bdb3f"><thead id="bdb3f"></thead></del></pre>

                        <ruby id="bdb3f"><mark id="bdb3f"></mark></ruby><ruby id="bdb3f"></ruby>
                        <pre id="bdb3f"><pre id="bdb3f"><mark id="bdb3f"></mark></pre></pre><output id="bdb3f"></output><p id="bdb3f"></p><p id="bdb3f"></p>

                        <pre id="bdb3f"><del id="bdb3f"><progress id="bdb3f"></progress></del></pre>

                              <ruby id="bdb3f"></ruby>

                              哎呀哎呀视频在线观看