還在那裏硬編碼嗎?試試反射 | 打開新世界的大門

這是我參與更文挑戰的第27天,活動詳情查看: 更文挑戰java

記得以前寫了一篇json轉實體的文章web

記得以前寫了一篇json轉實體的文章,裏面就用到了java反射的文章,可是當時只是瞭解到反射這個知識點,並無深刻的瞭解,寒假閒來無事覺頂深刻整理一下java 反射的知識,一下都是我的學習反射的總結,不到之處,還望大神指點!!!面試

反射顧名思義就是和java編譯相反的過程,這裏實現的效果就是經過類名來進行實例化類對象並對類進行操做。具體看下json

獲取父類和全部的接口

  • 首先咱們的java類是能夠繼承和實現多個接口的,那麼咱們如何經過java反射獲取java類的父類和接口呢?markdown

  • 首先咱們在這裏新建一個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對象ide

Class<?> target=Class.forName("tom.change.Reflect.獲取父類和全部接口.Dog");


複製代碼
  • 而後經過getSuperClass和getInterfaces這兩個方法就能夠獲取到父類和全部的接口
//獲取Dog類的父類
Class<?> parent=target.getSuperclass();
//獲取該類繼承的全部類
Class<?> intefaces[]=target.getInterfaces();
複製代碼
  • 最後看程序運行的效果圖

這裏寫圖片描述

獲取全部的屬性(getDeclaredFields)

  • 在Java類中出了類與類中關係,每一個類還有具備特定的屬性,那麼咱們如何經過反射來獲取Java類中的屬性呢。下面我寫了一個user類,其中的屬性爲

Dog類:svn

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的重要知識,學會它對本身之後的架構方面試有很大的幫助的。

源碼下載

相關文章
相關標籤/搜索