真人作爱90分钟免费看视频,亚洲中文有码字幕日本第一页,亚洲精品中文字幕乱码三区,亚洲日本va中文字幕,中国熟妇牲交视频

到底什么是反射?反射究竟能用來(lái)干什么?(到底什么是反射-反射究竟能用來(lái)干什么呢)

到底什么是反射?反射究竟能用來(lái)干什么?(到底什么是反射-反射究竟能用來(lái)干什么呢)

反射,顧名思義,它是一種逆向的操作。就好像人在照鏡子的時(shí)候,正是由于光的反射,才能看到鏡子中的自己。而在Java中,反射功能就好比是一面鏡子,通過(guò)它,我們可以在程序運(yùn)行過(guò)程中看到Class以及對(duì)象的相關(guān)信息。

在以往的經(jīng)驗(yàn)中,當(dāng)我們需要完成某些操作,往往是在編譯之前完成,比如根據(jù)創(chuàng)建對(duì)象、讀取屬性、設(shè)置屬性;我們把這些程序編寫(xiě)完之后編譯器會(huì)將之編譯為class文件,然后直接在虛擬機(jī)中運(yùn)行就可以了,大部分情況確實(shí)是這樣,這也是為什么Java是"靜態(tài)語(yǔ)言"。

但是我們卻可以通過(guò)反射來(lái)完成在動(dòng)態(tài)語(yǔ)言中才能做到的一些操作,比如首先第一步,通過(guò)反射獲取某個(gè).class文件的結(jié)構(gòu)信息。

示例如下:

