CTO:不要在代碼中寫 set/get 方法了,逮一次罰款...

2021-03-06 程式設計師教授
CTO:what?你的 Java 代碼中還充斥著大量的 set/get 方法於是公司出了規定:不要在代碼中寫 set/get 方法了,逮一次罰款。剛開始學習 Java 語言的時候,面向對象的三大特徵就是封裝,繼承,和多態。在 Java 中,要保證封裝性,需要將成員變量私有化,對外提供 set/get 方法來訪問,雖然現在的 IDE,像 eclipse,IDEA都提供了快捷鍵,來生成 set/get 方法,但是在做項目的時候,一個 JavaBean 往往會有很多的成員變量,一個變量對應兩個方法,如果有10幾個成員變量,那麼會對應20多個方法,也許還要去寫構造器、equals 等方法,而且需要維護。這樣一來,會使代碼變得非常冗餘,這些顯得很冗長也沒有太多技術含量,一旦修改屬性,就容易出現忘記修改對應方法的失誤。我在看大項目的源碼的時候,看到他們的代碼中都沒有 set/get 方法,取而代之的是在 JavaBean 上標註的註解,我感到非常的好奇,原來他們是用了一種叫做 Lombok 的插件,便去詳細了解了這個插件。
Lombok背景介紹
Project Lombok makes java a spicier language by adding 'handlers' that know how to build and compile simple, boilerplate-free, not-quite-java code.

大致意思是 Lombok 通過增加一些「處理程序」,可以讓 Java 變得簡潔、快速。Lombok使用方法Lombok 能通過註解的方式,在編譯時自動為屬性生成構造器、getter/setter、equals、hashcode、toString 方法。出現的神奇就是在源碼中沒有 getter 和 setter 方法,但是在編譯生成的字節碼文件中有 getter 和 setter 方法。這樣就省去了手動重建這些代碼的麻煩,使代碼看起來更簡潔些。Lombok 的使用跟引用 jar 包一樣,可以在官網(https://projectlombok.org/download)下載 jar 包,也可以使用 maven 添加依賴:
<dependency>
  <groupId>org.projectlombok</groupId>
    <artifactId>lombok</artifactId>
    <version>1.18.10</version>
    <scope>provided</scope>
</dependency>

選中 Plugins,搜索 Lombok,點擊 Install在公眾號程式設計師小樂後臺回復「Java」,獲取Java面試題和答案。

選擇默認的編譯方式為 javac,因為 eclipse 是不支持 Lombok 的編譯方式的,javac 支持 Lombok 的編譯方式。

打開註解生成器 Enable annotation processing

IntelliJ IDEA 2019.2(也就是我用的版本)默認是不支持 Lombok 插件的,需要去
https://plugins.jetbrains.com/plugin/6317-lombok/versions

下載對應版本的插件,然後手動引入,在 IDEA 中選擇 File -> Setting -> plugins 找到 Install Plugin from Disk…(注意版本不同位置可能有所差異)@Data 註解在類上,會為類的所有屬性自動生成 setter/getter、equals、canEqual、hashCode、toString 方法,如為 final 屬性,則不會為該屬性生成 setter 方法。
@Data
public class Student {

    private String name;

    private Integer age;

    private Integer id;

    private String major;

}

如果覺得@Data 太過殘暴(因為@Data 集合了@ToString、@EqualsAndHashCode、@Getter/@Setter、@RequiredArgsConstructor 的所有特性)不夠精細,可以使用@Getter/@Setter 註解,此註解在屬性上,可以為相應的屬性自動生成 set/get 方法。
public class Student {
   @Setter private String name;

    private Integer age;

    private Integer id;

    private String major;

    public static void main(String[] args) {

        Student stu = new Student();

        stu.setName("Mr.ml");

    }
}

該註解用在屬性或構造器上,Lombok 會生成一個非空的聲明,可用於校驗參數,能幫助避免空指針。
public class Student {
  @Setter private String name;

    private Integer age;

    private Integer id;

    private String major;



    public Student(@NonNull String name) {

        this.name = name;

    }

}

該註解能幫助我們自動調用 close() 方法,很大的簡化了代碼。
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);

     }

   }

}

