【Java 強化】代碼規範、JavaBean、lombok、內省(Introspector)、commons-beanutils組件

Java筆記目錄可以點這裏: Java強化筆記

代碼規範(包、類、接口、方法、變量、常量名)

爲什麼要有編碼規範(Why Have Code Conventions)?

  1. 一個軟件的生命週期中,80%的花費在於維護;
  2. 幾乎沒有任何一個軟件,在其整個生命週期中,均由最初的開發人員來維護;
  3. 編碼規範可以改善軟件的可讀性,可以讓程序員儘快而徹底地理解新的代碼;
  4. 如果你將源碼作爲產品發佈,就需要確任它是否被很好的打包並且清晰無誤;
  5. 不規範,無高薪!

包名:標識符規範,全小寫字母。

  • 域名倒寫.模塊名稱.組件名;
  • com.wolfcode.crm.util;
  • cn.wolfcode._01_review;

類名:標識符規範,首字母大寫,駝峯命名法,不要用拼音和拼音縮寫。

  • Employee
  • EmployeeAdvancedSetting

接口名:副詞、名詞,習慣性以 I 開頭。

  • IEmployeeDAO
  • IUSB

方法名:動詞,首字母小寫,駝峯表示法。

  • sayHello
  • saveEmployee

變量名:名詞,首字母小寫,駝峯表示法。

  • username
  • password
  • bornDate

常量名:全大寫字母,單詞之間使用下劃線隔開。

  • MAX_VALUE
  • NOT_FOUND

知識點回顧 - 主板加載通信組件案例

面向接口編程 + 集合 + 匿名內部類

聲明一個 IUSB 接口作爲規範:

// USB規範
public interface IUSB {
	void swapData();
}

創建一個實現該規範的類 Mouse

public class Mouse implements IUSB {
	public void swapData() {
		System.out.println("鼠標在移動");
	}
}

創建主板類 MotherBoard

import java.util.HashMap;
import java.util.Map;

public class MotherBoard {
	// 存儲安裝的USB設備對象
	private Map<String, IUSB> plugins = new HashMap<>();
	
	// 將配件插在主板上
	public void install(String name, IUSB usb) {
		plugins.put(name, usb);
	}
	
	// 從主板上卸載指定的配件
	public void uninstall(String name) {
		plugins.remove(name);
	}
	
	// 主板通信, 讓每個配件都工作
	public void doWork() {
		for (IUSB usb : plugins.values()) {
			usb.swapData();
		}
	}
	
}

用來啓動項目的類 App

public class App {
	public static void main(String[] args) {
		// 主板對象
		MotherBoard board = new MotherBoard();
		// 鼠標對象
		Mouse mouse = new Mouse();
		
		// 安裝配件
		board.install("mouse", mouse);
		// 使用匿名內部類, 安裝打印接對象
		board.install("print", new IUSB() {
			@Override
			public void swapData() {
				System.out.println("打印......");
			}
		});
	
		// 調用主板的通信
		board.doWork();
		System.out.println("-----------------------");
		
	}
}
鼠標在移動
打印......
-----------------------

加載資源文件 + 反射

上面的一系列操作是很常規的面向接口編程,接下來重點來了!!!如果我們要添加一個鍵盤類 Keyboard要怎麼做,新建一個 Keyboard 類,然後在 App.javanew 了,再進行操作嗎?這樣還是有點麻煩了,可以利用 加載資源文件 + 反射 真正實現解放雙手。。

首先創建一個 資源文件夾(必須是 resource folder,它會在編譯時將裏面的文件放到項目的 path 路徑),在裏面引用 properties 文件:

# key = value
mouse = com.yusael._01_review.Mouse

此時目錄是這樣的:
在這裏插入圖片描述
來到 MotherBoard使用靜態代碼塊加載資源文件,並通過反射創建對象

import java.io.InputStream;
import java.util.HashMap;
import java.util.Map;
import java.util.Map.Entry;
import java.util.Properties;
import java.util.Set;

public class MotherBoard {
	// 存儲安裝的USB設備對象
	private static Map<String, IUSB> plugins = new HashMap<>();
	
	//-----------------------靜態代碼快加載資源文件-------------------------
	static {
		Properties p = new Properties();
		// 從classpath的根路徑去加載plugins.properties文件
		try (InputStream is = Thread.currentThread()
			.getContextClassLoader()
			.getResourceAsStream("plugins.properties"))
		{						  
			p.load(is);
			
			// 讀取properties文件, 創建USB組件對象
			Set<Entry<Object, Object>> entrys = p.entrySet();
			
			for (Entry<Object, Object> entry : entrys) {
				// 資源文件中讀取到的類名
				String className = entry.getValue().toString(); 
				// 通過反射利用類名創建對象
				IUSB usbObject = (IUSB)Class.forName(className).newInstance();
				
				plugins.put(entry.getKey().toString(), usbObject);
			}
			
		} catch (Exception e) {
			e.printStackTrace();
		}
		
	}
	//-------------------------------------------------------------------
	
	// 將配件插在主板上
	public void install(String name, IUSB usb) {
		plugins.put(name, usb);
	}
	
	// 從主板上卸載指定的配件
	public void uninstall(String name) {
		plugins.remove(name);
	}
	
	// 主板通信, 讓每個配件都工作
	public void doWork() {
		for (IUSB usb : plugins.values()) {
			usb.swapData();
		}
	}
	
}

此時 APP 中的代碼將變得十分簡潔,我們無需再手動創建配件對象再調用主板的 install,我們只需要維護好配置文件 plugins.properties 中的內容即可。

比如,我們寫一個鍵盤類 Keyboard