/** * 蝙蝠俠 */public class Batman { public Batman(String name,int age,String power){ this.name = name; this.age = age; this.power = power; } //蝙蝠俠的名字 private String name; //蝙蝠俠的年齡 private int age; //蝙蝠俠的超能力 private String power; public String getName() { return name; } public void setName(String name) { this.name = name; } public int getAge() { return age; } public void setAge(int age) { this.age = age; } public String getPower() { return power; } public void setPower(String power) { this.power = power; } /** 跟小貓談戀愛(ài) */ private void beInLove(){ System.out.println("蝙蝠俠正在跟小貓談戀愛(ài)"); } /** 教訓(xùn)小丑 */ public void work(){ System.out.println("蝙蝠俠正在教訓(xùn)小丑"); } private void workWithGordon(String name){ System.out.printf("蝙蝠俠正在和%s一起教訓(xùn)小丑",name); }}復(fù)制代碼

//測(cè)試類(lèi)public class ReflectTest { public static void main(String[] args) { Class cls = Batman.class; //1.獲取class中的所有屬性,包括全局屬性和局部屬性 Field[] fields = cls.getDeclaredFields(); System.out.println("屬性:"); for (Field f : fields) { System.out.println(f); } System.out.println("方法:"); //獲取class中的所有方法 Method[] mets = cls.getDeclaredMethods(); for (Method met : mets) { System.out.println(met); } System.out.println("構(gòu)造器:"); //獲取class中的所有構(gòu)造器 Constructor[] cons = cls.getDeclaredConstructors(); for (Constructor c : cons) { System.out.println(c); } }}復(fù)制代碼

運(yùn)行結(jié)果:
屬性:
private java.lang.String day2.demo2.Batman.name private int day2.demo2.Batman.age private java.lang.String day2.demo2.Batman.power
方法:
public int day2.demo2.Batman.getAge() public void day2.demo2.Batman.setAge(int) public java.lang.String day2.demo2.Batman.getPower() public void day2.demo2.Batman.setPower(java.lang.String) public java.lang.String day2.demo2.Batman.getName() public void day2.demo2.Batman.setName(java.lang.String)
構(gòu)造器:
public day2.demo2.Batman(java.lang.String,int,java.lang.String)

java程序在運(yùn)行時(shí),虛擬機(jī)在加載類(lèi)時(shí),會(huì)為這個(gè)類(lèi)創(chuàng)建一個(gè)Class對(duì)象,用來(lái)表示這個(gè)類(lèi)的信息??梢酝ㄟ^(guò)類(lèi)名.class、Class.forName("類(lèi)名")、Object.getClass等方式獲取到一個(gè)Class對(duì)象,這個(gè)對(duì)象記錄了類(lèi)的信息,通過(guò)它可以逆向獲取類(lèi)的結(jié)構(gòu)。

在示例中,通過(guò)Class對(duì)象中方法的調(diào)用,獲取了Batman類(lèi)中的所有屬性、方法、構(gòu)造器,但是反射的功能遠(yuǎn)不止于此,比如通過(guò)上述三個(gè)方法獲取到的Field、Method、Constructor數(shù)組對(duì)象完成進(jìn)一步的操作:

public class ReflectTest { public static void main(String[] args) { Class cls = Batman.class; Field[] fields = cls.getDeclaredFields(); System.out.println("屬性:"); System.out.println("訪問(wèn)修飾符:" Modifier.toString(fields[0].getModifiers())); System.out.println("是否靜態(tài)的:" Modifier.isStatic(fields[0].getModifiers())); System.out.println("是否為public:" Modifier.isPublic(fields[0].getModifiers())); System.out.println("是否常量:" Modifier.isFinal(fields[0].getModifiers())); System.out.println("方法:"); Method[] mets = cls.getDeclaredMethods(); System.out.println("是否為本地方法:" Modifier.isNative(mets[0].getModifiers())); System.out.println("是否為抽象方法:" Modifier.isAbstract(mets[0].getModifiers())); System.out.println("是否為接口:" Modifier.isInterface(mets[0].getModifiers())); System.out.println("是否線程同步:" Modifier.isSynchronized(mets[0].getModifiers())); System.out.println("構(gòu)造器:"); Constructor[] cons = cls.getDeclaredConstructors(); System.out.println("是否公有:" Modifier.isPublic(cons[0].getModifiers())); /** * ... * */ }}復(fù)制代碼

以上這些都是直接對(duì)Class類(lèi)的操作,其實(shí)java反射也同樣支持對(duì)運(yùn)行中的對(duì)象的操作,甚至可以修改對(duì)象中屬性的值。

示例代碼:

public class ReflectTest { public static void main(String[] args) throws IllegalAccessException { Batman batman = new Batman("布魯斯韋恩",27,"有錢(qián)"); Class cls = batman.getClass(); Field[] fields = cls.getDeclaredFields(); /**獲取第一個(gè)屬性name的值,由于是private屬性, 所以會(huì)報(bào)IllegalAccessException異常,很顯然是與權(quán)限有關(guān)*/ try { var name = fields[0].get(batman); System.out.println(name); }catch (IllegalAccessException e){ //這里通過(guò)一個(gè)方法設(shè)置可訪問(wèn)對(duì)象的可訪問(wèn)標(biāo)志 fields[0].setAccessible(true); var name = fields[0].get(batman); System.out.println(name); } //但是這里設(shè)置的只是數(shù)組中第一個(gè)屬性的訪問(wèn)權(quán)限,下面這句話依然會(huì)報(bào)錯(cuò) try { var name = fields[1].get(batman); System.out.println(name); }catch (IllegalAccessException e){ //所以通過(guò)下面的方法對(duì)整個(gè)數(shù)組對(duì)象的訪問(wèn)權(quán)限進(jìn)行設(shè)置 AccessibleObject.setAccessible(fields,true); var age = fields[1].get(batman); var power = fields[2].get(batman); System.out.println(age); System.out.println(power); } //修改fields[2]的值 fields[2].set(batman,"哥譚首富"); System.out.println("超能力:" batman.getPower()); }}復(fù)制代碼

運(yùn)行結(jié)果:
布魯斯韋恩
27
有錢(qián)
超能力:哥譚首富

通過(guò)調(diào)用對(duì)象的getClass()方法獲取這個(gè)類(lèi)唯一的Class對(duì)象,再通過(guò)獲取到field對(duì)象的get(obj)方法獲取到這個(gè)field的值(當(dāng)然如果屬性是私有的,還需要使用setAccessible方法設(shè)置訪問(wèn)標(biāo)志),并且不僅可以獲取,還能通過(guò)其set(obj,val)方法重新設(shè)置這個(gè)屬性的值。而這一切都是在程序運(yùn)行期間完成的,成功的通過(guò)反射修改了對(duì)象中的屬性。

至此,已經(jīng)實(shí)現(xiàn)了通過(guò)反射來(lái)查看類(lèi)的信息、對(duì)象的屬性以及設(shè)置對(duì)象的屬性。那么如何通過(guò)反射來(lái)調(diào)用方法以及構(gòu)造器呢?

示例代碼:

public class ReflectTest { public static void main(String[] args) throws IllegalAccessException, NoSuchMethodException, InvocationTargetException, NoSuchFieldException, InstantiationException { Class cls = Batman.class; //通過(guò)反射調(diào)用構(gòu)造器創(chuàng)建蝙蝠俠對(duì)象 Batman batman = (Batman) cls.getDeclaredConstructor(String.class,int.class,String.class).newInstance("蝙蝠俠", 27, "有錢(qián)"); Method method = cls.getDeclaredMethod("beInLove"); //因?yàn)閎eInLove()方法是私有的,所以需要設(shè)置以下權(quán)限 method.setAccessible(true); method.invoke(batman); Method work = cls.getDeclaredMethod("work"); //work方法不是private的,不需要設(shè)置權(quán)限 work.invoke(batman); //調(diào)用帶參數(shù)的方法 Method workWithGordon = cls.getDeclaredMethod("workWithGordon", String.class); //私有方法依然要設(shè)置權(quán)限 workWithGordon.setAccessible(true); workWithGordon.invoke(batman,"Gordon"); }}復(fù)制代碼

至此,就完成了方法及構(gòu)造方法的調(diào)用。需要注意的是,若調(diào)用了一個(gè)帶返回值的方法,如果返回值類(lèi)型是基本類(lèi)型,invoke方法會(huì)返回其包裝類(lèi)型,如int返回Integer、double返回Double。

另外,java.lang.reflect包中還提供了一個(gè)很好用的類(lèi)Array,ArrayList中的數(shù)組擴(kuò)容就使用到了這個(gè)類(lèi)。

示例代碼:

public class ReflectTest { public static void main(String[] args) throws IllegalAccessException, NoSuchMethodException, InvocationTargetException, NoSuchFieldException, InstantiationException { //假如我想創(chuàng)建一個(gè)數(shù)組 String[] strs = {"bruce","jack","jerry"}; strs = (String[]) copyOf(strs,10); } //現(xiàn)在我想寫(xiě)一個(gè)方法來(lái)為泛型數(shù)組擴(kuò)容 public static Object[] CopyOf(Object[] obj,int nlength){ var newArray = new Object[nlength]; System.arraycopy(obj,0,newArray,0,Math.min(obj.length,nlength)); return newArray; }}復(fù)制代碼

運(yùn)行結(jié)果:Exception in thread "main" java.lang.ClassCastException

這段代碼看起來(lái)好像沒(méi)有問(wèn)題,通過(guò)Object超類(lèi)接收任意類(lèi)型的數(shù)組。但是有一個(gè)細(xì)節(jié)問(wèn)題,當(dāng)創(chuàng)建一個(gè)數(shù)組然后將其轉(zhuǎn)為Object[],再把它從Object[]轉(zhuǎn)回來(lái)是沒(méi)有問(wèn)題的,但是如果直接創(chuàng)建一個(gè)Object[]轉(zhuǎn)成目標(biāo)類(lèi)型的數(shù)組是會(huì)出錯(cuò)的。所以上述代碼無(wú)法完成泛型數(shù)組的擴(kuò)容。

現(xiàn)在對(duì)代碼做一些改進(jìn),示例代碼:

public class ReflectTest { public static void main(String[] args) throws IllegalAccessException, NoSuchMethodException, InvocationTargetException, NoSuchFieldException, InstantiationException { //假如我想創(chuàng)建一個(gè)數(shù)組 String[] strs = {"bruce","jack","jerry"}; strs = (String[]) CopyOf(strs,10); System.out.println(strs.length); } //現(xiàn)在我想寫(xiě)一個(gè)方法來(lái)為泛型數(shù)組擴(kuò)容 public static Object CopyOf(Object obj,int nlength){ Class cls = obj.getClass(); if(!cls.isArray()) return null; //獲取數(shù)組的類(lèi)型 Class type = cls.getComponentType(); //獲取數(shù)組的長(zhǎng)度 int length = Array.getLength(obj); //通過(guò)Array.newInstance創(chuàng)建一個(gè)泛型數(shù)組,類(lèi)型通過(guò)參數(shù)指定 Object newArray = Array.newInstance(type,nlength); System.arraycopy(obj,0,newArray,0,Math.min(length,nlength)); return newArray; }}復(fù)制代碼

運(yùn)行結(jié)果:10

這次程序成功運(yùn)行,并且成功為數(shù)組擴(kuò)容。最主要的原因是代碼中的關(guān)鍵方法,Array類(lèi)的靜態(tài)方法newInstance,這個(gè)方法能夠返回一個(gè)有給定類(lèi)型,給定大小的新數(shù)組,而不是一個(gè)簡(jiǎn)單的Object[]。

總結(jié):反射機(jī)制可以在運(yùn)行時(shí)查看、操作字段和方法。但是不應(yīng)該濫用反射,因?yàn)榉瓷湓诰幾g階段無(wú)法查找出錯(cuò)誤,如果存在問(wèn)題,往往到了運(yùn)行時(shí)才會(huì)發(fā)現(xiàn)。JVM無(wú)法對(duì)反射的相關(guān)代碼做優(yōu)化,所以效率相對(duì)低。并且反射可能導(dǎo)致程序不安全。

作者:現(xiàn)在沒(méi)有牛仔了
鏈接:https://juejin.cn/post/7228967103349080120

版權(quán)聲明:本文內(nèi)容由互聯(lián)網(wǎng)用戶自發(fā)貢獻(xiàn),該文觀點(diǎn)僅代表作者本人。本站僅提供信息存儲(chǔ)空間服務(wù),不擁有所有權(quán),不承擔(dān)相關(guān)法律責(zé)任。如發(fā)現(xiàn)本站有涉嫌抄襲侵權(quán)/違法違規(guī)的內(nèi)容, 請(qǐng)發(fā)送郵件至89291810@qq.com舉報(bào),一經(jīng)查實(shí),本站將立刻刪除。
(0)
上一篇 2024年4月24日 下午2:05
下一篇 2024年4月24日 下午2:11

相關(guān)推薦

  • 吉林教育信息網(wǎng)中考

    吉林教育信息網(wǎng)中考 吉林教育信息網(wǎng)中考是吉林省中學(xué)生的重要考試之一。每年,成千上萬(wàn)的考生們都會(huì)聚集在這里,為自己的未來(lái)做出重要的決定。中考不僅是對(duì)學(xué)生的一次考驗(yàn),更是對(duì)他們的綜合素…

    教育百科 2024年12月9日
  • 孩子厭學(xué)的辦法

    孩子厭學(xué)是許多家長(zhǎng)都會(huì)遇到的問(wèn)題,以下是一些孩子厭學(xué)的辦法,希望能有所幫助。 1. 幫助孩子找到學(xué)習(xí)的動(dòng)力。讓孩子知道學(xué)習(xí)對(duì)他們的未來(lái)非常重要,并且讓他們知道他們正在為美好的未來(lái)努…

    教育百科 2025年2月28日
  • 蛋白質(zhì)的合成過(guò)程蛋白質(zhì)是什么

    蛋白質(zhì)是生物體內(nèi)最重要的分子之一,是組成細(xì)胞結(jié)構(gòu)和功能的重要成分。蛋白質(zhì)的合成過(guò)程涉及到多個(gè)分子的相互作用,包括氨基酸的化學(xué)合成、核糖核苷酸的構(gòu)建、多肽鏈的形成和折疊,以及轉(zhuǎn)錄和翻…

    教育百科 2025年1月26日
  • 蘭州高中排名前50位

    蘭州高中排名前50位 蘭州是中國(guó)甘肅省的一個(gè)地級(jí)市,也是一個(gè)歷史悠久的城市。在蘭州,有許多優(yōu)秀的高中,其中一些高中在甘肅內(nèi)外都享有很高的聲譽(yù)。本文將介紹蘭州排名前50位的高中,這些…

    教育百科 2024年10月23日
  • 馬云說(shuō)上學(xué)不上學(xué)的話

    上學(xué)或不上學(xué),這是一個(gè)非常個(gè)人化的問(wèn)題。對(duì)于某些人來(lái)說(shuō),上學(xué)是他們實(shí)現(xiàn)自我價(jià)值和獲得成功的重要途徑。而對(duì)于其他人來(lái)說(shuō),他們可能認(rèn)為不上學(xué)也能成功,或者他們更愿意從事自己喜歡的工作。…

    教育百科 2025年4月28日
  • 復(fù)數(shù)的運(yùn)算

    復(fù)數(shù)的運(yùn)算 復(fù)數(shù)是數(shù)學(xué)中的一個(gè)基本概念,它可以用來(lái)表示一個(gè)復(fù)變量的值,例如實(shí)數(shù)x和y的復(fù)數(shù)表示為x+y,即z=x+y。復(fù)數(shù)的運(yùn)算是復(fù)數(shù)理論中非常重要的一部分,它涉及到復(fù)數(shù)的模、余弦…

    教育百科 2024年12月10日
  • 什么心理咨詢(xún)師證書(shū)含金量高(有什么心理咨詢(xún))

    心理咨詢(xún)是一種非常重要的心理健康服務(wù),可以幫助我們解決心理問(wèn)題,緩解心理壓力,改善情緒,提高生活質(zhì)量。在這篇文章中,我們將探討一些常見(jiàn)的心理咨詢(xún)問(wèn)題,并提供一些實(shí)用的心理咨詢(xún)技巧和…

    教育百科 2024年8月22日
  • 本田呷家庭教育

    本田呷家庭教育的故事 本田呷是一位普通的日本家庭,他的父母非常注重家庭教育。他們教育孩子要善良,勇敢,并且有同情心。他們也經(jīng)常教育孩子要尊重長(zhǎng)輩,并且要關(guān)心別人。 本田呷的父母從小…

    教育百科 2024年10月26日
  • 2024廣東480分公辦二本大學(xué) 好考的院校有哪些(廣東省450分的公辦二本)

    2024廣東480分公辦二本大學(xué) 好考的院校有哪些(廣東省450分的公辦二本)

    教育百科 2024年3月29日
  • 怎樣不讓孩子不玩手機(jī)玩手機(jī)對(duì)孩子的危害

    當(dāng)今社會(huì),手機(jī)已經(jīng)成為人們生活中不可或缺的一部分。然而,過(guò)度使用手機(jī)也會(huì)對(duì)孩子產(chǎn)生負(fù)面影響。本文將探討如何不讓孩子過(guò)度玩手機(jī),以及玩手機(jī)對(duì)孩子的危害。 過(guò)度使用手機(jī)對(duì)孩子的身體健康…

    教育百科 2024年10月9日

發(fā)表回復(fù)

您的郵箱地址不會(huì)被公開(kāi)。 必填項(xiàng)已用 * 標(biāo)注