記得之前寫了一篇json轉實體的文章
記得之前寫了一篇json轉實體的文章,里面就用到了java反射的文章,但是當時只是了解到反射這個知識點,並沒有深入的了解,寒假閑來無事覺頂深入整理一下java 反射的知識,一下都是個人學習反射的總結,不到之處,還望大神指點!!!
反射顧名思義就是和java編譯相反的過程,這里實現的效果就是通過類名來進行實例化類對象並對類進行操作。具體看下
獲取父類和所有的接口
-
首先我們的java類是可以繼承和實現多個接口的,那么我們如何通過java反射獲取java類的父類和接口呢?
-
首先我們在這里新建一個Annimal作為父類
public class Annimal {
private String AnnimalName;
public void eat(){
System.out.println("Annimal is eatting");
}
public void run(){
System.out.println("Annimal is running");
}
}
- 然后再新建一個Behaviour接口
public interface Behaviour {
public String haviour="test";
public void sayHello();
public void isAngury();
public void love();
}
- 現在讓我們新建一個Dog類並讓Dog類繼承Annimal類並實現Behavour這個接口
public class Dog extends Annimal implements Behaviour
- Dog源碼
public class Dog extends Annimal implements Behaviour{
private String dogName;
public void fuck(String name){
System.out.println("fuck To : "+name);
}
@Override
public void sayHello() {
// TODO Auto-generated method stub
System.out.println("Dog sayHello");
}
@Override
public void isAngury() {
// TODO Auto-generated method stub
System.out.println("Dog isAngury");
}
@Override
public void love() {
// TODO Auto-generated method stub
System.out.println("Dog love");
}
}
-
測試
-
下面我們開始進行測試,首先我們通過Class類來獲取類的class對象
Class<?> target=Class.forName("tom.change.Reflect.獲取父類和所有接口.Dog");
- 然后通過getSuperClass和getInterfaces這兩個方法就可以獲取到父類和所有的接口
//獲取Dog類的父類
Class<?> parent=target.getSuperclass();
//獲取該類繼承的所有類
Class<?> intefaces[]=target.getInterfaces();
- 最后看程序運行的效果圖
獲取所有的屬性(getDeclaredFields)
- 在Java類中出了類與類中關系,每個類還有具有特定的屬性,那么我們如何通過反射來獲取Java類中的屬性呢。下面我寫了一個user類,其中的屬性為
Dog類:
private String dogName;
- 那么下面我們來試試到底能不能獲取上面的幾個屬性。同樣通過類路徑獲取class對象
Class<?> clazz=Class.forName("tom.change.Reflect.獲取父類和所有接口.Dog");
- 然后通過class對象的getDeclaredFields方法獲取本地類的屬性,這個方法是無法獲取繼承父類和接口中的屬性,如果非要獲取你可以先通過該類獲取到父類,然后在去獲取父類的class 對象,在去獲取父類中屬性。
for (int i = 0; i < fields.length; i++) {
//獲取字段的修飾權限符
System.out.println(Modifier.toString(fields[i].getModifiers())+"@@@"+fields[i].getName());
}
-
這里說一下,獲取后用Field 來接受,這個類getModifiers是獲取該屬性的屬性的,私有還是公共還是保護的。
-
這里獲取字段后,通過Field的set方法就可以給屬性設置,不管屬性的對外狀態。前提是開啟權限
field.setAccessible(true);
field.set(object, "21131084");
- 這里的object是class的一個實例化對象
獲取類中的所有的方法(getMethods)
- 在上面我們已經獲取了類中所有的屬性,那么下面我們自然就是獲取類中的所有的方法了。同樣的步驟上面已經有了,這里不贅述了,只不過和上面的不同的地方就是獲取class對象后我們調用getMethods方法。
public void tom.change.Reflect.獲取父類和所有接口.Dog.fuck(java.lang.String)
public void tom.change.Reflect.獲取父類和所有接口.Dog.sayHello()
public void tom.change.Reflect.獲取父類和所有接口.Dog.love()
public void tom.change.Reflect.獲取父類和所有接口.Dog.isAngury()
public void tom.change.Reflect.獲取父類和所有接口.Annimal.run()
public void tom.change.Reflect.獲取父類和所有接口.Annimal.eat()
public final void java.lang.Object.wait(long,int) throws java.lang.InterruptedException
public final native void java.lang.Object.wait(long) throws java.lang.InterruptedException
public final void java.lang.Object.wait() throws java.lang.InterruptedException
public boolean java.lang.Object.equals(java.lang.Object)
public java.lang.String java.lang.Object.toString()
public native int java.lang.Object.hashCode()
public final native java.lang.Class java.lang.Object.getClass()
public final native void java.lang.Object.notify()
public final native void java.lang.Object.notifyAll()
- 大家有沒有疑問,為什么有一些莫名的方法出現,有些方法甚至我們的Dog和繼承類中都沒有出現過,這是怎么回事呢。首先getMethods獲取類本身的方法這是肯定的。繼承的類我們也是可以獲取的,這就解釋了為什么我們的獲取方法中有Annimal類中的方法,。那么后面那些Object類的方法是哪里來的呢,大家還記得嗎所有的類都是繼承Object類的。
類中方法的調用(getMethod)
- 在上面我們獲取了方法后,通過getMethod獲取指定的方法,該方法返回的是Method對象,然后通過Method里的invoke方法調用指定的方法。在調用的時候需要傳入class實力化對象,有參數的話我們還需要傳入參數。
public Object invoke(Object obj, Object... args)
-
源碼顯示,方法需要參數有多少這里就傳入多少,這里是通用的。
-
在通過getMethod獲取Method的時候我們需要傳入方法參數的類型
```
public Object invoke(Object obj, Object... args)
```
```
public Method getMethod(String name, Class<?>... parameterTypes)
```
獲取所有構造函數(getConstructors)
- Java類中最后應該還剩下構造函數了,既然是反射,我們就要將類反射的干干晶晶的。獲得class對象后我們通過getConstructors獲取構造函數,該方法返回的是Constructor集合。在Constructor類中getParameterTypes獲取構造函數中的參數,有個這個我們就可以自己進行類的構造了。
總結
- 到這里我們的反射已經完全可以操作一個類了。有人會問這有啥意思呢,在我們Javaweb中,哪些知名的框架源碼里必須有反射,通過反射我們能夠實現注解這個功能。當然注解還有其他知識,以后知道在介紹。再比如說我們將map與實體進行映射這里就需要反射區獲取Java Bean中的屬性並將map的值賦值。不管怎么樣,反射是我們Java的重要知識,學會它對自己以后的架構方面試有很大的幫助的。