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

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

JAVA反射机制及其原理实现

發布時間:2024/1/23 编程问答 39 豆豆
生活随笔 收集整理的這篇文章主要介紹了 JAVA反射机制及其原理实现 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

?

9.1 概念

JAVA反射機制是在運行狀態中,對于任意一個類,都能夠知道這個類的所有屬性和方法;對于任意一個對象,都能夠調用它的任意方法和屬性;public、protected、private。

OO(面向對象),private私有的,不能訪問。這種動態獲取信息以及動態調用對象方法的功能稱為java語言的反射機制。**

反射就是把java類中的各種成分映射成一個個的Java對象 例如:一個類有:成員變量、方法、構造方法、包等等信息,利用反射技術可以對一個類進行解剖,把各個組成部分映射成一個個對象。

物理:有個反射的概念,通過鏡子,可以知道物體的存在。看到一個鏡像或名字等,知道物體在哪里。

(其實:一個類中這些成員方法、構造方法、在加入類中都有一個類來描述) 如圖是類的正常加載過程:反射的原理在與class對象。 熟悉一下加載的時候:Class對象的由來是將class文件讀入內存,并為之創建一個Class對象。

Student.java--->Student.class 經過編譯成了一個字節碼文件。

?

9.2 作用

在日常的第三方應用開發過程中,經常會遇到某個類的某個成員變量、方法或是屬性是私有的或是只對系統應用開放,這時候就可以利用Java的反射機制通過反射來獲取所需的私有成員或是方法。當然,也不是所有的都適合反射,之前就遇到一個案例,通過反射得到的結果與預期不符。閱讀源碼發現,經過層層調用后在最終返回結果的地方對應用的權限進行了校驗,對于沒有權限的應用返回值是沒有意義的缺省值,否則返回實際值起到保護用戶的隱私目的。

反射是框架設計的靈魂

(使用的前提條件:必須先得到代表的字節碼的Class,Class類用于表示.class文件(字節碼))

9.2.1 反編譯:.class-->.java

9.2.2通過反射機制訪問java對象的屬性,方法,構造方法等;

User user=new User();--》形成的java文件-->XXX.class

將來賦值的時候,不是User類,是不是就報錯了啊。存在緊耦合的狀態,我們做OO的目的就是高內聚、松耦合,說白了,就是模塊內部實現特定功能,模塊與模塊之間,關聯度不大。

這種方式,是編譯時

我們以后寫程序,更多的應該是運行時給值。

?

9.3 反射機制的相關類

與Java反射相關的類如下:

類名用途
Class類代表類的實體,在運行的Java應用程序中表示類和接口
Field類代表類的成員變量(成員變量也稱為類的屬性)
Method類代表類的方法
Constructor類代表類的構造方法

9.3.1 查看Class類在java中的api

Class 類的實例表示正在運行的 Java 應用程序中的類和接口。也就是jvm中有N多的實例每個類都有該Class對象。(包括基本數據類型) Class 沒有公共構造方法。Class 對象是在加載類時由 Java 虛擬機以及通過調用類加載器中的defineClass 方法自動構造的。也就是這不需要我們自己去處理創建,JVM已經幫我們創建好了。

沒有公共的構造方法,方法共有64個太多了。下面用到哪個就詳解哪個吧

9.3.2 根據一個字符串得到一個類

類名方法含義
StringgetClass表示此對象運行時類的 Class 對象
ClassforName具有指定名的類的 Class 對象
包裝類屬性Type

參考代碼:

? String str="今天是反射課程";Class clz=str.getClass();//得到當前正在運行的類;System.out.println(clz);Class clz2=Integer.TYPE; //包裝類型,不同;包裝類.TypeSystem.out.println(clz2);System.out.println(Boolean.TYPE);System.out.println(Double.TYPE);System.out.println(Character.TYPE);?

9.3.3 獲取Class對象的 三種方式

  • Object:getClass

  • 任何數據類型(包含基本數據類型)都有一個"靜態"的class屬性,這時候可以通過類名.屬性訪問.

  • 通過Class類的靜態方法:forName(string className路徑)

參考代碼

//1.使用第一種方式來獲取User的Class對象;User user=new User(); //弄了一個User對象,在內存里面;Class clz1=user.getClass(); //對象.getClassSystem.out.println(clz1); //clz1:是什么類呢?com.aaa.chapter07.User;路徑+類名;//2.使用第二種方式;Class clz2=User.class; //類名.class 這個靜態屬性.System.out.println(clz2);//這時候,我們是不是考慮一下,之前講的那個原理圖。證明原理圖,里面,正在運行的Class是一個。System.out.println(clz1==clz2);//3.Class.forName(類路徑方式)try {Class clz3=Class.forName("com.aaa.chapter07.User");System.out.println(clz3);System.out.println(clz2==clz3);} catch (ClassNotFoundException e) {e.printStackTrace();}

