優雅的JAVA工具庫LOMBOK

優雅的Java工具庫Lombok
最近在公司的項目中看到了對於Lombok的應用,經過@Data註解標註POJO,省略了大量的getter/setter代碼,原先冗長的POJO在瘦身以後直接變得乾淨、清爽,程序員不再須要去關注那些長長的方法,只須要集中注意力於字段field之中java

Lombok簡介
Lombok是一個很是實用的Java工具庫,有效地簡化Java代碼的冗長。它經過註解如@Data能夠直接爲Java bean在編譯期動態地生成字段的getter/setter方法,使用註解@NoArgsConstructor 和@AllArgsConstructor 爲Java bean添加無參構造器和有參構造器,甚至能夠在Java代碼中使用val和var聲明一個動態變量,而無需再指定具體的變量類型,區別只是val聲明的變量爲final。Lombok還提供了delombok供生成Javadoc,delombok在運行時會將註解@Data轉換成getter/setter方法,而後移除@Data註解,若是哪天再也不須要Lombok,也只須要簡單運行delombok便可。Lombok的構建支持maven和gradle,同時eclipse、myeclipse和idea等主流IDE也都和lombok兼容,因此能夠放心大膽地使用Lombok,不用擔憂IDE的編譯檢查問題。程序員

Lombok栗子
若是想學習Java工程化、高性能及分佈式、深刻淺出。微服務、Spring,MyBatis,Netty源碼分析的朋友能夠加個人Java高級交流:854630135,羣裏有阿里大牛直播講解技術,以及Java大型互聯網技術的視頻免費分享給你們。apache

Eclipse安裝Lombok支持
官網Lombok https://projectlombok.org/download 下載jar包或者經過構建工具maven,gradle下載jar包api

雙擊jar包,jar包內的安裝器會自動運行尋找eclipseeclipse

點擊【Install/Update】maven

引入Lombok依賴
    <dependency>
        <groupId>org.projectlombok</groupId>
        <artifactId>lombok</artifactId>
        <version>1.18.2</version>
        <scope>provided</scope>
    </dependency>
Lombok註解使用
Lombok的註解分爲穩定版本和試驗版本,這裏主要介紹穩定版本,由於試驗版本的支持目前和IDE不是很好分佈式

@Getter/@Setter註解ide

@Getter/@Setter註解的做用就是爲字段添加getter/setter方法,可標註在類上,也可標註在字段上。標註在類上表示全部的非靜態(no-static)字段都會生成相應的getter/setter方法,標註在字段上表示只爲這個字段生成,且會覆蓋標註在類上的註解。可設置訪問級別,默認爲public。@Setter不能夠標註final字段函數

@Getter@Setter
public class SetterExample {
    
    @Getter(value=AccessLevel.PRIVATE)@Setter
    private String name;
    
    //onMethod=@__({@AnnotationsHere})
    @Setter(onMethod=@__({@Deprecated}))
    private String age;
    
    //onParam=@__({@AnnotationsHere})
    @Setter(onParam=@__({}))
    private String sex;
    
    public static void main(String[] args) {
        SetterExample se = new SetterExample();
        se.setName("zhangsan");
        se.setAge("16");
        System.out.println(se.getAge());
        System.out.println(se.getName());
    }
}
Lombok提供了onX的試驗屬性,分別爲:onMethod, onParam, onConstructor,用於向生成的方法,構造器,參數添加註解微服務

反編譯後結果

@NonNull註解

@NonNull註解標註方法和構造器的參數,若是參數爲null,則會拋出空指針異常,不須要在代碼中進行null檢測

public class NonNullExample {
    
    @Getter
    private String name;
    
    public NonNullExample(@NonNull String name){
        this.name = name;
    }
    
    public static void main(String[] args){
        String name = null;
        NonNullExample nne = new NonNullExample(name);
        System.out.println(nne.getName());
    }
}
@ToString註解

@ToString註解生成toString()方法

@ToString
public class ToStringExample {
 
    @ToString.Exclude
    private String name;
    
    @ToString.Include
    private String age;
    
    private String sex;
    