默認情況下,會使用所有非靜態(non-static)和非瞬態(non-transient)屬性來生成 equals 和 hashCode,也能通過 exclude 註解來排除一些屬性。
@EqualsAndHashCode(exclude={"id", "shape"})
public class EqualsAndHashCodeExample {

    private transient int transientVar = 10;

    private String name;

    private double score;

    private Shape shape = new Square(5, 10);

    private String[] tags;

    private int id;

    public String getName() {

        return this.name;

    }

    @EqualsAndHashCode(callSuper=true)

    public static class Square extends Shape {

        private final int width, height;

        public Square(int width, int height) {

            this.width = width;

            this.height = height;

        }

    }

}

類使用@ToString 註解,Lombok 會生成一個 toString() 方法,默認情況下,會輸出類名、所有屬性(會按照屬性定義順序),用逗號來分割。在公眾號程式設計師小樂後臺回復「offer」,獲取算法面試題和答案。通過將 includeFieldNames 參數設為 true,就能明確的輸出 toString() 屬性。這一點是不是有點繞口,通過代碼來看會更清晰些。
@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;

        }

    }

}

@NoArgsConstructor, @RequiredArgsConstructor and @AllArgsConstructor無參構造器、部分參數構造器、全參構造器。Lombok沒法實現多種參數構造器的重載。
@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;

    }

}

