java反射機(jī)制是在運(yùn)行狀態(tài)中,對于任意一個(gè)類,都能夠知道這個(gè)類的所有屬性和方法;對于任意一個(gè)對象,都能夠調(diào)用它的任意一個(gè)方法和屬性;這種動(dòng)態(tài)獲取的信息以及動(dòng)態(tài)調(diào)用對象的方法的功能稱為java語言的反射機(jī)制。
注意:反射是在運(yùn)行的時(shí)候進(jìn)行的,不是在編譯的時(shí)候運(yùn)行的。
反射的功能
Java反射機(jī)制主要提供了以下功能:
API簡介
在這里先看一下sun為我們提供了那些反射機(jī)制中的類:
— java.lang.Class; 代表一個(gè)類
— java.lang.reflect.Constructor; 代表類的構(gòu)造方法
— java.lang.reflect.Field; 代表類的成員變量(成員變量也稱為類的屬性)
— java.lang.reflect.Method; 代表類的方法
— java.lang.reflect.Array; 提供了動(dòng)態(tài)創(chuàng)建數(shù)組,以及訪問數(shù)組的元素的靜態(tài)方法
注意:java中無論生成某個(gè)類的多少對象, 這些對象都會(huì)對應(yīng)于同一個(gè)Class對象。
方法介紹
方法關(guān)鍵字 | 含義 |
getDeclaredMethods() | 獲取所有的方法 |
getReturnType() | 獲得方法的放回類型 |
getParameterTypes() | 獲得方法的傳入?yún)?shù)類型 |
getDeclaredMethod("方法名",參數(shù)類型.class,……) | 獲得特定的方法 |
|
|
構(gòu)造方法關(guān)鍵字 | 含義 |
getDeclaredConstructors() | 獲取所有的構(gòu)造方法 |
getDeclaredConstructor(參數(shù)類型.class,……) | 獲取特定的構(gòu)造方法 |
|
|
父類和父接口 | 含義 |
getSuperclass() | 獲取某類的父類 |
getInterfaces() | 獲取某類實(shí)現(xiàn)的接口 |
獲取Class的三種方式
1)、使用Class類的forName(String className)靜態(tài)方法。改方法需要傳入字符串參數(shù),改字符串參數(shù)的值是某個(gè)類的全限定類名(必須添加完整的包名)。
Class.forName("java.lang.String");
2)、調(diào)用某個(gè)類的class屬性來獲取該類對應(yīng)的class對象,如
String.class
3)、調(diào)用某個(gè)對象的getClass方法。
String s = "aa";Class<?> clazz = s.getClass();生成對象
1)、通過不帶參數(shù)的構(gòu)造方法生成對象有兩種方法
a)、先獲得Class對象,然后通過該Class對象的newInstance()方法直接生成即可:
newInstance()方法可以返回一個(gè)實(shí)例,但是構(gòu)造方法要是沒有參數(shù)列表的,它相當(dāng)于調(diào)用某個(gè)類的不帶參數(shù)的構(gòu)造方法,但是如果在初始化對象的時(shí)候要傳參數(shù),就要使用Constructor
Class<?> classType = String.class;
Object obj = classType.newInstance();
b)、先獲得Class對象,然后通過該對象獲得相應(yīng)的Constructor對象,再通過該Constructor對象的newInstance()方法生成:
Class<?> classType = object.getClass();Constructor cons = classType.getConstructor(new Class[]{});Object obj = cons.newInstance(new Object[]{});
2)、若想通過類的帶參數(shù)的構(gòu)造方法生成對象,只能使用下面一種方式:
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{ //方法實(shí)現(xiàn)對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("-----------");*/ //以上的兩行代碼等價(jià)于下面一行 //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; } }
相對復(fù)雜的例子
import java.lang.reflect.Constructor;import java.lang.reflect.Field;import java.lang.reflect.Method;public class ReflectTester{ //方法實(shí)現(xiàn)對Customer對象的拷貝操作 public Object copy(Object object) throws Exception { Class<?> classType = object.getClass(); Object ObjectCopy = classType.getConstructor(new Class[]{}).newInstance(new Object[]{}); //獲得成員變量 Field[] fields = classType.getDeclaredFields(); for(Field field : fields) { String name = field.getName(); String firstLetter = name.substring(0,1).toUpperCase(); //將屬性的首字母轉(zhuǎn)換為大寫 String getMethodName = "get" + firstLetter + name.substring(1); String setMethodName = "set" + firstLetter + name.substring(1); Method getMethod = classType.getMethod(getMethodName, new Class[]{}); Method setMethod = classType.getMethod(setMethodName, new Class[]{field.getType()}); Object value = getMethod.invoke(object, new Object[]{}); setMethod.invoke(ObjectCopy, new Object[]{value}); } return ObjectCopy; } public static void main(String[] args) throws Exception { Customer customer = new Customer("tom",20); customer.setId(1L); ReflectTester test = new ReflectTester(); Customer cus = (Customer)test.copy(customer); System.out.println(cus.getAge()+","+cus.getName()+","+cus.getId()); } }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; } }
注意:Integer.TYPE返回的是int,而Integer.class返回的是Integer類所對應(yīng)的Class對象。
反射生成多維數(shù)組
import java.lang.reflect.Array;/** * * 用反射構(gòu)造一個(gè)多維數(shù)組 * */public class ArrayTester2 { public static void main(String[] args) { int[] dims = new int[]{5,10,15}; //newInstance()方法的第二個(gè)參數(shù)是代表生成數(shù)組的維度,所以生成的數(shù)組維度為5,10,15,長寬高 Object array = Array.newInstance(Integer.TYPE,dims); //arrayObj是一個(gè)二維的數(shù)組 Object arrayObj = Array.get(array,3); Class<?> classType = arrayObj.getClass().getComponentType(); //arrayObj是一個(gè)一維的數(shù)組 arrayObj = Array.get(arrayObj, 5); Array.setInt(arrayObj, 10, 37); int[][][] arrayCast = (int[][][])array; System.out.println(arrayCast[3][5][10]); }}
反射訪問私有(private)的方法
private 限制的方法沒有辦法在另外的類中使用,但可以使用反射進(jìn)行使用。而getMethod()方法只能獲取public的方法。如果要使用private的方法就要使用 getDeclaredMethod()方法。
例子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); } }
例子2、改變private的屬性
public class Private2 { private String name = "zhangsan"; public String getName() { return name; }}
/** * * 將Private2中的private屬性name的值變?yōu)槔钏?* */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()); } }
致謝:感謝您的閱讀!
新聞熱點(diǎn)
疑難解答
圖片精選
網(wǎng)友關(guān)注