提問?最常用哪種?一般用第三個。松耦合方式。

9.3.4 通過反射來獲取構造方法

調用方法:

1.獲取構造方法:

1).批量的方法: public Constructor[] getConstructors():所有"公有的"構造方法 public Constructor[] getDeclaredConstructors():獲取所有的構造方法(包括私有、受保護、默認、公有)

2).獲取單個的方法,并調用: public Constructor getConstructor(Class... parameterTypes):獲取單個的"公有的"構造方法: public Constructor getDeclaredConstructor(Class... parameterTypes):獲取"某個構造方法"可以是私有的,或受保護、默認、公有;

例如:

調用構造方法: Constructor-->newInstance(Object... initargs)

package com.aaa.chapter07;import java.lang.reflect.Constructor; import java.lang.reflect.Field; import java.lang.reflect.InvocationTargetException; import java.sql.Connection;/*** Created by 張晨光 on 2020/3/10 10:24*/ public class Constructors {public static void main(String[] args) throws ClassNotFoundException, NoSuchFieldException, NoSuchMethodException, IllegalAccessException, InvocationTargetException, InstantiationException {Class clz=Class.forName("com.aaa.chapter07.User");//2.獲取所有公共字段; // Field[] fields = clz.getFields(); // for(Field f:fields){ // System.out.println(f); // }//2.獲取所有共有 私有字段; // Field[] fields = clz.getDeclaredFields(); // for(Field f:fields){ // System.out.println(f); // }Field field=clz.getField("country");System.out.println(field);Object obj=clz.getConstructor().newInstance();field.set(obj,"中國");User u=(User)obj;System.out.println(u.getCountry());} }

2、newInstance是 Constructor類的方法(管理構造函數的類) api的解釋為: newInstance(Object... initargs) 使用此 Constructor 對象表示的構造方法來創建該構造方法的聲明類的新實例,并用指定的初始化參數初始化該實例。 它的返回值是T類型,所以newInstance是創建了一個構造方法的聲明類的新實例對象。并為之調用

?

package com.aaa.chapter07;import java.lang.reflect.Constructor; import java.lang.reflect.InvocationTargetException;/*** Created by 張晨光 on 2020/3/10 22:29*/ public class InstanceDemo {public static void main(String[] args) throws ClassNotFoundException, NoSuchMethodException, IllegalAccessException, InvocationTargetException, InstantiationException {Class clz=Class.forName("com.aaa.chapter07.User");//1.調用第一個默認構造方法,沒有參數,創建實例之后,再次使用setter賦值。 // Constructor constructor = clz.getConstructor();//Alt+Enter, // Object obj=constructor.newInstance(); // User user=(User)obj; // user.setName("張老師"); // System.out.println(obj);//2.調用第二個有3個參數的構造方法,公共的構造方法,注意里面參數的使用方式. // Constructor constructor2 = clz.getConstructor(String.class,char.class,Integer.class); // Object obj2=constructor2.newInstance("張晨光",'男',18);//類似于之前的構造方法,填充值; // User user2=(User)obj2; // System.out.println(user2);//3.調用第三個私有構造方法,這個構造方法,我們說外部無法訪問.Constructor declaredConstructor = clz.getDeclaredConstructor(String.class);//設置私有構造方法,可以訪問,強制(暴力)訪問.declaredConstructor.setAccessible(true);Object obj=declaredConstructor.newInstance("登徒子");User user3=(User)obj;System.out.println(user3);} }

9.3.5 獲取成員變量并調用

獲取成員變量并調用:

1.批量的

1).Field[] getFields():獲取所有的"公有字段"

2).Field[] getDeclaredFields():獲取所有字段,包括:私有、受保護、默認、公有;

2.獲取單個的:

1).public Field getField(String fieldName):獲取某個"公有的"字段;

2).public Field getDeclaredField(String fieldName):獲取某個字段(可以是私有的)

設置字段的值:

Field --> public void set(Object obj,Object value):

參數說明:

1.obj:要設置的字段所在的對象;

2.value:要為字段設置的值;

總結

以上是生活随笔為你收集整理的JAVA反射机制及其原理实现的全部內容,希望文章能夠幫你解決所遇到的問題。

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