1、反射java
反射:Java反射機制是在運行狀態中,對於任意一個類,都可以知道這個類的全部屬性和方法;對於任意一個對象,都可以調用它的任意一個方法和屬性;這種動態獲取的信息以及動態調用對象的方法的功能稱爲Java語言的反射機制。linux
要想解剖一個類,必須先要獲取到該類的字節碼文件對象。而解剖使用的就是Class類中的方法.因此先要獲取到每個字節碼文件對應的Class類型的對象。對於反射的操做實際上就是經過Class對象獲取:數組
*a、java.lang.reflect.Field:提供有關類或接口的單個字段的信息,以及對它的動態訪問權限。反射的字段多是一個類(靜態)字段或實例字段。操做類的成員變量。
*b、java.lang.reflect.Constructor<T>:操做類的夠造函數。
*c、java.lang.reflect.Method:操做類的方法。ide
在學習反射基礎前先建立一個Person對象做爲實例:函數
package com.linuxidc.org.base.relfect;學習
public class Person {
private String name;
int age;
public String address;this
public Person() {
}對象
private Person(String name) {
this.name = name;
}繼承
Person(String name, int age) {
this.name = name;
this.age = age;
}接口
public Person(String name, int age, String address) {
this.name = name;
this.age = age;
this.address = address;
}
public void show() {
System.out.println("show");
}
public void method(String s) {
System.out.println("method " + s);
}
public String getString(String s, int i) {
return s + "---" + i;
}
private void function() {
System.out.println("function");
}
@Override
public String toString() {
return "Person [name=" + name + ", age=" + age + ", address=" + address
+ "]";
}
}
2、獲取類的Class對象
public static void getClassObject() throws ClassNotFoundException{
//方式一:Object的getClass()方法
Person person1=new Person();
Person person2=new Person();
Class c1=person1.getClass();
Class c2=person2.getClass();
System.out.println(person1==person2);//false
System.out.println(c1==c2);//true 無論JVM內存中有多少個對象,對於字節碼文件來講只有一份
//方式二:數據類型的靜態class屬性
Class c3=Person.class;
System.out.println(c1==c3);//true
//方式三:Class 類的靜態方法
//public static Class<?> forName(String className)throws ClassNotFoundException
Class c4=Class.forName("com.linuxidc.org.base.relfect.Person");
System.out.println(c1==c4);//true
}
3、java.lang.reflect.Constructor<T>:對象並使用Constructor類。
一、獲取Constructor對象
//獲取Class 對象所表示的類的構造方法
public static void getConstructorTest() throws Exception{
Class c4=Class.forName("com.linuxidc.org.base.relfect.Person");
//一、獲取Class 對象所表示的類全部公共構造方法
//public Constructor<?>[] getConstructors() throws SecurityException
Constructor [] cs=c4.getConstructors();
//二、獲取Class 對象所表示的類全部構造方法
//public Constructor<?>[] getDeclaredConstructors() throws SecurityException
Constructor[] cs2 =c4.getDeclaredConstructors();
//三、獲取Class對象所表示類的指定指定公共構造方法, parameterTypes 參數是 Class 對象的一個數組 ,是指定數據類型的字節碼
//public Constructor<T> getConstructor(Class<?>... parameterTypes);
Constructor cs3=c4.getConstructor();//獲取公共的無參構造方法的Constructor對象
//獲取 該 構造函數 public Person(String name, int age, String address)
Constructor cs4=c4.getConstructor(String.class,int.class,String.class);
//四、獲取Clss對象所表示類指定的構造範法官 parameterTypes 參數是 Class 對象的一個數組,它按聲明順序標識構造方法的形參類型的字節碼。
//public Constructor<T> getDeclaredConstructor(Class<?>... parameterTypes);
//獲取該構造 函數 private Person(String name) 的Constructor對象
Constructor cs5=c4.getDeclaredConstructor(String.class);
}
二、經過 Constructor 對象建立Class對象所表示類的實例
public static void createObject() throws Exception{
Class c4=Class.forName("com.linuxidc.org.base.relfect.Person");
//使用此 Constructor 對象表示的構造方法來建立該構造方法的聲明類的新實例,並用指定的初始化參數初始化該實例
//public T newInstance(Object... initargs);
// Person person=new Person()
Constructor cs3=c4.getConstructor();//獲取公共的無參構造方法的Constructor對象
Object obj=cs3.newInstance();
//Person person=new Person("linuxidc", 21, "北京");
Constructor cs4=c4.getConstructor(String.class,int.class,String.class);
Object obj1=cs4.newInstance("linuxidc",21,"北京");
System.out.println(obj1);//Person [name=linuxidc, age=21, address=北京]
//實例化一個私有的構造函數 private Person(String name)
//控制java的訪問檢查
//public void setAccessible(boolean flag)
//將此對象的 accessible 標誌設置爲指示的布爾值。值爲 true 則指示反射的對象在使用時應該取消 Java 語言訪問檢查。
//值爲 false 則指示反射的對象應該實施 Java 語言訪問檢查。
Constructor cs5=c4.getDeclaredConstructor(String.class);
cs5.setAccessible(true);
Object obj2=cs5.newInstance("張三丰");
System.out.println(obj2);//Person [name=張三丰, age=0, address=null]
}
4、java.lang.reflect.Field
一、獲取Field對象
//獲取Class類的Field對象
public static void getFieldTest() throws Exception{
Class cs=Class.forName("com.linuxidc.org.base.relfect.Person");
//一、public Field[] getFields() throws SecurityException
//獲取Class 對象所表示的類或接口的全部可訪問公共(public修飾的)字段
Field [] fs=cs.getFields();
//二、public Field[] getDeclaredFields() throws SecurityException
// 獲取Class 對象所表示的類或接口所聲明的全部字段。包括公共、保護、默認(包)訪問和私有字段,但不包括繼承的字段
Field [] fs1=cs.getDeclaredFields();
//三、public Field getField(String name)throws NoSuchFieldException, SecurityException;
//獲取Class 對象所表示的類或接口的指定公共成員(public修飾)字段。name 參數是一個 String,用於指定所需字段的簡稱
Field fs2=cs.getField("address");
//public Field getDeclaredField(String name) throws NoSuchFieldException,SecurityException
//獲取 Class 對象所表示的類或接口的指定已聲明字段。name 參數是一個 String,它指定所需字段的簡稱
Field fs3=cs.getDeclaredField("name");
System.out.println(fs3);
}
二、經過Field對象對指定類屬性賦值
//使用 Field對象
public static void createVarValue() throws Exception{
Class cs=Class.forName("com.linuxidc.org.base.relfect.Person");
Object obj=cs.getConstructor().newInstance();
Field addressField=cs.getField("address");
//public void set(Object obj, Object value);
//將指定對象變量上此 Field 對象表示的字段設置爲指定的新值。若是底層字段的類型爲基本類型,則對新值進行自動解包
//obj - 應該修改其字段的對象 value - 正被修改的 obj 的字段的新值
addressField.set(obj, "北京");
System.out.println(obj); //Person [name=null, age=0, address=北京]
//對非public修飾的變量操做
Field nameField=cs.getDeclaredField("name");
//控制java的訪問檢查
nameField.setAccessible(true);
nameField.set(obj, "張三丰");
System.out.println(obj);//Person [name=張三丰, age=0, address=北京]
}
5、java.lang.reflect.Method
一、獲取Method對象
//獲取Method對象
public static void getMethodTest() throws Exception{
Class cs=Class.forName("com.linuxidc.org.base.relfect.Person");
//一、public Method[] getMethods() throws SecurityException
//獲取Class 對象所表示的類或接口(包括那些由該類或接口聲明的以及從超類和超接口繼承的那些的類或接口)的公共 member 方法。
Method [] m1=cs.getMethods();
//二、public Method[] getDeclaredMethods() throws SecurityException
//獲取Class 對象表示的類或接口聲明的全部方法,包括公共、保護、默認(包)訪問和私有方法,但不包括繼承的方法
Method [] m2=cs.getDeclaredMethods();
//三、public Method getMethod(String name, Class<?>... parameterTypes)throws NoSuchMethodException, SecurityException;
// 獲取Class 對象所表示的類或接口的指定公共成員方法。name 參數是一個 String,用於指定所需方法的簡稱。parameterTypes 參數是按聲明順序標識該方法形參類型的 Class 對象的一個數組
Method m3=cs.getMethod("show");//無參的方法
Method m4=cs.getMethod("method",String.class);//帶參的方法
//public Method getDeclaredMethod(String name, Class<?>... parameterTypes)throws NoSuchMethodException,SecurityException
// Class 對象所表示的類或接口的指定已聲明方法。name 參數是一個 String,它指定所需方法的簡稱,parameterTypes 參數是 Class 對象的一個數組
Method m5=cs.getDeclaredMethod("function");//無參的方法
System.out.println(m5);
}
二、經過Method對象調用指定類的方法
// Method對象的使用 public static void createMethod() throws Exception{ Class cs=Class.forName("com.linuxidc.org.base.relfect.Person"); Object obj=cs.getConstructor().newInstance(); Method m3=cs.getMethod("show");//無參的方法 //public Object invoke(Object obj,Object... args) //對帶有指定參數的指定對象調用由此 Method 對象表示的底層方法 obj - 從中調用底層方法的對象 args - 用於方法調用的參數 m3.invoke(obj); //對帶參方法的操做 Method m4=cs.getMethod("method",String.class);//帶參的方法 m4.invoke(obj,"北京"); //對有返回值得方法操做 Method m6=cs.getMethod("getString",String.class,int.class);//帶參的方法 Object str=m6.invoke(obj,"北京",200); System.out.println(str); //對私有無參方法的操做 Method m5=cs.getDeclaredMethod("function"); m5.setAccessible(true); m5.invoke(obj); }