Java-反射浅谈
這篇文章就是簡簡單單的介紹反射是什么、怎么用,面向初學者,老鳥勿噴。不涉及深層的原理。因為我不懂。
1.嘛是反射?
我在自己學習反射的時候,看到了一個說法很有意思——
有反就有正。我們先來看看“正射”是什么:
我們先定義一個Apple類,定義構造函數和屬性:
class Apple {private int age;public String name;public void setName(String name){this.name = name;}private Apple(){}public Apple(int age, String name){this.name = name;this.age = age;}public int getAge(){return age;}private void setAge(int age){this.age = age;}}然后在main函數中:
public static void main(String[] args) {Apple apple = new Apple(12, "青蘋果"); }這種我們最常用的建立對象的方式就是“正射”。來看看我們是怎么定義了這個對象的:
1.我們知道有一個類叫做Apple。
2.我們至少知道這個類的一個構造函數——至少要傳入一個int一個String。
我們事先知道了這個類和這個類的信息來創建對象,就是“正”。反射,就是在不知道這個類的具體信息的前提下,來創建對象、獲取類的方法屬性等等。一個是睜著眼一個是閉著眼,這么說你總能聽明白了吧。
2.怎么使用反射?
我們既然想操作一個類,就至少得知道他是誰吧,也就是說我們得獲取一個“類對象”。
類對象,用來創建其他對象的對象。
這里我們有三種方式來創建類對象:
1.Class cls=Class.forName(String string):其中參數是類的全路徑名。我們知道一個類的全路徑名時可以用這種方式。
class ReflectDemo {public static void main(String[] args){try{Class cls = Class.forName("Practice.Apple");} catch (ClassNotFoundException e)//這個方法會拋出ClassNotFoundException,找不到你指定的類就會異常。{e.printStackTrace();}} }2.xxx.class 適合編譯之前就知道class的情況。
class ReflectDemo {public static void main(String[] args){Class cls = Apple.class;} }3.使用對象的getClass()方法。
class ReflectDemo {Apple apple = new Apple();Class cls = apple.getClass(); }三種方式各有各的使用場景。
好了,我們現在已經拿到了這個類的類對象,下一步我們就可以用反射建立這個類的對象了。
建立類對象有兩種方式:
1.使用類對象的.newInstance()方法來獲取一個使用無參的構造函數初始化的對象。
try {Class cls = Class.forName("Practice.Apple");Apple apple = (Apple) cls.newInstance(); } catch (ClassNotFoundException | InstantiationException | IllegalAccessException e) //newInstance()拋出InstantiationException(如果此 Class 表示一個抽象類、接口、數組 // 類、基本類型或 void; 或者該類沒有 null 構造方法) //與IllegalAccessException(如果該類或其 null 構造方法是不可訪問的) {e.printStackTrace(); }我裝的是java11,newInstance()似乎是被要廢棄了?
2.通過Constructor對象的newInstance()方法。這個方式我們可以指定構造方法。
public static void main(String[] args) {try{Class cls = Class.forName("Practice.Apple");Constructor constructor = cls.getConstructor(int.class,String.class);Apple apple = (Apple) constructor.newInstance(13, "毒蘋果");} catch (ClassNotFoundException | NoSuchMethodException | InstantiationException | IllegalAccessException | InvocationTargetException e)//getConstructor()會拋出NoSuchMethodException。//newInstance()拋出InstantiationException,IllegalAccessException,//InvocationTargetException(當被調用的方法的內部拋出了異常而沒有被捕獲時,將由此異常接收){e.printStackTrace();} }在getConstructor時我們要指定參數類型。注意是class類型。
對象有了,我們現在需要調用對象的屬性or方法時怎么調用呢?
1.獲取對象的屬性
Field[] fields = cls.getFields();//cls是我們的類對象 for (Field field : fields) {System.out.println(field); }getFields可以獲取到所有除private的屬性。若獲取指定屬性可以使用getField(String name)。
獲取所有包括private的屬性我們可以使用getDeclaredFields()。
2.獲取對象的方法
Method[] methods = cls.getMethods(); for (Method method : methods) {System.out.println(method); }道理同上,getDeclaredMethods()可以獲取所有方法。
有了這些,我們就可以對對象進行操作了。
3.執行對象的方法
Method method = cls.getMethod("setAge", int.class); method.invoke(apple,10); System.out.println(apple.getAge());分析代碼:
首先我們指定了方法名來獲取指定的方法(第一個參數是方法名,第二個是方法的參數的所屬類。這里注意,若參數為int型的,要么寫int.class,要么寫Integer。Integer.class是不行的。)
接著我們調用方法的invoke(invoke,執行之意)。第一個參數是我們想在哪個對象上調用方法,第二個是參數值。(若方法為私有方法,我們雖然可以獲取到但是不能執行。若想執行,則需要在執行前調用method.setAccessible(true))
?
?有了以上的知識,你就已經了解了最基本的反射知識并且能靈活使用反射了。其他的我以后補充。希望能幫助到初學者理解。
?
轉載于:https://www.cnblogs.com/KangYh/p/10633226.html
總結