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

歡迎訪問 生活随笔!

生活随笔

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

java

Java基础:反射

發布時間:2025/4/16 java 36 豆豆
生活随笔 收集整理的這篇文章主要介紹了 Java基础:反射 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

反射注解動態代理相關閱讀

  • Java基礎:類加載器
  • Java基礎:反射
  • Java基礎:注解
  • Java基礎:動態代理

1. 反射概述

Java反射機制是在運行狀態中,對于任意一個類,都能夠知道這個類的所有屬性和方法;對于任意一個對象,都能夠調用它的任意一個方法和屬性;這種動態獲取的信息以及動態調用對象的方法的功能稱為java語言的反射機制。

Java 反射機制主要提供了以下功能: 在運行時判斷任意一個對象所屬的類;在運行時構造任意一個類的對象;在運行時判斷任意一個類所具有的成員變量和方法;在運行時調用任意一個對象的方法;生成動態代理。

Java中,反射是一種強大的工具。它使您能夠創建靈活的代碼,這些代碼可以在運行時裝配,無需在組件之間進行源代表鏈接。反射允許我們在編寫與執行時,使我們的程序代碼能夠接入裝載到JVM中的類的內部信息,而不是源代碼中選定的類協作的代碼。這使反射成為構建靈活的應用的主要工具。但需注意的是:如果使用不當,反射的成本很高。

2. 反射的應用場景

反射是Java中的高級特性,在各種Java框架中都需要使用反射。所以,就算你將來很長一段時間不使用反射,但你使用的框架都大量使用了反射,所以想深入學習框架,那么就一定要學習反射。

框架通常通過反射來識別一個對象的“類型信息”。當你傳遞給框架一個對象時,框架會通過反射來了解對象的真實類型(對象實體的類型,而不是引用的類型),這個類型有幾個構造器,有什么樣的屬性,有什么樣的方法。還可以通過反射調用構造器,調用方法,對屬性進行讀寫操作。

你可能覺得這沒有什么神奇的,那是你還沒了解我說的是什么!你需要再想一想,寫一個方法,參數是Object obj,然后你的方法需要創建一個與參數類型相同的對象出來,還要調用這個對象上的方法。需要注意,參數是Object類型,但用戶調用這個方法時,可能傳遞的不是Object實體對象,它的真實類型有可能是任何類型。

目前好多框架都會用到java的反射機制。比如struts2,sping,hibernate。 如果我們不用struts2,自己寫一個類似的功能也是可以實現的,比如瀏覽器通過HTTP發送數據,而這些數據都是字符串,我們接受到這些字符串時, 可以通過反射去構造一個對象(通過攔截器做成框架的功能),這樣就可以用對象的get和set方法了,而不用原始的getPeremter()方法。事實上, 在struts2出來之前,我們又不想用struts1的ActionForm就做過這樣項目。

Java反射機制主要提供了以下功能:

  • 在運行時判斷任意一個對象所屬的類
  • 在運行時構造任意一個類的對象
  • 在運行時判斷任意一個類所具有的成員變量和方法
  • 在運行時調用任意一個對象的方法
  • 生成動態代理

3. 反射

JAVA反射機制是在運行狀態中,對于任意一個類,都能夠知道這個類的所有屬性和方法;對于任意一個對象,都能夠調用它的任意一個方法和屬性;這種動態獲取的信息以及動態調用對象的方法的功能稱為java語言的反射機制。

要想解剖一個類,必須先要獲取到該類的字節碼文件對象。而解剖使用的就是Class類中的方法,所以先要獲取到每一個字節碼文件對應的Class類型的對象。

一句話概括:反射就是把java類中的各種成分映射成相應的java類(Class,Field,Method,Constructor),在程序運行的過程中,動態的訪問java類中的成分,反射還可以實現框架的功能

例如:一個Java類中用一個Class類的對象來表示,一個類中的組成部分:成員變量,方法,構造方法,包等信息也用一個個的Java類來表示,就像汽車是一個類,汽車中的發動機,變速箱等等也是一個個的類。表示java類的Class類顯然要提供一系列的方法,來獲得其中的變量,方法,構造方法,修飾符,包等信息,這些信息就是用相應類的實例對象來表示,它們是Field、Method、Contructor、Package等。

