<span style="font-family: Arial, Helvetica, sans-serif; background-color: rgb(255, 255, 255);">我們知道大多數腳本語言都是動態語言,例如Perl、Python、ruby之類的。他們都有用一共同的特點數據類型可在程序運行時動態的改變其類型、結構和屬性。基本都是解釋型語言,而JAVA在程序運行前需要通過編譯器先進行源碼編譯(編譯成字節碼),然後有jvm加載運行。同樣java也引入動態加載的相關機制----反射機制。從而實現動態加載類對象,提高程序設計的靈活性。</span>
1.java的反射機制:
反射機制允許程序在運行狀態中知道類對象的所有方法和屬性。對於任意對象都可以調用其任意方法。
java反射機制相關的API在JDK的java.lang.reflect包中。
Member接口 | 該接口可以獲取有關類成員(域或者方法)後者構造函數的信息。 |
AccessibleObject類 |
該類是域(field)對象、方法(method)對象、構造函數(constructor)對象的基礎類。 它提供了將反射的對象標記爲在使用時取消默認 Java 語言訪問控制檢查的能力。 |
Array類 | 該類提供動態地生成和訪問JAVA數組的方法。 |
Constructor類 | 提供一個類的構造函數的信息以及訪問類的構造函數的接口。 |
Field類 | 提供一個類的域的信息以及訪問類的域的接口。 |
Method類 | 提供一個類的方法的信息以及訪問類的方法的接口。 |
Modifier類 | 提供了 static 方法和常量,對類和成員訪問修飾符進行解碼。 |
Proxy類 |
提供動態地生成代理類和類實例的靜態方法。 |
2.Class對象的獲取(Class類是一個特殊的類對象,它本身也是一個對象):
1>.通過類對象的.getClass()方法:
Class class1 = [對象].getClass();
2>.通過Class的靜態方法.forName()獲取:
Class class2 = Class.forName();
3>.通過類的.class屬性獲取:
Class class3 = Boolean.class;
3.獲取fields
Java的Class中提供幾個方法來獲取類中聲明的字段。方法如下:
public FieldgetField()、 public Field[] getFields()、 public Field getDeclaredField(String name)、public Field[] getDeclareds().
4.獲取Class的Method
同獲取聲明字段一樣Class同樣提供瞭如下方法:
public Method getMethod(String name, Class<?>, parameterTypes)、getMethods()、public Method getDeclaredMethod(String name, Class<?> ... parameterTypes)、public Method[] getDeclaredMethod().
5.獲取構造函數:
同樣使用 public Constructor getConstructor(Class<T>...parameterTypes ).等方法可以獲取到類的公共構造方法。方法詳情請API中自行查找。
6.程序實例:
1>.user Class Code:
public class User {
public int age;
private String fristName;
private String lastName;
public User(){}
public User(int age, String fristName, String lastName) {
this.age = age;
this.fristName = fristName;
this.lastName = lastName;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
public String getFristName() {
return fristName;
}
public void setFristName(String fristName) {
this.fristName = fristName;
}
public String getLastName() {
return lastName;
}
public void setLastName(String lastName) {
this.lastName = lastName;
}
}
2> TestReflest Class Code:
import java.lang.reflect.Constructor;
import java.lang.reflect.Field;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
public class TestReflect {
/**
* @param args
* @throws NoSuchFieldException
*/
public static void main(String[] args) throws NoSuchFieldException {
// TODO Auto-generated method stub
User user = new User();
//獲取類類型
Class class1 = User.class;
Class class2 = user.getClass();
try {
Class class3 = Class.forName("User");
} catch (ClassNotFoundException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
//獲取field
try {
Field [] fields = class1.getFields();
System.out.println(fields.length);
Field ageField = class1.getField("age");
System.out.println(ageField.toString());
} catch (SecurityException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
System.out.println();
//獲取方法
Method[] methods = class1.getMethods();
for (Method m : methods)
{
System.out.println(m);
}
System.out.println();
Constructor[] constructors = class1.getConstructors();
for(Constructor c: constructors) {
System.out.println(c);
}
System.out.println();
//創建對象
try {
User user2 = (User) class1.newInstance();
System.out.println(user2);
System.out.println();
Constructor constructor = class1.getConstructor();
User user3 = (User) constructor.newInstance();
System.out.println(user3);
} catch (InstantiationException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (IllegalAccessException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (NoSuchMethodException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (SecurityException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (IllegalArgumentException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (InvocationTargetException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
System.out.println();
//調用方法
try {
Method setAge = class1.getMethod("setAge", int.class);
setAge.invoke(user, 10);
System.out.println(user.getAge());
} catch (NoSuchMethodException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (SecurityException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (IllegalAccessException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (IllegalArgumentException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (InvocationTargetException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
代碼寫的比較粗狂簡單,通過調用上述的一些方法完成了class、field、method、constructor等類信息。同時通過調用invoke() 和newInstance()等方法完成方法調用和類對象的創建。
反射調用的性能問題:
* Created by cike on 16/6/28.
*/
public class User {
private String name;
private int age;
public User() {}
public User(String name, int age) {
this.name = name;
this.age = age;
}
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 String playing() {
StringBuffer stringBuffer = new StringBuffer();
for (int i = 0; i < 1000; i++) {
stringBuffer.append(i);
}
return stringBuffer.toString();
}
}
測試main方法:
public static void main(String[] args) {
Class userClass = User.class;
try {
Method method = userClass.getMethod("playing", null);
User user = (User) userClass.newInstance();
long start = System.currentTimeMillis();
System.out.println(method.invoke(user,null));
System.out.println("反射調用方法耗時:" + String.valueOf(System.currentTimeMillis() - start));
User user1 = new User();
long start1 = System.currentTimeMillis();
System.out.println(user1.playing());
System.out.println("常規調用方法耗時:" + String.valueOf(System.currentTimeMillis() - start1));
} catch (NoSuchMethodException e) {
e.printStackTrace();
} catch (InstantiationException e) {
e.printStackTrace();
} catch (IllegalAccessException e) {
e.printStackTrace();
} catch (InvocationTargetException e) {
e.printStackTrace();
}
}
多次運行代碼測試結果如下: