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