    public static void main(String[] args) {
        ToStringExample tse = new ToStringExample();
        System.out.println(tse.toString());
    }
}
屬性includeFieldNames,默認爲true,包含屬性值

屬性callSuper,默認爲false,調用父類實現

屬性onlyExplicitlyIncluded,默認爲false,僅包含明確包含的屬性

若是想學習Java工程化、高性能及分佈式、深刻淺出。微服務、Spring,MyBatis,Netty源碼分析的朋友能夠加個人Java高級交流:854630135,羣裏有阿里大牛直播講解技術,以及Java大型互聯網技術的視頻免費分享給你們。

@ToString.Exclude 標註屬性值不包含在toString()方法中

@ToString.Include標註屬性值包含在toString()方法中

@EqualsAndHashCode

@EqualsAndHashCode註解生成equals()和hashcode()方法,註解的屬性和@ToString相似

@EqualsAndHashCode
public class EqualsAndHashcodeExample {
 
    private String name;
    private String age;
    private String sex;
    
    public static void main(String[] args) {
        EqualsAndHashcodeExample ehe1 = new EqualsAndHashcodeExample();
        EqualsAndHashcodeExample ehe2 = new EqualsAndHashcodeExample();
        System.out.println(ehe1.equals(ehe2));
        System.out.println(ehe1.hashCode());
        System.out.println(ehe2.hashCode());
    }
}
@NoArgsConstructor@RequiredArgsConstructor@AllArgsConstructor

@NoArgsConstructor : 生成一個無參數的構造方法

@NoArgsConstructor(force=true, staticName="newInstance")
public class NoArgsConstructorExample {
 
    //包含的final字段若是沒有初始化,須要加上force=true強制初始化,不然編譯錯誤
    private final String name;
    
    //不會進行null檢查
    @NonNull
    @Getter
    private String age;
    
    private String sex;
    
    public static void main(String[] args) {
        NoArgsConstructorExample nace1 = new NoArgsConstructorExample();
        System.out.println(nace1.getAge());
        NoArgsConstructorExample nace2 = NoArgsConstructorExample.newInstance();
        System.out.println(nace2.getAge());
    }
}
@RequiredArgsConstructor:會生成一個包含常量,和標識了NotNull的變量 的構造方法。

@RequiredArgsConstructor(staticName="newInstance")
public class RequiredArgsConstructorExample {
 
    private final String name;
    
    @NonNull
    @Getter
    private String age;
    
    private String sex;
    
    public static void main(String[] args) {
        RequiredArgsConstructorExample race1 = new RequiredArgsConstructorExample("lisi", "18");
        System.out.println(race1.getAge());
        RequiredArgsConstructorExample race2 = RequiredArgsConstructorExample.newInstance("zhangsan", "16");
        System.out.println(race2.getAge());
    }
}
@AllArgsConstructor:會生成一個包含全部變量,同時若是變量使用了NotNull annotation , 會進行是否爲空的校驗

@AllArgsConstructor(staticName="newInstance")
public class AllArgsConstructorExample {
 
    private final String name;
    
    @NonNull
    @Getter
    private String age;
    
    private String sex;
    public static void main(String[] args) {
        AllArgsConstructorExample aace1 = new AllArgsConstructorExample("zhangsan", "18", "female");
        System.out.println(aace1.getAge());
        AllArgsConstructorExample aace2 = AllArgsConstructorExample.newInstance("lisi", "16", "male");
        System.out.println(aace2.getAge());
    }
}
注意:三個註解生成的構造器均可以指定訪問權限,同時也能夠提供一個靜態方法來供調用。三個註解的區別在於對final和@NonNull字段的處理不一樣

另外關於staticName屬性,Lombok源碼註釋以下:

If set, the generated constructor will be private, and an additional static 'constructor' is generated with the same argument list that wraps the real constructor.
很明顯三個註解都是能夠使用構造器直接建立對象的,也能夠使用靜態方法建立對象,不知道這段註釋是什麼意思???

@Data註解

