摘要:不包含父類或父接口的方法返回,根據方法名和類型獲取。類或接口的及父類父接口公共成員方法。是的返回方法名,不包括修飾符,參數和返回值。打印打印拋出因為的訪問權限為拋出,因為是父類的方法。
反射機制呢就是在程序運行時,動態的獲取類(class),類的方法(method)屬性(field)等。主要的注意點就是程序運行時動態的獲取。
這里主要是從代碼的角度來講解Java反射。在使用中我們用的較多的幾個類有Class,Method,Field,Constructor,Annotation等。
下面我們分別介紹下。
獲取class對象有如下三種方式:
cat.getClass
Cat.class
Class.forName("xyz.magicer.Cat")
//方式1 調用對象的getClass()方式,該方法屬于Object類 Class extends Cat> aClass = cat.getClass(); //方式2 直接類.class獲取。 ClasscatClass = Cat.class; //方式3 通過Class類的靜態方法forName獲取,參數為想要獲取的類的全名(含包名,不然會報ClassNotFoundException) try { Class> cat2 = Class.forName("xyz.magicer.Cat"); } catch (ClassNotFoundException e) { e.printStackTrace(); }
在使用中根據實際情況選擇,獲取Class對象是我們使用反射的第一步。不過還是很簡單的。獲取了Class對象后,怎么創建一個實體呢?catClass.newInstance()
不過改方法會拋出兩個異常:InstantiationException和IllegalAccessException
InstantiationException :當該Class不能被實例化的時候拋出該異常,例如,為抽象類、接口、數組類、基本類、Void等時。
IllegalAccessException:當無參構造為私有時
還有一種創建實體的方式是使用Constructor,在下邊在介紹。
Method 獲取Method類或接口的方法對應這Method這個類。我們通過Class對象來獲取。主要方法有
getMethods(): 返回Method[] 返回所有public的方法。包含父類或父接口的方法。
getDeclaredMethods(): 返回Method[] 返回所有的方法。包括 private public default 和 protected的。不包含父類或父接口的方法
getMethod(String name, Class>... parameterTypes) : 返回Method, 根據方法名和類型獲取Method。類或接口的及父類父接口公共成員方法。
getDeclaredMethod(String name, Class>... parameterTypes): 返回Method。根據方法名和類型返回Method。類和接口的所有方法。
//sleep是private的 Method[] methods = catClass.getMethods(); for (Method method : methods) { //method.getName() 返回方法名,不包括修飾符,參數和返回值。 System.out.printf(method.getName()+" "); } // 打印toString getName setName setColor eat eat getAge setAge getColor wait wait wait equals hashCode getClass notify notifyAll System.out.println(); Method[] declaredMethods = catClass.getDeclaredMethods(); for (Method declaredMethod : declaredMethods) { System.out.printf(declaredMethod.getName()+" "); } //打印 toString getName setName sleep setColor eat eat getAge setAge getColor //拋出NoSuchMethodException 因為sleep的訪問權限為private //Method sleep1 = catClass.getMethod("sleep", null); Method hashCode = catClass.getMethod("hashCode", null); //拋出NoSuchMethodException,因為hashCode是父類的方法。 //Method hashCode1 = catClass.getDeclaredMethod("hashCode", null); Method eat2 = catClass.getMethod("eat",null); Method sleep1 = catClass.getDeclaredMethod("sleep", null);
通過上面的代碼我們能看到,getMethods()可以獲取父類的方法,但是不能獲取私有方法,而getDeclaredMethod()方法不可以獲取父類的方法,但是可以獲取私有的方法。getMethod也是一樣,可以獲取父類父接口方法,但是無法獲取私有方法,而getDeclaredMethod可以獲取私有方法不能獲取父類父接口方法。
而帶s和不帶s的區別是帶s返回值為Method[],不帶返回的是Method。
既然我們獲取到了方法(Method)當然是想調用它,那么怎么調用呢?Method有個方法invoke(Object obj, Object... args).
invoke接收兩個參數,第一個是調用該方法的實體,第二個是方法的參數。參數類型多個時順序要跟方法參數相同。
Method eat1 = catClass.getMethod("eat"); eat1.invoke(catInstance,null); //打印:我只吃小魚干。 Method eat = catClass.getDeclaredMethod("eat"); eat.invoke(catInstance,null); //打印: 我只吃小魚干。 Method sleep = catClass.getDeclaredMethod("sleep"); //IllegalAccessException sleep.invoke(catInstance,null);
我們會發現當私有方法invoke調用時會拋出IllegalAccessException,不是可以獲取么為什么不能調用?因為方法有權限修飾符,我們需要設置成我們可以調用的。如下:
sleep.setAccessible(true); sleep.invoke(catInstance,null);
在調用前設置為可以調用就解決了。
在前面我們接觸到了兩個Method類的方法了(getName,和invoke)。
getModifiers(): 返回方法修飾符
getAnnotations(): 可以獲取父類的注解
getDeclaredAnnotations(): 不可以返回父類的注解
getAnnotation(Class
getDeclaredAnnotation(Class
getParameters(): 返回Parameter[] (java1.8加入)
Field獲取Field對象的方式跟Method一樣,用法和規律都一樣。無非是現在方法改為getFields()、getDeclaredFields()、getField(String)、getDeclaredField(String)。
設置Field可以通過set方法來設置值 public void set(Object obj, Object value) 每種基本數據類型都有的setxxx()方法。
//name 為私有 Field name = catClass.getDeclaredField("name"); name.setAccessible(true); name.set(cat,"啦啦啦"); System.out.println(" "+cat.toString());
在使用反射設置屬性的時候一定要注意,可能在代碼中用到該屬性的地方較多,改變了值之后引起一些意想不到的效果。
Constructor獲取Constructor對象的方式跟Field和Method一樣。有四個方法:
getConstructors(),getDeclaredConstructors,getConstructor(Class>... parameterTypes), getDeclaredConstructor(Class>... parameterTypes)。
得到了Constructor對象后我們就可以調用newInstance(Object ... initargs)方法進行初始化了,注意參數的順序。
Constructorconstructor1 = catClass.getDeclaredConstructor(String.class, int.class, String.class); Cat cat1 = constructor1.newInstance("喵喵2", 3, "white"); System.out.println(cat1.toString());
到這里我們看到,通過反射創建一個對象有兩種方式:(1)class.newInstance()和(2)consturctor.newInstance(Object ... initargs)。那么他們有什么區別呢?
方式(1)只能調用無參構造創建對象,并且無參構造不能為私有,而方式(2)可以調用所有
Constructorconstructor1 = catClass.getDeclaredConstructor(String.class, int.class, String.class); Cat cat1 = constructor1.newInstance("喵喵2", 3, "white"); System.out.println(cat1.toString()); //調用私有構造 Constructor constructor2 = catClass.getDeclaredConstructor(String.class); constructor2.setAccessible(true); Cat miaomiao = constructor2.newInstance("miaomiao"); System.out.println(miaomiao.toString());
文章版權歸作者所有,未經允許請勿轉載,若此文章存在違規行為,您可以聯系管理員刪除。
轉載請注明本文地址:http://specialneedsforspecialkids.com/yun/68704.html
摘要:基本語法我們通過注解的定義來切入注解的語法。跟定義接口差不多,就是用到的是,然后加上了元注解。那么元注解的作用是什么呢元注解元注解說明了注解所修飾對象的類型。也就是標識該注解可以被繼承。的內置注解重寫了父類的方法表示已過時,不推薦使用。 在Android開發中我們經常會用到注解,例如@Override Butterknife中的BindView等。這里主要記錄下注解怎么寫和簡單的使用。...
摘要:谷歌表示,與搜索并列,是谷歌機器學習技術最重要的產品服務載體。谷歌宣布了基于機器學習技術的全面升級,很可能是其誕生以來的最大升級。在去年的大會上,谷歌宣布了其第一代。 showImg(https://segmentfault.com/img/bVNTKT?w=900&h=385); Google I/O Google I/O 是由 Google 舉行的網絡開發者年會,討論的焦點是用 G...
閱讀 3870·2021-09-10 11:22
閱讀 2325·2021-09-03 10:30
閱讀 3660·2019-08-30 15:55
閱讀 1873·2019-08-30 15:44
閱讀 841·2019-08-30 15:44
閱讀 582·2019-08-30 14:04
閱讀 3042·2019-08-29 17:18
閱讀 1262·2019-08-29 15:04