public class Keyboard implements IUSB{
	@Override
	public void swapData() {
		System.out.println("鍵盤在跳舞");
	}
}

我們只需要將它添加到配置文件中即可。

# key=value
mouse = com.yusael._01_review.Mouse
keyboard = com.yusael._01_review.Keyboard

APP 中的代碼是不需要動的。

public class App {
	public static void main(String[] args) {
		// 主板對象,
		MotherBoard board = new MotherBoard();
		// 調用主板的通信
		board.doWork();
		System.out.println("-----------------------");
	}
}
鍵盤在跳舞
鼠標在移動
-----------------------

JavaBean 規範

JavaBean 是一種JAVA語言寫成的可重用組件(類),必須遵循一定的規範:

  1. 類必須使用 public 修飾
  2. 必須保證有公共無參數構造器
  3. 包含了屬性的操作手段(gettersetter

分類:

  • 複雜:UI,比如 ButtonPanelWindow
  • 簡單:domaindaoservice組件、封裝數據、操作數據庫、邏輯運算等

成員:

  • 方法:Method
  • 事件:event
  • 屬性:property

屬性:

  1. attribute:表示狀態,Java中沒有該概念,很多人把 字段(Field) 稱之爲 屬性(attribute)
  2. property:表示狀態,但是不是字段,是字段的操作方法(getter/setter)決定的

框架中使用的大多是是屬性。

設置字段值:writeMethod: setter 方法:

public void setXxx(數據類型 變量){
    賦值操作;
}

若:setName ----> 屬性:name
若:setUserName ----> 屬性:userName
若:setISBN ----> 屬性:ISBN

獲取字段值:readMethod: getter方法:

public 數據類型 getXxx(){
	return 結果值;
}

若:getName ----> 屬性:name
若:getUserName----> 屬性:userName
若:getISBN ----> 屬性:ISBN
若:數據類型是 boolean,則不叫 get 方法,而是is方法,如:isEmpty

標準的屬性:一般提供字段,Eclipse 生成 getter/setter字段和屬性同名

是否需要同時提供 getter/setter

public  class User{
	private String firstName;  // 名
	private String lastName; // 性別

	//在數據庫只需要存儲全名
	public void setFullName(String fullName){}
}

面試題:說說 JavaBean 和 EJB 的區別。

Lombok 工具

一、Lombok 是什麼
Lombok 是一款小巧的代碼生成工具。官方網址:http://projectlombok.org/

Lombok 主要特性有:自動生成默認的 getter/setter 方法、自動化的資源管理(通過@Cleanup註解)及註解驅動的異常處理等。目前在國外廣泛應用。

Lombok 它和 jquery 一樣,目標是讓程序員寫更少的代碼,以及改進一些原始語法中不盡人意的地方。Lombok 能做到這一點。既不是用 annotations process,也不是用反射。而是直接黑到了編譯過程中。所以對運行效率沒有任何影響,我們可以通過反編譯 class 文件進行驗證。

二、爲何項目中要引入 Lombok

  1. 提高開發效率
  2. 使代碼直觀、簡潔、明瞭、減少了大量冗餘代碼(一般可以節省60%-70%以上的代碼)
  3. 極大減少了後期維護成本
  4. 修改變量名不需要再手動修改 getter/setter

三、使用 Lombok
5. 給 Eclipse 安裝插件,識別語法
6. 在項目中引入 lombok 包
7. 使用其中的註解(標籤)

import lombok.Getter;
import lombok.Setter;

@Getter@Setter
public class Person {
	private Long id;
	private String name;
	private Integer age;
}

Ctrl + O 可以看到當前類的字段方法getter/setter 已經存在。
在這裏插入圖片描述

內省機制(Introspector)

內省機制作用:查看和操作 JavaBean 中的屬性

  • 獲取 JavaBean 中的每一個屬性名/屬性類型
  • 通過 getter 方法獲取屬性值;通過 setter 方法給屬性設置值

首先創建一個類 User

public class User {
	private String name;
	private int age;
	private boolean man;
	
	public String getName() {
		return name;
	}
	public void setName(String name) {
		this.name = name;
	}
	public int getAge() {
		return age;
	}
	public void setAge(int age) {
		this.age = age;
	}
	public boolean isMan() {
		return man;
	}
	public void setMan(boolean man) {
		this.man = man;
	}
	
}

下面是一個關於內省機制的例子:

import java.beans.BeanInfo;
import java.beans.Introspector;
import java.beans.PropertyDescriptor;
import java.lang.reflect.Method;

// 內省機制: 操作User類值的屬性
public class IntrospectorDemo {
	public static void main(String[] args) throws Exception {
		// 1:獲取JavaBean的描述對象
		BeanInfo beanInfo = Introspector.getBeanInfo(User.class, Object.class);
		User u = User.class.newInstance();
		
		// 2:獲取JavaBean中的屬性的描述器
		PropertyDescriptor[] pds = beanInfo.getPropertyDescriptors();
		System.out.println(u); // 證明是同一個對象
		for (PropertyDescriptor pd : pds) {
			// 獲取當前屬性的名稱
			System.out.println("屬性名 = " + pd.getName());
			// 獲取當前屬性的getter方法
			System.out.println("getter : " + pd.getReadMethod());
			// 獲取當前屬性的setter方法
			System.out.println("setter : " + pd.getWriteMethod());
			System.out.println("--------------------------------");
			if ("name".equals(pd.getName())) {
				Method setter = pd.getWriteMethod(); // 獲取方法
				setter.invoke(u, "Jack"); // 調用方法
			}
		}
		System.out.println(u);
	}
}

commons-beanutils 組件

JavaBean 和 Map 相互轉換

在這裏插入圖片描述

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章