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