日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問(wèn) 生活随笔!

生活随笔

當(dāng)前位置: 首頁(yè) > 编程语言 > java >内容正文

java

[Java基础] 反射机制汇总

發(fā)布時(shí)間:2025/3/21 java 35 豆豆
生活随笔 收集整理的這篇文章主要介紹了 [Java基础] 反射机制汇总 小編覺(jué)得挺不錯(cuò)的,現(xiàn)在分享給大家,幫大家做個(gè)參考.

引言

初學(xué)Java反射機(jī)制的時(shí)候,只是感覺(jué)很神奇,但是不知道學(xué)了該怎么用,所以過(guò)了一段時(shí)間就忘得差不多了;最近接觸到了框架,在學(xué)習(xí)中遇到了反射,深深體會(huì)到了反射機(jī)制的神奇,回來(lái)復(fù)習(xí)了一下反射機(jī)制,寫一個(gè)小總結(jié);

概念

反射機(jī)制是什么?百度百科很好的解釋了:

Java的反射(reflection)機(jī)制是指在程序的運(yùn)行狀態(tài)中,可以構(gòu)造任意一個(gè)類的對(duì)象,可以了解任意一個(gè)對(duì)象所屬的類,可以了解任意一個(gè)類的成員變量和方法,可以調(diào)用任意一個(gè)對(duì)象的屬性和方法。
這種動(dòng)態(tài)獲取程序信息以及動(dòng)態(tài)調(diào)用對(duì)象的功能稱為Java語(yǔ)言的反射機(jī)制。反射被視為動(dòng)態(tài)語(yǔ)言的關(guān)鍵。

在這里我也就不細(xì)說(shuō)概念了,在使用中你就可以慢慢明白了;

下面我來(lái)展示一下Java反射機(jī)制的基本操作;
注:為了使代碼簡(jiǎn)明易看,所有的異常處理直接拋出Exception(實(shí)際應(yīng)用不要這樣!!)

獲取類型

在Java中有一種類型叫做Class,這是一種類的類型,和String、Object一個(gè)意思,所以不要和類弄混了;

我們可以通過(guò)反射機(jī)制獲取一個(gè)類的類型,返回值類型就是Class

獲取類型有三種方法:

  • Class靜態(tài)方法forName()
  • 對(duì)象.getClass
  • 類名.class

下面是代碼演示:

// 獲取不同類型(Class)的三種方式:Class靜態(tài)方法forName、對(duì)象.getClass()、類名.class // Class也是一個(gè)類類型,和String、Object一樣 // java.lang.Class:Class代表整個(gè)字節(jié)碼,代表一個(gè)類型,代表整個(gè)類 public class ReflectTest01 {public static void main(String[] args) throws Exception {// 第一種:通過(guò)Class的靜態(tài)方法:forName獲取Class類型Class c1 = Class.forName("java.lang.String"); // String類型Class c2 = Class.forName("java.lang.Object"); // Object類型System.out.println(c1 == c2); // String類型和Object類型不同, false//==============================================================// 第二種:(對(duì)象.getClass())java中任何一個(gè)對(duì)象都有這個(gè)方法:getClass(),返回值類型是Class類型Class c3 = "444".getClass(); // c5是String類型Class c4 = new Object().getClass(); // c6是Object類型System.out.println(c1 == c3); // trueSystem.out.println(c2 == c4); // true//=========================================================// 第三種:(類名.class)java中任何一種類型,包括基本數(shù)據(jù)類型,都有一個(gè).class屬性Class c5 = String.class; // String類型Class c6 = Object.class; // Object類型System.out.println(c1 == c5); // trueSystem.out.println(c2 == c6); // true} }

這三種方法中主要留意的就是第一種,forName()方法的使用規(guī)則是:

這里需要記住forName()方法可以使對(duì)應(yīng)的類加載,類加載就會(huì)執(zhí)行靜態(tài)代碼塊;
所以如果只想執(zhí)行靜態(tài)代碼塊,那么可以使用forName()方法;
為什么說(shuō)這一點(diǎn)呢?因?yàn)?strong>JDBC注冊(cè)驅(qū)動(dòng)中將會(huì)用到這一點(diǎn);

下面來(lái)展示一下這個(gè)特性:
forName()傳入的類:

