天天看點

javaSE-反射1. 類的加載2.反射機制3. commons-beanutils工具

1. 類的加載

當程式要使用某個類時,如果該類還未被加載到記憶體中,則系統會通過加載,連接配接,初始化三步來實作對這個類進行初始化。

  • 加載

    就是指将class檔案讀入記憶體,并為之建立一個Class對象。

    任何類被使用時系統都會建立一個Class對象

  • 連接配接

    驗證:是否有正确的内部結構,并和其他類協調一緻

    準備:負責為類的靜态成員配置設定記憶體,并設定預設初始化值

    解析:将類的二進制資料中的符号引用替換為直接引用

  • 初始化 就是我們以前講過的初始化步驟

2.反射機制

javaSE-反射1. 類的加載2.反射機制3. commons-beanutils工具

2.1 定義

JAVA反射機制是在運作狀态中,對于任意一個類,都能夠知道這個類的所有屬性和方法;對于任意一個對象,都能夠調用它的任意一個方法和屬性;這種動态擷取的資訊以及動态調用對象的方法的功能稱為

java語言的反射機制

簡而言之:

反射就是通過class檔案對象,去使用該檔案中的成員變量,構造方法,成員方法。
           

2.2 擷取class檔案對象的方式:

  • Object類的getClass()方法:不常用
  • 資料類型的靜态屬性class:友善
  • Class類中的靜态方法:最常用,參數是字元串,友善配置

    public static Class forName(String className)

    (參數是包括包名的全路徑)
public static void main(String[] args) throws Exception {
		// 方式1
		Person p = new Person();
		Class c = p.getClass();

		Person p2 = new Person();
		Class c2 = p2.getClass();

		System.out.println(p == p2);// false
		System.out.println(c == c2);// true

		// 方式2
		Class c3 = Person.class;
		System.out.println(c == c3);// true

		// 方式3
		Class c4 = Class.forName("d1.Person");
		System.out.println(c == c4);// true
	}
           

2.3 擷取構造方法

// 1.擷取位元組碼檔案對象
Class c = Class.forName("cn.itcast_01.Person");

// 2.1擷取公有帶參構造方法
// public Constructor<T> getConstructor(Class<?>... parameterTypes)
Constructor con = c.getConstructor(String.class, int.class,String.class);
// 2.2擷取私有構造方法
Constructor con = c.getDeclaredConstructor(String.class);
con.setAccessible(true); // 值為true則訓示反射的對象在使用時應該取消Java語言通路檢查。

// 3.通過構造方法對象建立對象
// public T newInstance(Object... initargs)
Object obj = con.newInstance("林青霞", 27, "北京");
           

2.3 擷取成員變量

// 擷取公有成員變量address并對其指派
Field addressField = c.getField("address");
// public void set(Object obj,Object value) 設定新值
addressField.set(obj, "北京"); // 給obj對象的addressField字段設定值為"北京"
System.out.println(obj);

// 擷取私有成員變量name并對其指派
Field nameField = c.getDeclaredField("name");
nameField.setAccessible(true);
nameField.set(obj, "林青霞");
System.out.println(obj);
           

2.3 擷取成員方法

// 擷取公有方法 public void show()
// public Method getMethod(String name,Class<?>... parameterTypes)
// 第一個參數表示的方法名,第二個參數表示的是方法的參數的class類型
Method m1 = c.getMethod("show");
m1.invoke(obj); // 調用obj對象的m1方法

// 擷取私有方法 private String getString(String s, int i)
Method m3 = c.getMethod("getString", String.class, int.class);
m3.setAccessible(true);
Object objString = m3.invoke(obj, "hello", 100);
System.out.println(objString);
           

3. commons-beanutils工具

内省依賴反射

,但比反射簡化一點點,用來操作JavaBean把Map中的資料封裝到指定類型的JavaBean中。

1. 通過Class對象擷取BeanInfo
BeanInfo info = Introspector.getBeanInfo(User.class);

2. 通過BeanInfo擷取所有屬性描述符對象
PropertyDescriptor[] pds = info.getPropertyDescriptors();

3. PropertyDescriptor:
* String name getName():擷取目前屬性名稱
* Method getReadMethod():擷取get方法反射對象
* Method getWriteMethod():擷取set方法反射對象
           

commons-beanutils這個工具。它

底層使用了内省

,對内省進行了大量的簡化!

BeanUtils.getProperty(Object bean, String propertyName)
BeanUtils.setProperty(Object bean, String propertyName, String propertyValue)
BeanUtils.populate(Map map, Object bean)
           
1. jar包
commons-beanutils.jar、commons-logging.jar

2. 通過反射設定Javabean
Class<User> clazz = User.class;
Object user = clazz.newInstance();
		
BeanUtils.setProperty(user, "username", "admin"); 
BeanUtils.setProperty(user, "password", "admin123"); 

3. 擷取屬性值

String username = BeanUtils.getProperty(user, "username");

4. 把Map資料封裝到JavaBean對象中
Map<String,String> map = new HashMap<String,String>();
map.put("username", "admin");
map.put("password", "admin123");
User user = new User();
BeanUtils.populate(user, map); 

要求:map的key名稱必須與User類的屬性名稱相同。不要無法指派!
           

繼續閱讀