3.1 反射的主要作用

  • 運行時取得類的方法和字段的相關信息。
  • 創建某個類的新實例(newInstance())
  • 取得字段引用直接獲取和設置對象字段,無論訪問修飾符是什么
  • 觀察或操作應用程序的運行時行為
  • 調試或測試程序,因為可以直接訪問方法、構造函數和成員字段
  • 通過名字調用不知道的方法并使用該信息來創建對象和調用方法

4. 反射從Class類開始

要想使用反射,首先你需要得到Class對象,然后才能通過Class對象獲取Constructor、Field、Method等對象。所有的反射對象都不可能自己來new,說白一點,這些反射對象對應的是class文件上的信息,你怎么可能自己去new呢?如果可以自己去new一個Class類的對象,那么是不是就不用我們再去編寫.java文件,然后再通過編譯器去編譯成.class文件了呢?當然這是不可能的!

我們需要思考,Class除了可以返回當前對應類型的所有屬性、方法、構造器的反射對象外,還有什么功能呢?例如對應類型的類名是什么?對應類型的父類是誰?對應類型是不是public類,是不是final類。對應類型有沒有可能是個數組類型?有沒有可能是接口類型?有沒有可能是基本類型等等!如果你學會了這樣思考,那么你今后學習新類是就方便多了!

4.1 三種獲取Class對象的方式

  • Object類的getClass()方法
Person p = new Person();Class c = p.getClass();
  • 數據類型的靜態屬性class
Class c2 =Person.class;

任意數據類型都具備一個class靜態屬性,看上去要比第一種方式簡單

  • 將類名作為字符串傳遞給Class類中的靜態方法forName即可
