javaSE-反射

1. 類的加載

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

  • 加載
    就是指將class文件讀入內存,併爲之創建一個Class對象。
    任何類被使用時系統都會建立一個Class對象
  • 連接
    驗證:是否有正確的內部結構,並和其他類協調一致
    準備:負責爲類的靜態成員分配內存,並設置默認初始化值
    解析:將類的二進制數據中的符號引用替換爲直接引用
  • 初始化 就是我們以前講過的初始化步驟

2.反射機制

在這裏插入圖片描述

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類的屬性名稱相同。不要無法賦值!
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章