public class MyClass {static {System.out.println("靜態(tài)代碼塊執(zhí)行了!!");} } // 結(jié)論:如果只想要一個(gè)類的靜態(tài)代碼塊執(zhí)行,其余代碼都不執(zhí)行,可以使用: // Class.forName("完整類名") // 這個(gè)方法的執(zhí)行會(huì)導(dǎo)致類加載,類加載時(shí)靜態(tài)代碼快執(zhí)行 // *****這一點(diǎn)會(huì)在后面JDBC中用到***** public class ReflectTest03 {public static void main(String[] args) throws Exception{// Class.forName()導(dǎo)致類加載,靜態(tài)代碼快執(zhí)行Class.forName("reflect.test03.MyClass");} }

輸出:

當(dāng)然這里只是簡(jiǎn)單模擬了一下,但是原理都是一樣的;
結(jié)論:如果只想要一個(gè)類的靜態(tài)代碼塊執(zhí)行,其余代碼都不執(zhí)行,可以使用:Class.forName(“完整類名”)

實(shí)例化對(duì)象

當(dāng)獲取到對(duì)象類型后就可以通過(guò)該類型實(shí)例化對(duì)應(yīng)的對(duì)象,用到newInstance()方法

在框架一般都是需要通過(guò)反射機(jī)制獲取配置文件內(nèi)容并進(jìn)行操作的,通過(guò)配置文件內(nèi)容可以獲取不同信息,下面演示一下如何通過(guò)配置文件實(shí)例化對(duì)象;
注:這里使用.properties文件,簡(jiǎn)單易懂

創(chuàng)建一個(gè).properties文件:

這個(gè)配置文件需要放到該項(xiàng)目的目錄下,不能放到類路徑(src)或者其他目錄下;

import java.io.FileInputStream; import java.util.Properties;// 通過(guò)反射機(jī)制獲取配置文件內(nèi)容并實(shí)例化對(duì)象 // 反射機(jī)制讓程序更加靈活,符合OPC開(kāi)閉原則 // 高級(jí)框架(Spring等)底層原理都是反射機(jī)制 public class ReflectTest02 {public static void main(String[] args) throws Exception{FileInputStream fis = new FileInputStream("classname.properties"); // 創(chuàng)建輸入流Properties properties = new Properties(); // 底層實(shí)現(xiàn)是Map,繼承了HashTable,key和Value都是String類型properties.load(fis); // 加載Java的配置文件classname.properties到內(nèi)存中fis.close(); // 關(guān)閉輸入流String classname = properties.getProperty("first"); // 通過(guò)key得到ValueClass<?> clazz = Class.forName(classname); // 獲取classname(Value值)的類型Object obj = clazz.newInstance(); // 創(chuàng)建對(duì)象實(shí)例System.out.println(obj);} }

因?yàn)檫@里的key傳入的是first,所以輸出為:

可以看出實(shí)例化了一個(gè)Object對(duì)象

還有另外一種方法,是比較常用簡(jiǎn)單的方法:
java.util包下提供了一個(gè)資源綁定器,便于獲取屬性配置文件中的內(nèi)容;

需要使用該類的兩個(gè)方法:

創(chuàng)建一個(gè)配置文件:

使用這種方式的時(shí)候,配置文件必須放到類路徑(src)下

import java.util.ResourceBundle;// 使用以下這種方式的時(shí)候,屬性配置文件xxx.properties必須放到類路徑下。 // 實(shí)現(xiàn)和ReflectTest02一樣的功能,但是又通過(guò)新的獲取絕對(duì)路徑的方法,而且以后常用這個(gè)方法 public class ReflectTest05 {public static void main(String[] args) throws Exception {// 資源綁定器,只能綁定xxx.properties文件。并且這個(gè)文件必須在類路徑(src文件夾)下。文件擴(kuò)展名也必須是properties// 并且在寫路徑的時(shí)候,路徑后面的擴(kuò)展名.properties不能寫。ResourceBundle bundle = ResourceBundle.getBundle("absolute_path"); // 綁定配置文件String classname = bundle.getString("second"); // 通過(guò)key得到ValueClass c = Class.forName(classname);Object obj = c.newInstance();System.out.println(obj);} }

這次key傳入的是second,輸出為:

反射機(jī)制的一些操作

下面展現(xiàn)反射機(jī)制的一些操作,其實(shí)就是各種方法的調(diào)用,會(huì)查文檔就好;
這里先定義一個(gè)類,下面所有的操作都基于這個(gè)類;