相關焦點

  • Java中的get()方法和set()方法
    在Java中,為了數據的安全
  • 優雅的寫一個JavaBean,免去生成get和set的終極解決方案
    開發中我們要寫大量的java實體類,雖然idea能夠直接生成get和set方法,有的時候碰到那種屬性很多的實體類,看代碼都看的頭痛。現在介紹一款好用的插件給各位小夥伴,它能夠讓代碼更簡潔好看,不需要生成get和set方法,編譯也能通過。
  • java技能提升,用Lombok甩掉get和set,讓代碼變得更簡潔
    Lombok通常我們代碼裡的實體Dao或者自定義Bean都會有get()和set()方法,set是設置的意思,而get是獲取的意思,顧名思義,這兩個方法是對數據進行設置和獲取用的。一般來說set和get方法都是對私有域變量進行操作的,所以大多數都是使用在包含特定屬性的類實體中。
  • CTO:再寫if-else,逮著罰款1000!
    設計更好的軟體,替換 If-Else 的 5 種方法,從入門到高級示例If-Else 通常是一個糟糕的選擇,它導致設計複雜,代碼可讀性差,並且可能導致重構困難。應用保護子句防禦性編碼技術,你將檢查方法的輸入值,然後繼續執行方法。
  • 2020徵文-TV10分鐘鴻蒙應用實戰開發:鴻蒙手繪板 (含原始碼)
    實現onTouchEvent()方法:所以,在onTouchEvent事件函數中,我們的代碼這樣寫:switch (touchEvent.getAction()) {  case TouchEvent.PRIMARY_POINT_DOWN
  • 這樣寫的 JS 代碼看著就很舒服
    ();getClientData();getCustomerRecord();// Good:getUser()每個常量(全大寫)都該命名可以用 ESLint 檢測代碼中未命名的常量。嚴格遵守這條規則會讓你的代碼可讀性更好,也更容易重構。如果違反這個規則,那麼代碼會很難被測試或者重用。
  • Android中不得不談的setContentView
    的 setContentView       public void setContentView(int layoutResID) {        getWindow().setContentView(layoutResID);        initWindowDecorActionBar();    }getWindow
  • CTO 寫的代碼,真是絕了!
    場景:當我們接收到一些數據需要對其進行處理時,由於它們來自於不同的渠道(如:騰訊,頭條),不同渠道所需的處理方式不同,下面我們寫一個簡單Demo來實現該的場景。1、首先構建一個 GeneralChannelRule 基礎規則抽象類,定義一個抽象方法process(),不同的渠道都需要實現該抽象方法。
  • PHP實戰技巧(9)魔術方法 __get()和__set()
    前言繼續說我們的「PHP語法技巧」,這次我們來說說__get()和__set()。基礎概念get()讀取不可訪問屬性的值時,__get($name)會被調用。$name 是屬性名稱set()在給不可訪問屬性賦值時,__set($name, $value)會被調用。
  • 「譯」這樣寫的 JS 代碼看著就很舒服
    ();getClientData();getCustomerRecord();// Good:getUser()每個常量(全大寫)都該命名可以用 ESLint 檢測代碼中未命名的常量。嚴格遵守這條規則會讓你的代碼可讀性更好,也更容易重構。如果違反這個規則,那麼代碼會很難被測試或者重用。
  • Java高級特性泛型:泛型的基本用法,怎樣才能少寫1萬行代碼
    比如,在電商系統中,用戶有兩種類型,分別是普通用戶、商戶用戶。當用戶點擊獲取信息詳情時,系統要先把一些敏感信息設置為空,像是 password 之類欄位,然後才返回給用戶。  你能寫一個通用方法,把這些敏感欄位設置為空嗎?  你可能想到了,在 Java 中,所有的類都繼承了 Object 。於是,你寫出了第一個版本。
  • 30個Python極簡代碼,10分鐘get常用技巧!
    ,只有自己去想與寫,才記得住規則。作者簡單概覽了 30 段代碼,它們都是平常非常實用的技巧,我們只要花幾分鐘就能從頭到尾瀏覽一遍。以下方法可以檢查給定列表是不是存在重複元素,它會使用 set() 函數來移除所有重複元素。
  • 面試題:React中setState是異步還是同步?
    將 setState()認為是一次請求而不是一次立即執行更新組件的命令。為了更為可觀的性能,React可能會推遲它,稍後會一次性更新這些組件。React不會保證在setState之後,能夠立刻拿到改變的結果。
  • Android-SetContentView內部原理
    現在我們具體看一下setContentView中到底寫了什麼?通過尋找,發現AppCompatDelegateImplV9中進行了重寫:我們會發現三個方法中都執行了 ensureSubDecor();,我們來分析一下此段代碼:@Override    public void setContentView
  • Spring 中那些讓你愛不釋手的代碼技巧
    ("person"); }}實現ApplicationContextAware接口,然後重寫setApplicationContext方法,也能從該方法中獲取到spring容器對象。決定他們調用順序的關鍵代碼在AbstractAutowireCapableBeanFactory類的initializeBean方法中。
  • get新技能,Java的Class與反射機制原理,讓你寫出更靈活的代碼
    作為一個優秀的碼農,總是希望用最少的代碼來實現某一項功能,我也會經常翻看自己寫的舊代碼,看看有沒有可以提升的空間。代碼太複雜要考慮的是有沒有「殺雞用牛刀」,架構過度的設計,代碼層級過度設計等等。反射機制反射是框架設計的靈魂,java的反射機制就是增加程序的靈活性,避免將代碼寫死在程序裡反射的概述JAVA反射機制是在運行狀態中,對於任意一個類,都能夠知道這個類的所有屬性和方法;對於任意一個對象,都能夠調用它的任意一個方法和屬性
  • 寫代碼用這6款IDEA插件,讓你快到飛起!
    因為 idea的背景是純色,看久了使人麻木,並且單調,有了Background Image Plus,就可以設置自己喜歡圖片,顯得比較活潑一點,比如你換個自己喜歡的明星、人物是不是寫代碼時就可以充滿幹勁!還能設為每隔一段時間後隨機變化圖片,以及圖片的透明度等等,寫代碼無聊?用它用它!2.
  • JavaScript 代碼整潔之道(中)
    耦合是種非常不好的開發模式,因為它讓代碼難以重構。前提已經提到,JavaScript 沒有接口,因此抽象依賴於隱性契約。也就是說,一個對象/類會把方法和屬性暴露給另一個對象/類。在下面的例子中,隱性契約是任何用於 InventoryTracker 的 Request 模塊都應該擁有 requestItems 方法。
  • 30段極簡Python代碼:這些小技巧你都Get了麼
    作者簡單概覽了 30 段代碼,它們都是平常非常實用的技巧,我們只要花幾分鐘就能從頭到尾瀏覽一遍。1. 重複元素判定以下方法可以檢查給定列表是不是存在重複元素,它會使用 set() 函數來移除所有重複元素。
  • 112.setAttribute 和 getAttribute區別
    req.setAttribute(「msg」,「驗證碼錯誤!!」);setAttribute是賦值,如上就是將 驗證碼錯誤!!