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

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程语言 > java >内容正文

java

java 反射 new class_Java高级特性-反射:不写死在代码,还怎么 new 对象?

發布時間:2023/12/1 java 36 豆豆
生活随笔 收集整理的這篇文章主要介紹了 java 反射 new class_Java高级特性-反射:不写死在代码,还怎么 new 对象? 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

反射是 Java 的一個高級特性,大量用在各種開源框架上。

在開源框架中,往往以同一套算法,來應對不同的數據結構。比如,Spring 的依賴注入,我們不用自己 new 對象了,這工作交給 Spring 去做。

然而,我們要 new 一個對象,就得寫在代碼上。但 Spring 肯定猜不到我們的類叫什么名字,那 Spring 又是怎么把對象給 new 出來的呢?

這就離不開反射。

反射的意義與作用

Java 有兩種操作類的方式,分別是:非反射、反射。

先來說第一種方式,非反射。

非反射,就是根據代碼,靜態地操作類。比如,下面這段代碼:public class Application {

public static void main(String[] args) {

// 創建一個用戶對象

ClientUser client = new ClientUser();

}

}

這個 main() 方法很簡單,就是創建一個用戶對象。整個過程是這樣的,在 JVM 運行前,你必須先想好要創建哪些對象,然后寫在代碼上,最后你運行 main() 方法,JVM 給你創建一個用戶對象。

簡單來說,你寫好代碼,扔給 JVM 運行,運行完就沒了。

在這種情況下,程序員必須控制一切,創建什么對象得提前寫死在代碼上。比如,我要多創建一個商戶對象,那就得改代碼:public class Application {

public static void main(String[] args) {

// 創建一個用戶對象

ClientUser client = new ClientUser();

// 創建一個商戶對象

ShopUser shop = new ShopUser();

// 省略無數 new 操作

}

}

如果按照這種做法,只要需求一變,程序員就得改代碼,工作效率很低。比如說,你碰上復雜些的項目,不光得創建對象,還得 set 成員變量。這樣一來,每新加一個對象,你就得改一堆代碼,遲早得累死。

那這些工作能簡化嗎?

這要用到第二種操作類的方式,反射。反射是一種動態操作類的機制。比如,我要創建一堆對象,那不用提前寫死在代碼,而是放在配置文件或者數據庫上,等到程序運行的時候,再讀取配置文件創建對象。

還是上面的代碼,經過反射的改造,就變成這個樣子:public class Application {

// 模擬配置文件

private static Set configs = new HashSet<>();

static {

configs.add("com.jiarupc.reflection.ShopUser");

configs.add("com.jiarupc.reflection.ClientUser");

// 省略無數配置

}

public static void main(String[] args) throws Exception {

// 讀取配置文件

for (String config : configs) {

// 通過配置文件,獲取類的Class對象

Class clazz = Class.forName(config);

// 創建對象

Object object = clazz.newInstance();

System.out.println(object);

}

}

}

當你運行 main() 方法的時候,程序會先讀取配置文件,然后根據配置文件創建對象。用了反射后,你有沒有發現,工作變輕松了。一旦新加對象,我們只要加一行配置文件,不用動其它地方。

看到這兒,你是不是想起某些開源框架?比如,Spring 的依賴注入。// 加上一行注解,Spring 就接管這個類的創建工作

@Service

public class UserService {

// 省略業務代碼...

}

你在某個類上加一行注解(這相當于加一行配置),Spring 就幫你接管這個類,你不用操心怎么創建對象了。而 Spring 之所以能接管你這個類,是因為利用了 Java 的反射。

簡單來說,我們如果用好反射,能減少大量重復的代碼。

接下來,我們來看看反射能做什么吧~

反射獲取類信息

如果你想操作一個類,那得知道這個類的信息。比如,有哪些變量,有哪些構造器,有哪些方法...沒有這些信息,你連代碼都沒法寫,更別談反射了。

限于篇幅,我們主要講怎么獲取類的 Class 對象、成員變量、方法。

Class 對象只有 JVM 才能創建,里面有一個類的所有信息,包括:成員變量、方法、構造器等等。

換句話說,創建 Class 對象是 JVM 的事,我們不用管。但想通過反射來操作一個類,得先拿到這個類的 Class 對象,這有三種方式:1. Class.forName("類的全限定名")

2. 實例對象.getClass()

3. 類名.class

你可以看下面的代碼:public class User {

public static void main(String[] args) throws Exception {

// 1. Class.forName("類的全限定名")

Class clazz1 = Class.forName("com.jiarupc.reflection.User");

// 2. 實例對象.getClass()

User user = new User();

Class clazz2 = user.getClass();

// 3. 類名.class

Class clazz3 = ClientUser.class;

}

}

