1. 程式人生 > >你知道的反射是這樣嗎?(二)

你知道的反射是這樣嗎?(二)

在上一篇文章,已經講到了反射的一些基本概念以及基本的使用,也介紹到了一些反射中常用的方法以及區別,今天我們再次進入反射的第二期,更進一步的瞭解一下反射。 我們在使用反射去建立一個類的例項的時候一般都是使用: ```java Class clazz = Test.class; Constructor constructor = clazz.getDeclaredConstructor(); constructor.setAccessible(true); Object obj = constructor.newInstance(); ``` 這種寫法稍顯繁雜,我們可以通過另一種便捷的方式去實現: ```java Class clazz = Test.class; Test instance1 = clazz.newInstance(); ``` 這種方式雖然不直接使用構造器物件,但是這種方式是有缺陷的: 1、如果需要例項化的Test類無參構造方法使用private修飾則會出現java.lang.IllegalAccessException異常,因為沒有許可權訪問。 2、如果我們沒有無參構造方法,因為newInstance()是不需要傳參的,在執行時newInstance()只會尋找公共的、無參的構造方法。 注意:在這裡我們一定要區分newInstance這個方法,這裡的newInstance方法是Class下的一個方法,與Constructor中的newInstance方法是不一樣的。 Method物件的使用 如果我們需要獲取某一個類中的所有Method物件,我們還是需要通過位元組碼物件去操作。比如我們現在需要和獲取到Test2類中的所有Method物件。 ```java public class Test2 { private String name; private Integer age; public String getName() { return name; } public void setName(String name) { this.name = name; } public Integer getAge() { return age; } public void setAge(Integer age) { this.age = age; } @Override public String toString() { return "Test2{" + "name='" + name + '\'' + ", age=" + age + '}'; } private void test(){ System.out.println("I'm test method"); } } ``` 我們在Test2中提供了get、set方法,也重寫了toString方法,並且也建立了一個私有的test方法,然後再通過使用getDeclaredMethods()方法獲取到了Test2中所有的Method物件。 ```java Class clazz = Test2.class; Method[] declaredMethods = clazz.getDeclaredMethods(); for (Method declaredMethod : declaredMethods) { System.out.println(declaredMethod); } ``` ![](https://img2020.cnblogs.com/blog/1157447/202009/1157447-20200914104806177-1172438451.png) 但是如果使用getMethods()這個時候我們就不能獲取到私有Method物件了,如果我們需要獲取指定的方法則可以使用getMethod(name)或者getDeclaredMethod(name),至於他們兩個的區別就不再贅述。 那麼又有一個問題出現了,Java是有多型特性的,如果我們有某一個方法進行了方法過載,那麼這個時候我們如果根據方法名稱去獲取不就有問題了嗎?不用急,我們可以通過getMethod(name,paramClassType)或者getDeclaredMethod(name,paramClassType)獲取到我們指定的過載方法。如: ```java public class Test{ private void test(){ System.out.println("I'm test method"); } private void test(String name, Integer age){ System.out.println("I'm test method:"+name+age+"歲"); } } // 通過此方式便可以獲取到我們指定的過載方法 Method test = clazz.getDeclaredMethod("test", String.class, Integer.class); ``` 獲取到指定的方法後我們要如何使用? 我們一般在使用一個方法的時候都是obj.method(param);但是如果我們需要用反射進行呼叫則需要,method.invoke(obj,param); ```java Class clazz = Test2.class; Method test = clazz.getDeclaredMethod("test", String.class, Integer.class); test.setAccessible(true); test.invoke(clazz.newInstance(), "zhangsan", 12); ``` ![](https://img2020.cnblogs.com/blog/1157447/202009/1157447-20200914104853422-499392639.png) #### Field物件如何使用呢? 這裡其實與Class、Method物件都是大同小異了,都是同樣的玩法。 ```java Class clazz = Test2.class; Field field1 = clazz.getDeclaredField("name"); Field field2 = clazz.getDeclaredField("age"); Test2 test2 = clazz.newInstance(); field1.setAccessible(true); field1.set(test2, "張三"); field2.setAccessible(true); field2.set(test2, 12); System.out.println(test2); ``` ![](https://img2020.cnblogs.com/blog/1157447/202009/1157447-20200914104926712-597528037.png) 至此我們的反射也就已經整體結束了,後續將繼續努力給大家帶來一些易懂的Java知識。如果你有興趣,可以關注我後續將帶來更多精彩的文章。 ![](https://img2020.cnblogs.com/blog/1157447/202009/1157447-20200914105004448-19331785