Java 內(nèi)省和反射是 Java 語言的兩個(gè)重要特性,可以在運(yùn)行時(shí)獲取和操作對象的信息,優(yōu)化代碼設(shè)計(jì)和開發(fā)效率。下面我們分別介紹一下內(nèi)省和反射。
Java 內(nèi)省
Java 內(nèi)省(Introspection)是一種獲取 Java 對象的屬性和方法信息的方式,可以在運(yùn)行時(shí)動態(tài)地查詢和修改對象的屬性值和方法調(diào)用。通過內(nèi)省機(jī)制,可以在不知道對象的具體類型的情況下調(diào)用其特定屬性或方法,實(shí)現(xiàn)了一種解耦合的程序設(shè)計(jì)。
Java 內(nèi)省是基于 JavaBean 規(guī)范實(shí)現(xiàn)的,這種規(guī)范要求 Java 對象需滿足一定的條件,包括:
public class Person { private String name; private int age; // 必須具有無參數(shù)的構(gòu)造方法 public Person() {} // 必須提供 getter 和 setter 方法 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; } }
通過內(nèi)省機(jī)制,可以獲取 Person 對象的屬性名和屬性類型,以及設(shè)置其屬性值:
import java.beans.BeanInfo; import java.beans.IntrospectionException; import java.beans.Introspector; import java.beans.PropertyDescriptor; public class IntrospectionDemo { public static void main(String[] args) throws IntrospectionException { Person p = new Person(); BeanInfo beanInfo = Introspector.getBeanInfo(p.getClass()); PropertyDescriptor[] pds = beanInfo.getPropertyDescriptors(); for (PropertyDescriptor pd : pds) { if ("name".equals(pd.getName())) { pd.getWriteMethod().invoke(p, "Tom"); } else if ("age".equals(pd.getName())) { pd.getWriteMethod().invoke(p, 18); } } System.out.println(p.getName() + "," + p.getAge()); // Tom,18 } }
Java 反射
Java 反射(Reflection)是一種在運(yùn)行時(shí)動態(tài)地獲取類的信息和操作類的屬性和方法的機(jī)制。通過反射機(jī)制,可以在程序運(yùn)行時(shí)動態(tài)地加載類、獲取類的屬性和方法、進(jìn)行屬性和方法的調(diào)用、修改對象的屬性值等。Java 反射是 Java 動態(tài)編程的核心特性之一,可用于編寫框架、插件、動態(tài)代理等應(yīng)用場景。
Java 反射通常涉及三個(gè)重要的類:Class、Constructor 和 Method。其中 Class 表示被反射的類,Constructor 和 Method 表示類的構(gòu)造方法和方法。
下面是一個(gè)簡單的反射示例,實(shí)現(xiàn)了一個(gè)動態(tài)調(diào)用類方法的方法:
import java.lang.reflect.InvocationTargetException; import java.lang.reflect.Method; public class ReflectionDemo { public static void main(String[] args) throws ClassNotFoundException, NoSuchMethodException, SecurityException, IllegalAccessException, IllegalArgumentException, InvocationTargetException { Class clazz = Class.forName("java.lang.String"); Method method = clazz.getMethod("substring", int.class, int.class); String result = (String)method.invoke("abcdef", 2, 4); System.out.println(result); // cd } }
在上述代碼中,首先獲取了 java.lang.String 類的 Class 對象,然后獲取了其 substring(int,int) 方法,并動態(tài)地調(diào)用該方法,獲取其返回值。
通過 Java 內(nèi)省和反射,我們可以實(shí)現(xiàn)很多動態(tài)性的操作,從而優(yōu)化程序設(shè)計(jì)和提高開發(fā)效率。