當你通過這三種方式,拿到 Class 對象后,就可以用反射獲取類的信息了。

Field 對象代表類的成員變量。我們想拿到一個類的成員變量,可以調用 Class 對象的四個方法。1. Field getField(String name) - 獲取公共字段

2. Field[] getFields() - 獲取所有公共字段

3. Field getDeclaredField(String name) - 獲取成員變量

4. Field[] getDeclaredFields() - 獲取所有成員變量

我們嘗試下獲取所有成員變量,代碼邏輯是這樣的:通過 User 類的全限定名,獲取 Class 對象,然后調用 getDeclaredFields() 方法,拿到 User 類的全部成員變量,最后把變量名、類型輸出到控制臺。public class User {

// 唯一標識

private Long id;

// 用戶名

private String username;

public static void main(String[] args) throws Exception {

// 獲取類的 Class 對象

Class clazz = Class.forName("com.jiarupc.reflection.User");

// 獲取類的所有成員變量

Field[] fields = clazz.getDeclaredFields();

for (Field field : fields) {

String msg = String.format("變量名:%s, 類型:%s", field.getName(), field.getType());

System.out.println(msg);

}

}

}

Method 對象代表類的方法。要拿到一個類的方法,Class 對象同樣提供了四個方法:1. Method getMethod(String name, Class[] params) - 通過方法名、傳入參數,獲取公共方法

2. Method[] getMethods() - 獲取所有公共方法

3. Method getDeclaredMethod(String name, Class[] params) - 通過方法名、傳入參數,獲取任何方法

4. Method[] getDeclaredMethods() - 獲取所有方法

同樣的,我們嘗試下獲取所有方法,先通過 User 類的全限定名,獲取 Class 對象,然后調用 getDeclaredMethods() 方法,拿到 User 類的全部成員方法,最后把方法名、形參數量輸出到控制臺。public class User {

// 唯一標識

private Long id;

// 用戶名

private String username;

public static void main(String[] args) throws Exception {

// 獲取類的 Class 對象

Class clazz = Class.forName("com.jiarupc.reflection.User");

// 獲取類的所有方法

Method[] methods = clazz.getDeclaredMethods();

for (Method method : methods) {

String msg = String.format("方法名:%s, 形參數量:%s", method.getName(), method.getParameterCount());

System.out.println(msg);

}

}

}

看到這兒,你應該能知道:怎么通過反射獲取類的信息。

首先,獲取類的 Class 對象有三種方式;然后,獲取類的成員變量,這對應著 Field 對象;最后,獲取類的方法,這對應著 Method 對象。

然而,反射不止能拿到類的信息,還能操作類。

反射操作類

反射能玩出很多花樣,但我認為最重要的是:創建對象和調用方法。

創建對象是一切的前提。對反射來說,如果沒有創建對象,那我們只能看看這個類的信息。比如,有什么成員變量,有什么方法之類的。而如果你想操作一個類,那么第一步就是創建對象。

你想要創建對象,必須調用類的構造器。這分為兩種情況,最簡單的是:你寫了一個類,但沒有寫構造器,那這個類會自帶一個無參的構造器,這就好辦了。public class User {

// 唯一標識

private Long id;

// 用戶名

private String username;

public static void main(String[] args) throws Exception {

// 獲取類的 Class 對象

Class clazz = Class.forName("com.jiarupc.reflection.User");

// 創建對象

Object object = clazz.newInstance();

System.out.println(object);

}

}

我們先獲取類的 Class 對象,然后調用 newInstance()。

但還有一種情況,我不用 Java 自帶的構造器,而是自己寫。這種情況會復雜一些,你得指定傳入參數的類型,先拿到構造器,再調用 newInstance() 方法。public class User {

// 唯一標識

private Long id;

// 用戶名

private String username;

// 構造器1

public User(Long id) {

this.id = id;

this.username = null;

}

// 構造器2

public User(Long id, String username) {

this.id = id;

this.username = username;

}

public static void main(String[] args) throws Exception {

// 獲取類的 Class 對象

Class clazz = Class.forName("com.jiarupc.reflection.User");

// 通過傳入參數,獲取構造器,再創建對象

Constructor constructor = clazz.getConstructor(Long.class, String.class);

Object object = constructor.newInstance(1L, "jiarupc");

System.out.println(object);

}

}

我們要在一開始就設置 id 和 username,那么你得傳入參數的類型,先找到構造器2-constructor;然后,傳入 id 和 username 到 constructor.newInstance() 方法,就能得到一個用戶對象。

當拿到構造器,并創建好對象后,我們就可以調用對象的方法了。