Class c3 = Class.forName("Person"); package cn.itcast;class Person {private String name;int age;public String address;public Person() {}private Person(String name) {this.name = name;}Person(String name, int age) {this.name = name;this.age = age;}public Person(String name, int age, String address) {this.name = name;this.age = age;this.address = address;}public void show() {System.out.println("show");}public void method(String s) {System.out.println("method " + s);}public String getString(String s, int i) {return s + "---" + i;}private void function() {System.out.println("function");}public String toString() {return "Person [name=" + name + ", age=" + age + ", address=" + address+ "]";} }/** 反射:就是通過class文件對象,去使用該文件中的成員變量,構造方法,成員方法。* * Person p = new Person(); p.使用* * 要想這樣使用,首先你必須得到class文件對象,其實也就是得到Class類的對象。 Class類: 成員變量 Field 構造方法 Constructor* 成員方法 Method* * 獲取class文件對象的方式: A:Object類的getClass()方法 B:數據類型的靜態屬性class C:Class類中的靜態方法 public* static Class forName(String className)* * 一般我們到底使用誰呢? 第三種:因為第三種是一個字符串,而不是一個具體的類名。這樣我們就可以把這樣的字符串配置到配置文件中。*/ public class ReflectDemo {public static void main(String[] args) throws ClassNotFoundException {// 方式1Person p = new Person();Class c = p.getClass();Person p2 = new Person();Class c2 = p2.getClass();System.out.println(p == p2);// falseSystem.out.println(c == c2);// true// 方式2Class c3 = Person.class;// int.class;// String.class;System.out.println(c == c3);// 方式3// ClassNotFoundExceptionClass c4 = Class.forName("cn.itcast_01.Person");System.out.println(c == c4);} }

4.2 第三種和前兩種的區別

前兩種你必須明確Person類型;后面是你我這種類型的字符串就行.這種擴展更強.我不需要知道你的類.我只提供字符串,按照配置文件加載就可以了。

PS:所謂的框架就是對外提供一些接口,也就是功能擴展的標準,由實現類按照這個接口標準去實現。框架內部如果需要操縱這些實現類的對象完成某些操作,那么只需要把這些實現類的全名(包名+類名)寫在某個配置文件中,框架代碼只需要讀取這個配置文件,就可以獲取這個實現類的字節碼文件,然后利用反射技術創建這個實現類的對象并且調用相應的方法完成一些操作。

用于描述字節碼的類就是Class類,創建對象,可以提取字節碼文件中的內容,如字段、構造函數、一般函數。該類就可以獲取字節碼文件中的所有內容,那么反射就是依靠該類完成的。想要對一個類文件進行解剖,只要獲取到該類的字節碼文件對象即可。

5. 加載類

我們已經知道,main()方法是程序的入口。那是不是在main()方法開始執行之前,所有的class文件都已經加載到方法區中了呢?答案是:NO!通常只有需要執行到使用某個類的代碼時,才會去CLASSPATH中加載class文件,如果程序從頭到尾都沒有使用某個類,那么這個類對應的class文件就不會被加載到內存。

可以導致一個類被加載可能有:

  • 使用一個類的靜態方法;
  • 使用一個類的靜態屬性;
  • 創建這個類的對象;
  • 使用Class.forName()方法加載類;
  • 反序列化一個類的對象;
  • 加載一個類的子類時,也會加載其父類;
  • 加載一個類時,也會加載與該類相關的類。

上面給出的幾個可能也只是可能而已,如果當前類沒有被加載過,才會去加載,如果已經加載到方法區中了,那么就不可能再去加載。

6. Class 字節碼

Class 類的實例表示正在運行的 Java 應用程序中的類和接口。

方法說明
forName()通過類名獲取類的字節碼
getClassLoader()獲取該類的類加載器
getInterfaces()獲取所實現的接口
getSuperclass()獲取父類
getGenericSuperclass()獲取傳遞給父類參數化類型
newInstance()創建實例
getName()獲取類名,接口名
getPackage()獲取包名
isPrimitive()判定指定的 Class 對象是否表示一個基本類型
isArray()判定此 Class 對象是否表示一個數組類
getResourceAsStream()查找具有給定名稱的資源

6.1 獲取注解

方法說明
getAnnotation()獲取指定類型的注解
getAnnotations()獲取所有的注解
getDeclaredAnnotations()獲取除了繼承得到的所有注解

6.2 獲取構造方法

方法說明
getConstructor()獲取指定的非私有的構造方法
getDeclaredConstructor()獲取指定的構造方法
getConstructors()獲取公有的構造方法
getDeclaredConstructors()獲取所有的構造方法

6.3 獲取成員方法

方法說明
getMethod()獲取指定的非私有方法
getDeclaredMethod()獲取指定的方法
getMethods()獲取公有的方法
getDeclaredMethods()獲取所有的方法

6.4 獲取成員變量

方法說明
getField()獲取指定名稱的字段
getFields()獲取公有的字段
getDeclaredField(String name)獲取指定名稱的字段
getDeclaredFields()獲取所有的字段

7. AccessibleObject

AccessibleObject 類是 Field、Method 和 Constructor 對象的基類

方法說明
getAnnotation()獲取指定類型的注解
getAnnotations()獲取所有的注解
getDeclaredAnnotations()獲取除了繼承得到的所有注解
setAccessible(true)暴力反射,取消訪問檢查

8. Constructor

Constructor 提供關于類的單個構造方法的信息以及對它的訪問權限

方法說明
newInstance()通過構造方法創建實例
getParameterTypes()獲取構造器的所有參數的類型
getExceptionTypes()獲取構造器上聲明的所有異常類型
getDeclaringClass()獲取構造器所屬的類型
getModifiers()獲取構造器上的所有修飾符信息

9. Method

表示一個類中的成員方法

方法說明
invoke(Object obj, Object… args)通過方法反射對象調用方法,如果當前方法是實例方法,那么當前對象就是obj,如果當前方法是static方法,那么可以給obj傳遞null。args表示是方法的參數
setAccessible(true)暴力反射,取消訪問檢查
getAnnotation()獲取方法上指定類型的注解
getAnnotations()獲取所有的注解
getDeclaredAnnotations()獲取方法上說所有的注解
getGenericParameterTypes()獲取泛型的參數化類型

10. Field

表示一個類中的成員變量

方法說明
getAnnotation()獲取字段上指定類型的注解
getAnnotations()獲取所有的注解
getDeclaredAnnotations()獲取字段所有的注解
set()給指定字段設置新值
get()獲取字段值
setAccessible(true)暴力反射,取消訪問檢查
getType()獲取字段的類型
getXXX(Object obj)如果當前屬性為基本類型,可以使用getXXX()系列方法獲取基本類型屬性值
setXXX(Object obj, XXX value)如果當前屬性為基本類型,可以使用setXXX()系統方法基本類型屬性值

11. Type

Type 是 Java 編程語言中所有類型的公共高級接口

11.1 ParameterizedType

ParameterizedType 表示參數化類型,如 Collection

方法說明
Type[ ] getActualTypeArguments()獲取真實參數


public abstract class BaseProtocol<T> {.../**泛型解析*/protected T parsejson(String jsonString){ParameterizedType genericSuperclass = (ParameterizedType) getClass().getGenericSuperclass();Type[] args = genericSuperclass.getActualTypeArguments();Type type = args[0];return GsonUtil.changeGsonToBean(jsonString,type);} }

12. Array

Array 類提供了動態創建和訪問 Java 數組的方法

方法說明
Array.getLenght()獲取數組的長度
Array.get()獲取數組中指定索引的值

13. Modifier

Modifier類有一系列的static方法用來解析其他getModifiers()方法返回的int值

Method m = … int m = m.getModifiers(); boolean b1 = Modifier.isAbstract(m);//解析m中是否包含abstract修飾 boolean b2 = Modifier.isStatic(m);//解析m中是否包含static修飾 String s = Modifiers.toString(m);//把所有修飾都轉換成字符串

14. 反射的應用

通過反射獲取構造方法并使用

package cn.itcast_02;import java.lang.reflect.Constructor;/** 需求:通過反射獲取私有構造方法并使用* private Person(String name){}* * Person p = new Person("風清揚");* System.out.println(p);*/ public class ReflectDemo3 {public static void main(String[] args) throws Exception {// 獲取字節碼文件對象Class c = Class.forName("cn.itcast_01.Person");// 獲取私有構造方法對象// NoSuchMethodException:每個這個方法異常// 原因是一開始我們使用的方法只能獲取公共的,下面這種方式就可以了。Constructor con = c.getDeclaredConstructor(String.class);// 用該私有構造方法創建對象// IllegalAccessException:非法的訪問異常。// 暴力訪問con.setAccessible(true);// 值為true則指示反射的對象在使用時應該取消Java語言訪問檢查。Object obj = con.newInstance("風清揚");System.out.println(obj);} }

通過反射獲取成員變量并使用

package cn.itcast_03;import java.lang.reflect.Constructor; import java.lang.reflect.Field;/** 通過發生獲取成員變量并使用*/ public class ReflectDemo {public static void main(String[] args) throws Exception {// 獲取字節碼文件對象Class c = Class.forName("cn.itcast_01.Person");// 獲取所有的成員變量// Field[] fields = c.getFields();// Field[] fields = c.getDeclaredFields();// for (Field field : fields) {// System.out.println(field);// }/** Person p = new Person(); p.address = "北京"; System.out.println(p);*/// 通過無參構造方法創建對象Constructor con = c.getConstructor();Object obj = con.newInstance();System.out.println(obj);// 獲取單個的成員變量// 獲取address并對其賦值Field addressField = c.getField("address");// public void set(Object obj,Object value)// 將指定對象變量上此 Field 對象表示的字段設置為指定的新值。addressField.set(obj, "北京"); // 給obj對象的addressField字段設置值為"北京"System.out.println(obj);// 獲取name并對其賦值// NoSuchFieldExceptionField nameField = c.getDeclaredField("name");// IllegalAccessExceptionnameField.setAccessible(true);nameField.set(obj, "林青霞");System.out.println(obj);// 獲取age并對其賦值Field ageField = c.getDeclaredField("age");ageField.setAccessible(true);ageField.set(obj, 27);System.out.println(obj);} }

通過反射獲取成員方法并使用

package cn.itcast_04;import java.lang.reflect.Constructor; import java.lang.reflect.Method;public class ReflectDemo {public static void main(String[] args) throws Exception {// 獲取字節碼文件對象Class c = Class.forName("cn.itcast_01.Person");// 獲取所有的方法// Method[] methods = c.getMethods(); // 獲取自己的包括父親的公共方法// Method[] methods = c.getDeclaredMethods(); // 獲取自己的所有的方法// for (Method method : methods) {// System.out.println(method);// }Constructor con = c.getConstructor();Object obj = con.newInstance();/** Person p = new Person(); p.show();*/// 獲取單個方法并使用// public void show()// public Method getMethod(String name,Class<?>... parameterTypes)// 第一個參數表示的方法名,第二個參數表示的是方法的參數的class類型Method m1 = c.getMethod("show");// obj.m1(); // 錯誤// public Object invoke(Object obj,Object... args)// 返回值是Object接收,第一個參數表示對象是誰,第二參數表示調用該方法的實際參數m1.invoke(obj); // 調用obj對象的m1方法System.out.println("----------");// public void method(String s)Method m2 = c.getMethod("method", String.class);m2.invoke(obj, "hello");System.out.println("----------");// public String getString(String s, int i)Method m3 = c.getMethod("getString", String.class, int.class);Object objString = m3.invoke(obj, "hello", 100);System.out.println(objString);// String s = (String)m3.invoke(obj, "hello",100);// System.out.println(s);System.out.println("----------");// private void function()Method m4 = c.getDeclaredMethod("function");m4.setAccessible(true);m4.invoke(obj);} }

14.1 反射應用舉例

給ArrayList<Integer>的一個對象,在這個集合中添加一個字符串數據,如何實現呢?

package cn.itcast.test;import java.lang.reflect.InvocationTargetException; import java.lang.reflect.Method; import java.util.ArrayList;/** 我給你ArrayList<Integer>的一個對象,我想在這個集合中添加一個字符串數據,如何實現呢?*/ public class ArrayListDemo {public static void main(String[] args) throws NoSuchMethodException,SecurityException, IllegalAccessException,IllegalArgumentException, InvocationTargetException {// 創建集合對象ArrayList<Integer> array = new ArrayList<Integer>();// array.add("hello");// array.add(10);Class c = array.getClass(); // 集合ArrayList的class文件對象Method m = c.getMethod("add", Object.class);m.invoke(array, "hello"); // 調用array的add方法,傳入的值是hellom.invoke(array, "world");m.invoke(array, "java");System.out.println(array);} }

通過配置文件運行類中的方法

package cn.itcast.test;import java.io.FileReader; import java.lang.reflect.Constructor; import java.lang.reflect.Method; import java.util.Properties;/** 通過配置文件運行類中的方法* * 反射:* 需要有配置文件配合使用。* 用class.txt代替。* 并且你知道有兩個鍵。* className* methodName*/ public class Test {public static void main(String[] args) throws Exception {// 反射前的做法// Student s = new Student();// s.love();// Teacher t = new Teacher();// t.love();// Worker w = new Worker();// w.love();// 反射后的做法// 加載鍵值對數據Properties prop = new Properties();FileReader fr = new FileReader("class.txt");prop.load(fr);fr.close();// 獲取數據String className = prop.getProperty("className");String methodName = prop.getProperty("methodName");// 反射Class c = Class.forName(className);Constructor con = c.getConstructor();Object obj = con.newInstance();// 調用方法Method m = c.getMethod(methodName);m.invoke(obj);} }

寫一個方法:public void setProperty(Object obj, String propertyName, Object value){},此方法可將obj對象中名為propertyName的屬性的值設置為value

package cn.itcast.test;import java.lang.reflect.Field;public class Tool {public void setProperty(Object obj, String propertyName, Object value)throws NoSuchFieldException, SecurityException,IllegalArgumentException, IllegalAccessException {// 根據對象獲取字節碼文件對象Class c = obj.getClass();// 獲取該對象的propertyName成員變量Field field = c.getDeclaredField(propertyName);// 取消訪問檢查field.setAccessible(true);// 給對象的成員變量賦值為指定的值field.set(obj, value);} } package cn.itcast.test;public class ToolDemo {public static void main(String[] args) throws NoSuchFieldException,SecurityException, IllegalArgumentException, IllegalAccessException {Person p = new Person();Tool t = new Tool();t.setProperty(p, "name", "林青霞");t.setProperty(p, "age", 27);System.out.println(p);System.out.println("-----------");Dog d = new Dog();t.setProperty(d, "sex", '男');t.setProperty(d, "price", 12.34f);System.out.println(d);} }class Dog {char sex;float price;@Overridepublic String toString() {return sex + "---" + price;} }class Person {private String name;public int age;@Overridepublic String toString() {return name + "---" + age;} }

總結

以上是生活随笔為你收集整理的Java基础:反射的全部內容,希望文章能夠幫你解決所遇到的問題。

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

主站蜘蛛池模板: 天堂毛片 | av一二区 | 国产精品女同一区二区 | 韩日视频在线观看 | 一级免费黄色片 | 国产人妖av | 亚洲黄业| 黄色99视频| 四季av一区二区三区免费观看 | 中文国产在线观看 | 欧美情侣性视频 | 影视av| 亚洲综合在线中文字幕 | 手机午夜视频 | 国产丝袜在线 | 亚色在线观看 | 一区二区在线观看视频 | 三及毛片| 亚洲 欧美 日韩系列 | 欧美在线视频你懂的 | 日本黄色免费网站 | 男女网站在线观看 | 亚洲三区在线观看无套内射 | 谁有免费黄色网址 | 综合网激情 | 久久国产情侣 | 久久综合在线 | 亚洲国产精品成人无久久精品 | 久久一区二区三区四区 | 国产极品久久 | 91在线观 | 欧美一级视频 | 久久久久精 | www欧美精品 | 国产一级片在线播放 | 三上悠亚ed2k| 活大器粗np高h一女多夫 | 亚洲在线视频观看 | 亚洲另类在线观看 | 婷婷五月综合久久中文字幕 | 久久羞羞 | 伊人久久大香线 | 欧美另类在线播放 | 精品在线二区 | 国产av精国产传媒 | 无码国产精品一区二区色情男同 | 杨贵妃颤抖双乳呻吟求欢小说 | 日本人性爱视频 | 蜜桃视频免费网站 | 色老头一区二区三区 | 国产精品免费久久久 | 欧美性大战久久久 | 久久一级电影 | 欧美日韩国产三区 | 午夜视频国产 | 91麻豆精品一二三区在线 | 手机av电影在线 | 日本少妇影院 | 天天做夜夜爽 | 亚洲一区在线视频观看 | 免费国产精品视频 | 一边摸一边做爽的视频17国产 | 久久久看 | 经典杯子蛋糕日剧在线观看免费 | 色图插插插 | 欧美激情性做爰免费视频 | www日本xxx | 狠操av | 99re6热在线精品视频播放 | 欧美日韩二区三区 | 精品三级视频 | av一卡| 思思精品视频 | av久热| 久久久久亚洲日日精品 | 国产乱人伦 | 免费看一级 | 亚洲青涩 | 亚洲美女偷拍 | 亚洲成人福利在线 | 黑人与亚洲人色ⅹvideos | 日韩六区 | 在线国产小视频 | 黄频在线 | 亚洲精品无码不卡在线播he | 久久精品店 | 亚洲欧美日本国产 | 色婷婷小说 | 欧美三级成人 | 国产一级片免费在线观看 | 91精品系列 | 三级在线免费 | 成人爱爱 | 亚洲欧美第一 | 亚洲一区二区三区四 | 久久99久久久久 | bbbbbxxxxx性欧美 | 男人的天堂手机在线 | 免费淫片|