若是想學習Java工程化、高性能及分佈式、深刻淺出。微服務、Spring,MyBatis,Netty源碼分析的朋友能夠加個人Java高級交流:854630135,羣裏有阿里大牛直播講解技術,以及Java大型互聯網技術的視頻免費分享給你們。

等同於@ToString, @EqualsAndHashcode, @Getter, @Setter和@RequiredArgsConstructor一塊兒使用

@Value

@Value註解爲不可變類型的@Data,是@Data的一個變種。它標註的類和字段都會被聲明爲final

@Builder註解

@Builder註解爲類生成builder api以供調用。Builder是一種解決包含數量巨大且繁雜的字段的類的一種構建方式。

假如一個類有幾十個字段,那麼該如何設計這個類呢?

方法一:將幾十個字段都添加在構造函數中。簡單粗暴,並且在構造函數中爲字段初始化也可以保證對象可以正確建立。缺點就是幾十個參數只會致使你在建立對象時記錯參數的位置,致使沒必要要的麻煩。

方法二:依賴注入。Spring的核心功能之一就是依賴注入,藉助這種思想,咱們經過無參構造建立一個對象,而後經過setter方法設置必需的屬性。這種方式能夠根據需求初始化相關屬性,且邏輯清晰,但也會形成代碼繁瑣,須要調用屢次setter方法。

方法三:Builder模式。建造者模式的思想就是將一個大的類的構建分爲幾部分建立,從而簡化建立的複雜性。

@Builder
public class BuilderExample {
    private String name;
    private String age;
    private String sex;
    public static void main(String[] args) {
        BuilderExample be = BuilderExample.builder().name("zhangsan").age("16").sex("male").build();
        
        System.out.println(BuilderExample.builder().name("zhangsan").age("16").sex("male"));
    }
}


@Log

若是想學習Java工程化、高性能及分佈式、深刻淺出。微服務、Spring,MyBatis,Netty源碼分析的朋友能夠加個人Java高級交流:854630135,羣裏有阿里大牛直播講解技術,以及Java大型互聯網技術的視頻免費分享給你們。 

@Log註解爲類添加一個日誌對象log,類型爲java.util.logging.Logger

這個類有不少變種,詳情以下:

@CommonsLog
private static final org.apache.commons.logging.Log log = org.apache.commons.logging.LogFactory.getLog(LogExample.class);
 
@Flogger
private static final com.google.common.flogger.FluentLogger log = com.google.common.flogger.FluentLogger.forEnclosingClass();
 
@JBossLog
private static final org.jboss.logging.Logger log = org.jboss.logging.Logger.getLogger(LogExample.class);
 
@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);
@CleanUp註解

@CleanUp註解用於關閉資源,調用資源的close()方法

public class CleanUpExample {
    
    @SneakyThrows({FileNotFoundException.class, Exception.class})
    public static void main(String[] args) {
        File file = new File("C:/Users/wang2/Desktop/11.jpg");
        @Cleanup
        FileInputStream is = new FileInputStream(file);
        @Cleanup
        FileOutputStream os = new FileOutputStream(new File("C:/Users/wang2/Desktop/111.jpg"));
        
        byte[] buffer = new byte[1024];
        int length = 0;
        while((length = is.read(buffer)) != -1){
            os.write(buffer, 0, length);
        }
    }
}
注意:拋出的異常被@SneakyThrows捕獲了

若是想學習Java工程化、高性能及分佈式、深刻淺出。微服務、Spring,MyBatis,Netty源碼分析的朋友能夠加個人Java高級交流:854630135,羣裏有阿里大牛直播講解技術,以及Java大型互聯網技術的視頻免費分享給你們。

@SneakyThrows註解

若是想學習Java工程化、高性能及分佈式、深刻淺出。微服務、Spring,MyBatis,Netty源碼分析的朋友能夠加個人Java高級交流:854630135,羣裏有阿里大牛直播講解技術,以及Java大型互聯網技術的視頻免費分享給你們。 

Sneaky的意思是偷偷摸摸地,@SneakyThrows註解的做用就是取代try...catch代碼塊,自動生成相應的try...catch代碼塊  

相關文章
相關標籤/搜索