調用對象的方法分為兩步:第一步,找到方法;第二步,調用方法。這聽起來是非常簡單,事實上也非常簡單。你可以看下面的代碼。public class User {

// 唯一標識

private Long id;

// 用戶名

private String username;

// ..忽略 set/get 方法

public static void main(String[] args) throws Exception {

// 獲取類的 Class 對象

Class clazz = Class.forName("com.jiarupc.reflection.User");

// 創建對象

Object object = clazz.newInstance();

System.out.println(object);

// 通過方法名、傳入參數,找到方法-setUsername

Method method = clazz.getMethod("setUsername", String.class);

// 調用 object 對象的 setUsername() 方法

method.invoke(object, "JerryWu");

// 輸出所有成員變量

Field[] fields = clazz.getDeclaredFields();

for (Field field : fields) {

String msg = String.format("變量名:%s, 變量值:%s", field.getName(), field.get(object));

System.out.println(msg);

}

}

}

我們通過方法名-setUsername、參數類型-String,找到 setUsername 方法;然后,傳入參數-username 到 method.invoke(),執行setUsername 方法;最后,輸出所有成員變量,驗證一下結果。

寫在最后

反射是一種動態操作類的機制,它有兩個用處。

第一個用處,通過反射,我們可以拿到一個類的信息,包括:成員變量、方法、構造器等等。

第二個用處,通過反射,我們可以操作一個類,包括:創建對象、調用對象的方法、修改對象的成員變量。

因為框架要以同一套算法,來應對不同的數據結構。所以,開源框架大量用到了反射。比如,Spring 的依賴注入就離不開反射。

總結

以上是生活随笔為你收集整理的java 反射 new class_Java高级特性-反射:不写死在代码,还怎么 new 对象?的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。

主站蜘蛛池模板: 99av在线| 色片在线免费观看 | 久久艹国产| 成人性生活视频 | 日本午夜啪啪 | 国产九九久久 | 午夜写真片福利电影网 | 秋霞在线观看秋 | 综合 欧美 亚洲日本 | 国产 日韩 欧美 成人 | 白石茉莉奈番号 | 91在线网站 | 在线观看福利视频 | 成人精品三级av在线看 | 91亚洲国产 | 欧美高清一区 | 国产三级国产精品国产国在线观看 | 在线成人一区 | xvideos永久免费入口 | 成年女人18级毛片毛片免费 | 日本视频在线观看免费 | 国产精品亚洲成在人线 | 国产视频69| 国产绿帽一区二区三区 | 久久激情综合网 | 婷婷资源网 | 五月天激情视频 | 好吊色一区二区 | 极品国产白皙 | 精品一区二区三区在线免费观看 | 国产二级一片内射视频播放 | av一道本| 国产中文在线视频 | 亚洲欧美日韩免费 | 日本不卡一区二区三区视频 | 无码精品人妻一区二区三区漫画 | 色婷婷97 | 岛国片在线免费观看 | 免费在线看黄视频 | 精品一区二区电影 | 成人交性视频免费看 | 鲁丝片一区二区三区 | 国产精品电影 | 91精品免费看 | 美人被强行糟蹋np各种play | 青青青视频免费观看 | 日韩欧美在线第一页 | 黄色动漫在线免费观看 | 黑人与日本少妇 | 久久人人爽人人爽 | 日韩精品一二三区 | 亚欧精品视频一区二区三区 | 欧美一级在线视频 | 波多野结衣调教 | 国产一区二区毛片 | 亚洲视频成人 | 69亚洲精品| 成年人观看视频 | 精品成人免费视频 | 成人午夜视频精品一区 | 日韩在线视频免费播放 | 黄色av电影网址 | 日本69av | 亚洲高清中文字幕 | 久久国产视频一区 | 成年人晚上看的视频 | 美女扒开尿口给男人看 | 国产内射老熟女aaaa∵ | 人人干网站 | 91久久极品少妇xxxxⅹ软件 | 一级高清视频 | 伊人网成人网 | 一区二区三区观看 | 九色蝌蚪视频 | 亚洲一区免费看 | 亚洲成人久久久久 | 一区二区免费在线播放 | 国产精品va在线观看无码 | 亚洲精品一区二区三区四区乱码 | 中文日韩 | a级一a一级在线观看 | 成人人伦一区二区三区 | 91影院在线免费观看 | 久久a毛片 | 免费看毛片的网站 | 国产免费又黄又爽又色毛 | 国产视频色| 国产xxxx孕妇 | 久草老司机| 九九午夜 | 日本三级免费网站 | 亚洲成人少妇 | 国产精品国产一区二区三区四区 | 午夜激情av在线 | 婷婷网五月天 | 一区二区日韩在线观看 | 久色网| 日韩黄色精品 | 亚洲 国产 日韩 欧美 |