------Java培訓、Android培訓、iOS培訓、.Net培訓、期待與您交流! -------
JAVA反射機制是在運行狀態中,對於任意一個類,都能夠知道這個類的所有屬性和方法;對於任意一個對象,都能夠調用它的任意一個方法和屬性;這種動態獲取的信息以及動態調用對象的方法的功能稱爲java語言的反射機制。
注意:反射是在運行的時候進行的,不是在編譯的時候運行的。
1 反射的功能
在運行時判斷任意一個對象所屬的類;
在運行時構造任意一個類的對象;
在運行時判斷任意一個類所具有的成員變量和方法;
在運行時調用任意一個對象的方法;生成動態代理。
2 API簡介
— java.lang.Class; 代表一個類
— java.lang.reflect.Constructor; 代表類的構造方法
— java.lang.reflect.Field; 代表類的成員變量(成員變量也稱爲類的屬性)
— java.lang.reflect.Method; 代表類的方法
— java.lang.reflect.Array; 提供了動態創建數組,以及訪問數組的元素的靜態方法
注意:java中無論生成某個類的多少對象, 這些對象都會對應於同一個Class對象。
3 方法介紹
方法關鍵字 |
含義 |
getDeclaredMethods() |
獲取所有的方法 |
getReturnType() |
獲得方法的放回類型 |
getParameterTypes() |
獲得方法的傳入參數類型 |
getDeclaredMethod("方法名",參數類型.class,……) |
獲得特定的方法 |
|
|
構造方法關鍵字 |
含義 |
getDeclaredConstructors() |
獲取所有的構造方法 |
getDeclaredConstructor(參數類型.class,……) |
獲取特定的構造方法 |
|
|
父類和父接口 |
含義 |
getSuperclass() |
獲取某類的父類 |
getInterfaces() |
獲取某類實現的接口 |
4 獲取Class的三種方式
Class.forName("java.lang.String");
2)、調用某個類的class屬性來獲取該類對應的class對象,如
Class.forName("java.lang.String");
3)、調用某個對象的getClass方法。
String s = "aa";
Class<?> clazz = s.getClass();
5 生成對象
a)、先獲得Class對象,然後通過該Class對象的newInstance()方法直接生成即可:
newInstance()方法可以返回一個實例,但是構造方法要是沒有參數列表的,它相當於調用某個類的不帶參數的構造方法,但是如果在初始化對象的時候要傳參數,就要使用Constructor
Class<?> classType = String.class;
Object obj = classType.newInstance();
Class<?> classType = object.getClass();
Constructor cons = classType.getConstructor(new Class[]{});
Object obj = cons.newInstance(new Object[]{});
Class<?> classType = object.getClass();
Constructor cons = classType.getConstructor(new Class[]{String.class,int.class});
Object obj = cons.newInstance(new Object[]{"hello",3});
public class ReflectTester
{
//方法實現對Customer對象的拷貝操作
public Object copy(Object object) throws Exception
{
Class<?> classType = object.getClass();
/*Constructor cons = classType.getConstructor(new Class[]{});
Object obj = cons.newInstance(new Object[]{});
System.out.println(obj);
System.out.println("-----------");*/
//以上的兩行代碼等價於下面一行
//Object obj2 = classType.newInstance();
Constructor cons2 = classType.getConstructor(new Class[]{String.class, int.class});
Object obj2 = cons2.newInstance(new Object[]{"hello",3});
System.out.println(obj2);
return null;
}
public static void main(String[] args) throws Exception {
ReflectTester test = new ReflectTester();
test.copy(new Customer());
}
}
class Customer
{
private Long id;
private int age;
private String name;
public Customer()
{
}
public Customer(String name,int age)
{
this.name = name;
this.age= age;
}
public Long getId() {
return id;
}
public void setId(Long id) {
this.id = id;
}
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;
}
}
6 反射生成多維數組
import java.lang.reflect.Array;
/**
*
* 用反射構造一個多維數組
*
*/
public class ArrayTester2 {
public static void main(String[] args) {
int[] dims = new int[]{5,10,15};
//newInstance()方法的第二個參數是代表生成數組的維度,所以生成的數組維度爲5,10,15,長寬高
Object array = Array.newInstance(Integer.TYPE,dims);
//arrayObj是一個二維的數組
Object arrayObj = Array.get(array,3);
Class<?> classType = arrayObj.getClass().getComponentType();
//arrayObj是一個一維的數組
arrayObj = Array.get(arrayObj, 5);
Array.setInt(arrayObj, 10, 37);
int[][][] arrayCast = (int[][][])array;
System.out.println(arrayCast[3][5][10]);
}
}
反射訪問私有(private)的方法
例子1、獲取privete方法、
public class PrivateTest {
private String sayHello(String name)
{
return "hello" + name;
}
}
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
public class TestPrivate {
public static void main(String[] args) throws SecurityException, NoSuchMethodException, IllegalArgumentException, IllegalAccessException, InvocationTargetException {
PrivateTest p = new PrivateTest();
Class<?> classType = p.getClass();
Method method = classType.getDeclaredMethod("sayHello", new Class[]{String.class});
method.setAccessible(true); //壓制java的訪問控制檢查
String str = (String)method.invoke(p, new Object[]{"aaa"});
System.out.println(str);
}
}
public class Private2 {
private String name = "zhangsan";
public String getName()
{
return name;
}
}
/**
*
* 將Private2中的private屬性name的值變爲李四
*
*/
public class TestPrivate2{
public static void main(String[] args) throws Exception
{
Private2 p = new Private2();
Class<?> classType = p.getClass();
Field field = classType.getDeclaredField("name");
field.setAccessible(true);
field.set(p, "lisi");
System.out.println(p.getName());
}
}