public class TestClass01 {int age;public String name;private final static int num = 4;static protected boolean flag;public void firstMethod(String s) {System.out.println("第一個(gè)方法的調(diào)用!");}public void secondMethod(String s, int i) {System.out.println("第二個(gè)方法的調(diào)用!");} }

反射TestClass類中所有Field(屬性)

import java.lang.reflect.Field; import java.lang.reflect.Modifier;public class ReflectTest06 {public static void main(String[] args) throws Exception {// 獲取整個(gè)類Class testClass = Class.forName("reflect.test06.TestClass01");// 獲取類名String classname = testClass.getName(); // 完整類名System.out.println(classname);System.out.println(testClass.getSimpleName()); // 簡(jiǎn)單類名// 獲取TestClass類的屬性// getFields()只會(huì)獲取所有public修飾的屬性Field[] fields01 = testClass.getFields();Field f = fields01[0];String filename = f.getName(); // 獲取屬性名System.out.println(filename);System.out.println("=====================");// 獲取所有屬性Field[] fields02 = testClass.getDeclaredFields();for (Field i : fields02) {System.out.println(i.getName()); // 獲取屬性名// 獲取屬性的類型System.out.println(i.getType().getName()); // 完整類型System.out.println(i.getType().getSimpleName()); // 簡(jiǎn)單類型// 獲取修飾符(用到了Modifier類的toString方法)System.out.println(Modifier.toString(i.getModifiers()));System.out.println("------------");}} }

輸出:

reflect.test06.TestClass01 TestClass01 name ===================== age int int------------ name java.lang.String String public ------------ num int int private static final ------------ flag boolean boolean protected static ------------

獲取對(duì)象屬性中的值

import java.lang.reflect.Field;public class ReflectTest07 {public static void main(String[] args) throws Exception {Class className = Class.forName("reflect.test06.TestClass01"); // 獲取類Object obj = className.newInstance(); // 通過(guò)類創(chuàng)建對(duì)象Field ageFiled = className.getDeclaredField("age"); // 獲取age屬性// 給屬性賦值需要有實(shí)例化的對(duì)象objageFiled.set(obj, 111); // 給obj對(duì)象的age屬性復(fù)制111System.out.println(ageFiled.get(obj)); // 獲取obj對(duì)象的age屬性的值} }

輸出:

獲取方法并調(diào)用(重要)

這個(gè)相對(duì)重要,獲取方法用到了Class類的getMethod()方法或者getMethods()

返回類型Method:

同樣獲取方法后需要調(diào)用,使用Method類的一個(gè)方法:invoke()

下面是具體使用方法:

import java.lang.reflect.Method;// 通過(guò)反射機(jī)制調(diào)用方法 public class ReflectTest08 {public static void main(String[] args) throws Exception{// 先獲取類Class c = Class.forName("reflect.test06.TestClass01");// 通過(guò)類實(shí)例化對(duì)象Object obj = c.newInstance();// 通過(guò)類獲取方法Method method01 = c.getMethod("firstMethod", String.class);Method method02 = c.getMethod("secondMethod", String.class, int.class);// 通過(guò)獲取的方法來(lái)調(diào)用(通過(guò)invoke方法)// 需要:1,該方法; 2,一個(gè)對(duì)象; 3,對(duì)應(yīng)參數(shù)Object retValue01 = method01.invoke(obj, "這是一個(gè)沒(méi)有什么用的參數(shù)");Object retValue02 = method02.invoke(obj, "這也是一個(gè)沒(méi)有什么用的參數(shù),后面1也是", 1);} }

輸出:

總結(jié)

這是反射機(jī)制一些基本常用操作,但是實(shí)際應(yīng)用并不會(huì)這么簡(jiǎn)單,所以基礎(chǔ)的一定要掌握好,這樣在以后學(xué)習(xí)spring等框架時(shí)就能看懂學(xué)習(xí)底層源碼了;
點(diǎn)評(píng)

《新程序員》:云原生和全面數(shù)字化實(shí)踐50位技術(shù)專家共同創(chuàng)作,文字、視頻、音頻交互閱讀

總結(jié)

以上是生活随笔為你收集整理的[Java基础] 反射机制汇总的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。

如果覺(jué)得生活随笔網(wǎng)站內(nèi)容還不錯(cuò),歡迎將生活随笔推薦給好友。