一、反射的作用
Java裏面的反射可以幫助我們在運行程序時候加載、使用編譯期間完全未知的class, 簡單來說就是Java可以加載一個運行時候才得知名稱的class, 獲得其完整的構造,並生成實例化對象,對其成員變量賦值,調用其方法等等。
二、應用場景
在具體的研發中,通過反射獲取類的實例,大大提高系統的靈活性和擴展性,同時由於反射的性能較低,而且它極大的破壞了類的封裝性(通過反射獲取類的私有方法和屬性),在大部分場景下並不適合使用反射,但是在大型的一些框架中,會大範圍使用反射來幫助架構完善一些功能。
三、使用反射前的準備
①. 聲明一個接口
public interface IHumanAction {
void eat();
}
②. 創建一個具體的類,注意類各個方法的修飾屬性
public class Human implements IHumanAction {
private int age;
public String name;
public Human() {
}
Human(String name) {
this.name = name;
}
protected Human(int age) {
this.age = age;
}
public Human(int age, String name, String sex) {
this.age = age;
this.name = name;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
protected void eatApple() {
System.out.println("eat apple");
}
void playGame() {
}
@Override
public void eat() {
System.out.println(this.name + " performs eat");
}
@Override
public String toString() {
return "Human{" +
"age=" + age +
", name='" + name + '\'' +
'}';
}
}
四、通過反射獲取類所實現的接口、類所繼承的超類、類的構造函數、類的方法、類的成員
①. 獲取類所實現的接口和所繼承的超類
Class clz = Class.forName("Human");
----------
if (clz != null) {
Class superclass = clz.getSuperclass();
System.out.println("該類的父類:" + superclass.getName());
Class[] interfaces = clz.getInterfaces();
for (Class class1 : interfaces) {
System.out.println("該類實現的接口:" + class1.getName());
}
}
②. 內容獲取類的構造函數
Class clz = Class.forName("Human");
----------
public static void method1_getConstructors() {
System.out.println("該類的構造函數(getConstructors): ");
if (clz != null) {
Constructor[] constructors = clz.getConstructors();
for (Constructor constructor : constructors) {
int modifiers = constructor.getModifiers();
System.out.println(Modifier.toString(modifiers) + " "+constructor.getName());
}
}
}
----------
public static void method2_getDeclaredConstructors() {
System.out.println("該類的構造函數(getDeclaredConstructors): ");
if (clz != null) {
Constructor[] declaredConstructors = clz.getDeclaredConstructors();
for (Constructor constructor : declaredConstructors) {
int modifiers = constructor.getModifiers();
System.out.println(Modifier.toString(modifiers) + " " + constructor.getName());
}
}
}
----------
public static void method3_getDeclaredConstructorsByParamType() {
System.out.println("該類的構造函數(getDeclaredConstructors(int type)): ");
if (clz != null) {
try {
Class param = int.class;
Constructor declaredConstructor = clz.getDeclaredConstructor(param);
if (declaredConstructor != null) System.out.println(Modifier.toString(declaredConstructor.getModifiers()) + " "
+ declaredConstructor.getName());
} catch (NoSuchMethodException e) {
e.printStackTrace();
} catch (SecurityException e) {
e.printStackTrace();
}
}
}
----------
public static void method4_getConstructorsByParamType() {
System.out.println("該類的構造函數(getConstructors(int type)): ");
if (clz != null) {
try {
Class param = int.class;
Constructor constructor = clz.getConstructor(param);
if (constructor != null)
System.out.println(Modifier.toString(constructor.getModifiers()) + " " + constructor.getName());
} catch (NoSuchMethodException e) {
e.printStackTrace();
} catch (SecurityException e) {
e.printStackTrace();
}
}
}
getConstuctors(),獲取的構造函數全部是public屬性的。
getConstuctor(Class …params),根據參數,從所有public屬性的構造函數中獲取相關構造函數。getDelaredConstructors(),獲取所有的構造函數。
getDelaredConstructor(Class … params),根據參數,從所有的構造函數中獲取相關構造函數
③. 內容獲取類的方法
Class clz = Class.forName("Human");
----------
public static void method1_getMethods() {
if (clz != null) {
System.out.println("getMethods()獲取該類的方法:");
Method[] methods = clz.getMethods();
for (Method method : methods) {
System.out.println(Modifier.toString(method.getModifiers()) + " " + method.getReturnType() + " "
+ method.getName());
}
}
}
----------
public static void method2_getDeclaredMethods() {
System.out.println("getDeclaredMethods()獲取該類的方法:");
if (clz != null) {
Method[] declaredMethods = clz.getDeclaredMethods();
for (Method method : declaredMethods) {
System.out.println(Modifier.toString(method.getModifiers()) + " " + method.getReturnType() + " "
+ method.getName());
}
}
}
getMethods()返回類中所有的public屬性的方法,包括從基類繼承的public方法。
getDeclaredMethods()返回類本身聲明的方法,包括複寫的方法,不包括從基類繼承的方法 。
getMethod(name,params)根據參數從getMethods()返回的結果中篩選。
getDeclaredMethod(name,params)根據參數從getDeclaredMethods()返回的結果中篩選 。
④. 內容獲取類的方法
Class clz = Class.forName("Human");
----------
public static void method1_getFields() {
if (clz != null) {
System.out.println("getFields方法獲取字段:");
Field[] fields = clz.getFields();
for (Field field : fields) {
System.out.println(Modifier.toString(field.getModifiers()) + " " + field.getName());
}
}
}
----------
public static void method2_getDeclaredFields() {
if (clz != null) {
System.out.println("getDeclaredFields方法獲取字段:");
Field[] fields = clz.getDeclaredFields();
for (Field field : fields) {
System.out.println(Modifier.toString(field.getModifiers()) + " " + field.getName());
}
}
}
五、藉助反射實例化對象
Class clz = Class.forName("Human");
----------
public static void method1_InvolveConstructorAndNewInstance(Class clz) {
if (clz != null) {
System.out.println("調用構造函數並生成實例對象:");
try {
Constructor declaredConstructor = clz.getDeclaredConstructor(int.class);
Human newInstance = (Human) declaredConstructor.newInstance(98);
System.out.println(newInstance);
Method method = clz.getMethod("setName", String.class);
Method method2 = clz.getMethod("setAge", int.class);
method.invoke(newInstance, "ZhangYi");
method2.invoke(newInstance, 29);
System.out.println(newInstance);
} catch (NoSuchMethodException e) {
e.printStackTrace();
} catch (SecurityException e) {
e.printStackTrace();
} catch (InstantiationException e) {
e.printStackTrace();
} catch (IllegalAccessException e) {
e.printStackTrace();
} catch (IllegalArgumentException e) {
e.printStackTrace();
} catch (InvocationTargetException e) {
e.printStackTrace();
}
}