最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

Java基礎(chǔ)學(xué)習(xí)之反射機(jī)制原理詳解

 更新時(shí)間:2022年04月06日 16:30:48   作者:張維鵬  
反射是框架的靈魂,Java框架底層都是用反射機(jī)制+xml配置等來實(shí)現(xiàn)的,本文將通過示例詳細(xì)講解Java中的反射機(jī)制,感興趣的小伙伴可以跟隨小編學(xué)習(xí)一下

一、什么是反射

(1)Java反射機(jī)制的核心是在程序運(yùn)行時(shí)動態(tài)加載類并獲取類的詳細(xì)信息,從而操作類或?qū)ο蟮膶傩院头椒ā1举|(zhì)是JVM得到class對象之后,再通過class對象進(jìn)行反編譯,從而獲取對象的各種信息。

(2)Java屬于先編譯再運(yùn)行的語言,程序中對象的類型在編譯期就確定下來了,而當(dāng)程序在運(yùn)行時(shí)可能需要動態(tài)加載某些類,這些類因?yàn)橹坝貌坏剑詻]有被加載到JVM。通過反射,可以在運(yùn)行時(shí)動態(tài)地創(chuàng)建對象并調(diào)用其屬性,不需要提前在編譯期知道運(yùn)行的對象是誰。

二、反射的原理

下圖是類的正常加載過程、反射原理與class對象:

Class對象的由來是將.class文件讀入內(nèi)存,并為之創(chuàng)建一個(gè)Class對象。

三、反射的優(yōu)缺點(diǎn)

1、優(yōu)點(diǎn):在運(yùn)行時(shí)獲得類的各種內(nèi)容,進(jìn)行反編譯,對于Java這種先編譯再運(yùn)行的語言,能夠讓我們很方便的創(chuàng)建靈活的代碼,這些代碼可以在運(yùn)行時(shí)裝配,無需在組件之間進(jìn)行源代碼的鏈接,更加容易實(shí)現(xiàn)面向?qū)ο蟆?/p>

2、缺點(diǎn):(1)反射會消耗一定的系統(tǒng)資源,因此,如果不需要動態(tài)地創(chuàng)建一個(gè)對象,那么就不需要用反射;

(2)反射調(diào)用方法時(shí)可以忽略權(quán)限檢查,因此可能會破壞封裝性而導(dǎo)致安全問題。

四、反射的用途

1、反編譯:.class-->.java

2、通過反射機(jī)制訪問java對象的屬性,方法,構(gòu)造方法等

3、當(dāng)我們在使用IDE,比如Ecplise時(shí),當(dāng)我們輸入一個(gè)對象或者類,并想調(diào)用他的屬性和方法是,一按點(diǎn)號,編譯器就會自動列出他的屬性或者方法,這里就是用到反射。

4、反射最重要的用途就是開發(fā)各種通用框架。比如很多框架(Spring)都是配置化的(比如通過XML文件配置Bean),為了保證框架的通用性,他們可能需要根據(jù)配置文件加載不同的類或者對象,調(diào)用不同的方法,這個(gè)時(shí)候就必須使用到反射了,運(yùn)行時(shí)動態(tài)加載需要的加載的對象。

5、例如,在使用Strut2框架的開發(fā)過程中,我們一般會在struts.xml里去配置Action,比如

<action name="login" class="org.ScZyhSoft.test.action.SimpleLoginAction" method="execute">   
    <result>/shop/shop-index.jsp</result>           
    <result name="error">login.jsp</result>       
</action>

比如我們請求login.action時(shí),那么StrutsPrepareAndExecuteFilter就會去解析struts.xml文件,從action中查找出name為login的Action,并根據(jù)class屬性創(chuàng)建SimpleLoginAction實(shí)例,并用Invoke方法來調(diào)用execute方法,這個(gè)過程離不開反射。配置文件與Action建立了一種映射關(guān)系,當(dāng)View層發(fā)出請求時(shí),請求會被StrutsPrepareAndExecuteFilter攔截,然后StrutsPrepareAndExecuteFilter會去動態(tài)地創(chuàng)建Action實(shí)例。

比如,加載數(shù)據(jù)庫驅(qū)動的,用到的也是反射。

Class.forName("com.mysql.jdbc.Driver"); // 動態(tài)加載mysql驅(qū)動

五、反射機(jī)制常用的類

Java.lang.Class;

Java.lang.reflect.Constructor;

Java.lang.reflect.Field;

Java.lang.reflect.Method;

Java.lang.reflect.Modifier;

六、反射的基本使用

1、獲得Class:主要有三種方法:

(1)Object-->getClass

(2)任何數(shù)據(jù)類型(包括基本的數(shù)據(jù)類型)都有一個(gè)“靜態(tài)”的class屬性

(3)通過class類的靜態(tài)方法:forName(String className)(最常用)

package fanshe;
 
public class Fanshe {
    public static void main(String[] args) {
        //第一種方式獲取Class對象  
        Student stu1 = new Student();//這一new 產(chǎn)生一個(gè)Student對象,一個(gè)Class對象。
        Class stuClass = stu1.getClass();//獲取Class對象
        System.out.println(stuClass.getName());
        
        //第二種方式獲取Class對象
        Class stuClass2 = Student.class;
        System.out.println(stuClass == stuClass2);//判斷第一種方式獲取的Class對象和第二種方式獲取的是否是同一個(gè)
        
        //第三種方式獲取Class對象
        try {
            Class stuClass3 = Class.forName("fanshe.Student");//注意此字符串必須是真實(shí)路徑,就是帶包名的類路徑,包名.類名
            System.out.println(stuClass3 == stuClass2);//判斷三種方式是否獲取的是同一個(gè)Class對象
        } catch (ClassNotFoundException e) {
            e.printStackTrace();
        }
        
    }
}

注意,在運(yùn)行期間,一個(gè)類,只有一個(gè)Class對象產(chǎn)生,所以打印結(jié)果都是true;

三種方式中,常用第三種,第一種對象都有了還要反射干什么,第二種需要導(dǎo)入類包,依賴太強(qiáng),不導(dǎo)包就拋編譯錯(cuò)誤。一般都使用第三種,一個(gè)字符串可以傳入也可以寫在配置文件中等多種方法。

2、判斷是否為某個(gè)類的示例:

一般的,我們使用instanceof 關(guān)鍵字來判斷是否為某個(gè)類的實(shí)例。同時(shí)我們也可以借助反射中Class對象的isInstance()方法來判斷時(shí)候?yàn)槟硞€(gè)類的實(shí)例,他是一個(gè)native方法。

public native boolean isInstance(Object obj);

3、創(chuàng)建實(shí)例:通過反射來生成對象主要有兩種方法:

(1)使用Class對象的newInstance()方法來創(chuàng)建Class對象對應(yīng)類的實(shí)例。

Class<?> c = String.class;
Object str = c.newInstance();

(2)先通過Class對象獲取指定的Constructor對象,再調(diào)用Constructor對象的newInstance()方法來創(chuàng)建對象,這種方法可以用指定的構(gòu)造器構(gòu)造類的實(shí)例。

//獲取String的Class對象
Class<?> str = String.class;
//通過Class對象獲取指定的Constructor構(gòu)造器對象
Constructor constructor=c.getConstructor(String.class);
//根據(jù)構(gòu)造器創(chuàng)建實(shí)例:
Object obj = constructor.newInstance(“hello reflection”);

4、通過反射獲取構(gòu)造方法并使用:

(1)批量獲取的方法:

public Constructor[] getConstructors():所有"公有的"構(gòu)造方法

public Constructor[] getDeclaredConstructors():獲取所有的構(gòu)造方法(包括私有、受保護(hù)、默認(rèn)、公有)

(2)單個(gè)獲取的方法,并調(diào)用:

public Constructor getConstructor(Class... parameterTypes):獲取單個(gè)的"公有的"構(gòu)造方法:

public Constructor getDeclaredConstructor(Class... parameterTypes):獲取"某個(gè)構(gòu)造方法"可以是私有的,或受保護(hù)、默認(rèn)、公有;

(3) 調(diào)用構(gòu)造方法:

Constructor-->newInstance(Object... initargs)

newInstance是 Constructor類的方法(管理構(gòu)造函數(shù)的類)

api的解釋為:newInstance(Object... initargs) ,使用此 Constructor 對象表示的構(gòu)造方法來創(chuàng)建該構(gòu)造方法的聲明類的新實(shí)例,并用指定的初始化參數(shù)初始化該實(shí)例。

它的返回值是T類型,所以newInstance是創(chuàng)建了一個(gè)構(gòu)造方法的聲明類的新實(shí)例對象,并為之調(diào)用。

例子:

Student類:共六個(gè)構(gòu)造方法。

package fanshe;
public class Student {
	//---------------構(gòu)造方法-------------------
	//(默認(rèn)的構(gòu)造方法)
	Student(String str){
		System.out.println("(默認(rèn))的構(gòu)造方法 s = " + str);
	}
	//無參構(gòu)造方法
	public Student(){
		System.out.println("調(diào)用了公有、無參構(gòu)造方法執(zhí)行了。。。");
	}
	//有一個(gè)參數(shù)的構(gòu)造方法
	public Student(char name){
		System.out.println("姓名:" + name);
	}
	//有多個(gè)參數(shù)的構(gòu)造方法
	public Student(String name ,int age){
		System.out.println("姓名:"+name+"年齡:"+ age);//這的執(zhí)行效率有問題,以后解決。
	}
	//受保護(hù)的構(gòu)造方法
	protected Student(boolean n){
		System.out.println("受保護(hù)的構(gòu)造方法 n = " + n);
	}
	//私有構(gòu)造方法
	private Student(int age){
		System.out.println("私有的構(gòu)造方法   年齡:"+ age);
	}
}

測試類:

package fanshe;
import java.lang.reflect.Constructor;
 
/*
 * 通過Class對象可以獲取某個(gè)類中的:構(gòu)造方法、成員變量、成員方法;并訪問成員;
 * 
 * 1.獲取構(gòu)造方法:
 * 		1).批量的方法:
 * 			public Constructor[] getConstructors():所有"公有的"構(gòu)造方法
            public Constructor[] getDeclaredConstructors():獲取所有的構(gòu)造方法(包括私有、受保護(hù)、默認(rèn)、公有)
 * 		2).獲取單個(gè)的方法,并調(diào)用:
 * 			public Constructor getConstructor(Class... parameterTypes):獲取單個(gè)的"公有的"構(gòu)造方法:
 * 			public Constructor getDeclaredConstructor(Class... parameterTypes):獲取"某個(gè)構(gòu)造方法"可以是私有的,或受保護(hù)、默認(rèn)、公有; 		
 * 		3).調(diào)用構(gòu)造方法:
 * 			Constructor-->newInstance(Object... initargs)
 */
public class Constructors {
 
	public static void main(String[] args) throws Exception {
		//1.加載Class對象
		Class clazz = Class.forName("fanshe.Student");
		
		//2.獲取所有公有構(gòu)造方法
		System.out.println("**********************所有公有構(gòu)造方法*********************************");
		Constructor[] conArray = clazz.getConstructors();
		for(Constructor c : conArray){
			System.out.println(c);
		}
		
		System.out.println("************所有的構(gòu)造方法(包括:私有、受保護(hù)、默認(rèn)、公有)***************");
		conArray = clazz.getDeclaredConstructors();
		for(Constructor c : conArray){
			System.out.println(c);
		}
		
		System.out.println("*****************獲取公有、無參的構(gòu)造方法*******************************");
		Constructor con = clazz.getConstructor(null);
		//1>、因?yàn)槭菬o參的構(gòu)造方法所以類型是一個(gè)null,不寫也可以:這里需要的是一個(gè)參數(shù)的類型,切記是類型
		//2>、返回的是描述這個(gè)無參構(gòu)造函數(shù)的類對象。
		System.out.println("con = " + con);
 
		//調(diào)用構(gòu)造方法
		Object obj = con.newInstance();
	//	System.out.println("obj = " + obj);
	//	Student stu = (Student)obj;
		
		System.out.println("******************獲取私有構(gòu)造方法,并調(diào)用*******************************");
		con = clazz.getDeclaredConstructor(char.class);
		System.out.println(con);
		//調(diào)用構(gòu)造方法
		con.setAccessible(true);//暴力訪問(忽略掉訪問修飾符)
		obj = con.newInstance('男');
	}
}

控制臺輸出:

**********************所有公有構(gòu)造方法*********************************
public fanshe.Student(java.lang.String,int)
public fanshe.Student(char)
public fanshe.Student()
************所有的構(gòu)造方法(包括:私有、受保護(hù)、默認(rèn)、公有)***************
private fanshe.Student(int)
protected fanshe.Student(boolean)
public fanshe.Student(java.lang.String,int)
public fanshe.Student(char)
public fanshe.Student()
fanshe.Student(java.lang.String)
*****************獲取公有、無參的構(gòu)造方法*******************************
con = public fanshe.Student()
調(diào)用了公有、無參構(gòu)造方法執(zhí)行了。。。
******************獲取私有構(gòu)造方法,并調(diào)用*******************************
public fanshe.Student(char)
姓名:男

5、獲取成員變量并調(diào)用:

Student類:

package fanshe.field;
 
public class Student {
	public Student(){
		
	}
	//**********字段*************//
	public String name;
	protected int age;
	char sex;
	private String phoneNum;
	
	@Override
	public String toString() {
		return "Student [name=" + name + ", age=" + age + ", sex=" + sex
				+ ", phoneNum=" + phoneNum + "]";
	}
}

測試類:

package fanshe.field;
import java.lang.reflect.Field;
/*
 * 獲取成員變量并調(diào)用:
 * 
 * 1.批量的
 *         1).Field[] getFields():獲取所有的"公有字段"
 *         2).Field[] getDeclaredFields():獲取所有字段,包括:私有、受保護(hù)、默認(rèn)、公有;
 * 2.獲取單個(gè)的:
 *         1).public Field getField(String fieldName):獲取某個(gè)"公有的"字段;
 *         2).public Field getDeclaredField(String fieldName):獲取某個(gè)字段(可以是私有的)
 * 
 *      設(shè)置字段的值:
 *         Field --> public void set(Object obj,Object value):
 *                     參數(shù)說明:
 *                     1.obj:要設(shè)置的字段所在的對象;
 *                     2.value:要為字段設(shè)置的值;
 */
public class Fields {
 
        public static void main(String[] args) throws Exception {
            //1.獲取Class對象
            Class stuClass = Class.forName("fanshe.field.Student");
            //2.獲取字段
            System.out.println("************獲取所有公有的字段********************");
            Field[] fieldArray = stuClass.getFields();
            for(Field f : fieldArray){
                System.out.println(f);
            }
            System.out.println("************獲取所有的字段(包括私有、受保護(hù)、默認(rèn)的)********************");
            fieldArray = stuClass.getDeclaredFields();
            for(Field f : fieldArray){
                System.out.println(f);
            }
            System.out.println("*************獲取公有字段**并調(diào)用***********************************");
            Field f = stuClass.getField("name");
            System.out.println(f);
            //獲取一個(gè)對象
            Object obj = stuClass.getConstructor().newInstance();//產(chǎn)生Student對象--》Student stu = new Student();
            //為字段設(shè)置值
            f.set(obj, "劉德華");//為Student對象中的name屬性賦值--》stu.name = "劉德華"
            //驗(yàn)證
            Student stu = (Student)obj;
            System.out.println("驗(yàn)證姓名:" + stu.name);
            
            
            System.out.println("**************獲取私有字段****并調(diào)用********************************");
            f = stuClass.getDeclaredField("phoneNum");
            System.out.println(f);
            f.setAccessible(true);//暴力反射,解除私有限定
            f.set(obj, "18888889999");
            System.out.println("驗(yàn)證電話:" + stu);
            
        }
    }

控制臺輸出:

************獲取所有公有的字段********************
public java.lang.String fanshe.field.Student.name
************獲取所有的字段(包括私有、受保護(hù)、默認(rèn)的)********************
public java.lang.String fanshe.field.Student.name
protected int fanshe.field.Student.age
char fanshe.field.Student.sex
private java.lang.String fanshe.field.Student.phoneNum
*************獲取公有字段**并調(diào)用***********************************
public java.lang.String fanshe.field.Student.name
驗(yàn)證姓名:劉德華
**************獲取私有字段****并調(diào)用********************************
private java.lang.String fanshe.field.Student.phoneNum
驗(yàn)證電話:Student [name=劉德華, age=0, sex=

6、獲取成員方法并調(diào)用:

Student類:

package fanshe.method;
 
public class Student {
    //**************成員方法***************//
    public void show1(String s){
        System.out.println("調(diào)用了:公有的,String參數(shù)的show1(): s = " + s);
    }
    protected void show2(){
        System.out.println("調(diào)用了:受保護(hù)的,無參的show2()");
    }
    void show3(){
        System.out.println("調(diào)用了:默認(rèn)的,無參的show3()");
    }
    private String show4(int age){
        System.out.println("調(diào)用了,私有的,并且有返回值的,int參數(shù)的show4(): age = " + age);
        return "abcd";
    }
}

測試類:

package fanshe.method;
import java.lang.reflect.Method;
 
/*
 * 獲取成員方法并調(diào)用:
 * 
 * 1.批量的:
 *         public Method[] getMethods():獲取所有"公有方法";(包含了父類的方法也包含Object類)
 *         public Method[] getDeclaredMethods():獲取所有的成員方法,包括私有的(不包括繼承的)
 * 2.獲取單個(gè)的:
 *         public Method getMethod(String name,Class<?>... parameterTypes):
 *                     參數(shù):
 *                         name : 方法名;
 *                         Class ... : 形參的Class類型對象
 *         public Method getDeclaredMethod(String name,Class<?>... parameterTypes)
 * 
 *      調(diào)用方法:
 *         Method --> public Object invoke(Object obj,Object... args):
 *                     參數(shù)說明:
 *                     obj : 要調(diào)用方法的對象;
 *                     args:調(diào)用方式時(shí)所傳遞的實(shí)參;
):
 */
public class MethodClass {
 
    public static void main(String[] args) throws Exception {
        //1.獲取Class對象
        Class stuClass = Class.forName("fanshe.method.Student");
        //2.獲取所有公有方法
        System.out.println("***************獲取所有的”公有“方法*******************");
        stuClass.getMethods();
        Method[] methodArray = stuClass.getMethods();
        for(Method m : methodArray){
            System.out.println(m);
        }
        System.out.println("***************獲取所有的方法,包括私有的*******************");
        methodArray = stuClass.getDeclaredMethods();
        for(Method m : methodArray){
            System.out.println(m);
        }
        System.out.println("***************獲取公有的show1()方法*******************");
        Method m = stuClass.getMethod("show1", String.class);
        System.out.println(m);
        //實(shí)例化一個(gè)Student對象
        Object obj = stuClass.getConstructor().newInstance();
        m.invoke(obj, "劉德華");
        
        System.out.println("***************獲取私有的show4()方法******************");
        m = stuClass.getDeclaredMethod("show4", int.class);
        System.out.println(m);
        m.setAccessible(true);//解除私有限定
        Object result = m.invoke(obj, 20);//需要兩個(gè)參數(shù),一個(gè)是要調(diào)用的對象(獲取有反射),一個(gè)是實(shí)參
        System.out.println("返回值:" + result);    
    }
}

控制臺輸出:

***************獲取所有的”公有“方法*******************
public void fanshe.method.Student.show1(java.lang.String)
public final void java.lang.Object.wait(long,int) throws java.lang.InterruptedException
public final native void java.lang.Object.wait(long) throws java.lang.InterruptedException
public final void java.lang.Object.wait() throws java.lang.InterruptedException
public boolean java.lang.Object.equals(java.lang.Object)
public java.lang.String java.lang.Object.toString()
public native int java.lang.Object.hashCode()
public final native java.lang.Class java.lang.Object.getClass()
public final native void java.lang.Object.notify()
public final native void java.lang.Object.notifyAll()
***************獲取所有的方法,包括私有的*******************
public void fanshe.method.Student.show1(java.lang.String)
private java.lang.String fanshe.method.Student.show4(int)
protected void fanshe.method.Student.show2()
void fanshe.method.Student.show3()
***************獲取公有的show1()方法*******************
public void fanshe.method.Student.show1(java.lang.String)
調(diào)用了:公有的,String參數(shù)的show1(): s = 劉德華
***************獲取私有的show4()方法******************
private java.lang.String fanshe.method.Student.show4(int)
調(diào)用了,私有的,并且有返回值的,int參數(shù)的show4(): age = 20
返回值:abcd

7、反射main方法:

Student類:

package fanshe.main;
 
public class Student {
    public static void main(String[] args) {
        System.out.println("main方法執(zhí)行了。。。");
    }
}

測試類:

package fanshe.main;
import java.lang.reflect.Method;
 
/**
 * 獲取Student類的main方法、不要與當(dāng)前的main方法搞混了
 */
public class Main {
    
    public static void main(String[] args) {
        try {
            //1、獲取Student對象的字節(jié)碼
            Class clazz = Class.forName("fanshe.main.Student");
            
            //2、獲取main方法
             Method methodMain = clazz.getMethod("main", String[].class);//第一個(gè)參數(shù):方法名稱,第二個(gè)參數(shù):方法形參的類型,
            //3、調(diào)用main方法
            // methodMain.invoke(null, new String[]{"a","b","c"});
             //第一個(gè)參數(shù),對象類型,因?yàn)榉椒ㄊ莝tatic靜態(tài)的,所以為null可以,第二個(gè)參數(shù)是String數(shù)組,這里要注意在jdk1.4時(shí)是數(shù)組,jdk1.5之后是可變參數(shù)
             //這里拆的時(shí)候?qū)? new String[]{"a","b","c"} 拆成3個(gè)對象。。。所以需要將它強(qiáng)轉(zhuǎn)。
             methodMain.invoke(null, (Object)new String[]{"a","b","c"});//方式一
            // methodMain.invoke(null, new Object[]{new String[]{"a","b","c"}});//方式二            
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
}

控制臺輸出:

main方法執(zhí)行了。。。

8、利用反射創(chuàng)建數(shù)值:

數(shù)組在Java里是比較特殊的一種類型,它可以賦值給一個(gè)Object Reference。

public static void testArray() throws ClassNotFoundException {
        Class<?> cls = Class.forName("java.lang.String");
        Object array = Array.newInstance(cls,25);
        //往數(shù)組里添加內(nèi)容
        Array.set(array,0,"golang");
        Array.set(array,1,"Java");
        Array.set(array,2,"pytho");
        Array.set(array,3,"Scala");
        Array.set(array,4,"Clojure");
        //獲取某一項(xiàng)的內(nèi)容
        System.out.println(Array.get(array,3));
    }

9、反射方法的其他使用--通過反射運(yùn)行配置文件內(nèi)容:

Student類:

public class Student {
    public void show(){
        System.out.println("is show()");
    }
}

配置文件以txt文件為例子:

className = cn.fanshe.Student
methodName = show

測試類:

import java.io.FileNotFoundException;
import java.io.FileReader;
import java.io.IOException;
import java.lang.reflect.Method;
import java.util.Properties;
 
/*
 * 我們利用反射和配置文件,可以使:應(yīng)用程序更新時(shí),對源碼無需進(jìn)行任何修改
 * 我們只需要將新類發(fā)送給客戶端,并修改配置文件即可
 */
public class Demo {
    public static void main(String[] args) throws Exception {
        //通過反射獲取Class對象
        Class stuClass = Class.forName(getValue("className"));//"cn.fanshe.Student"
        //2獲取show()方法
        Method m = stuClass.getMethod(getValue("methodName"));//show
        //3.調(diào)用show()方法
        m.invoke(stuClass.getConstructor().newInstance());
        
    }
    
    //此方法接收一個(gè)key,在配置文件中獲取相應(yīng)的value
    public static String getValue(String key) throws IOException{
        Properties pro = new Properties();//獲取配置文件的對象
        FileReader in = new FileReader("pro.txt");//獲取輸入流
        pro.load(in);//將流加載到配置文件對象中
        in.close();
        return pro.getProperty(key);//返回根據(jù)key獲取的value值
    }
}

控制臺輸出:

is show()

需求:

當(dāng)我們升級這個(gè)系統(tǒng)時(shí),不要Student類,而需要新寫一個(gè)Student2的類時(shí),這時(shí)只需要更改pro.txt的文件內(nèi)容就可以了。代碼就一點(diǎn)不用改動。

public class Student2 {
    public void show2(){
        System.out.println("is show2()");
    }
}

配置文件更改為:

className = cn.fanshe.Student2
methodName = show2

10、反射方法的其他使用--通過反射越過泛型檢查:

泛型用在編譯期,編譯過后泛型擦除(消失掉),所以是可以通過反射越過泛型檢查的

測試類:

import java.lang.reflect.Method;
import java.util.ArrayList;
 
/*
 * 通過反射越過泛型檢查
 * 例如:有一個(gè)String泛型的集合,怎樣能向這個(gè)集合中添加一個(gè)Integer類型的值?
 */
public class Demo {
    public static void main(String[] args) throws Exception{
        ArrayList<String> strList = new ArrayList<>();
        strList.add("aaa");
        strList.add("bbb");
        
    //    strList.add(100);
        //獲取ArrayList的Class對象,反向的調(diào)用add()方法,添加數(shù)據(jù)
        Class listClass = strList.getClass(); //得到 strList 對象的字節(jié)碼 對象
        //獲取add()方法
        Method m = listClass.getMethod("add", Object.class);
        //調(diào)用add()方法
        m.invoke(strList, 100);
        
        //遍歷集合
        for(Object obj : strList){
            System.out.println(obj);
        }
    }
}

控制臺輸出:

aaa
bbb
100

到此這篇關(guān)于Java十分鐘精通反射機(jī)制原理的文章就介紹到這了,更多相關(guān)Java 反射機(jī)制內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!

相關(guān)文章

  • java金錢處理方法實(shí)例詳解

    java金錢處理方法實(shí)例詳解

    這篇文章主要介紹了java金錢處理方法實(shí)例詳解的相關(guān)資料,這里提供實(shí)現(xiàn)方法分轉(zhuǎn)化成元的實(shí)現(xiàn)方法,需要的朋友可以參考下
    2017-08-08
  • springboot使JUL實(shí)現(xiàn)日志管理功能

    springboot使JUL實(shí)現(xiàn)日志管理功能

    這篇文章主要介紹了springboot使JUL實(shí)現(xiàn)日志管理功能,本文分步驟給大家介紹的非常詳細(xì),對大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下
    2020-09-09
  • java避免死鎖的常見方法代碼解析

    java避免死鎖的常見方法代碼解析

    這篇文章主要介紹了java避免死鎖的常見方法代碼解析,具有一定借鑒價(jià)值,需要的朋友可以參考下
    2018-01-01
  • SpringBoot測試之高級配置方式

    SpringBoot測試之高級配置方式

    這篇文章主要介紹了SpringBoot測試之高級配置方式,具有很好的參考價(jià)值,希望對大家有所幫助,如有錯(cuò)誤或未考慮完全的地方,望不吝賜教
    2024-04-04
  • SpringBoot項(xiàng)目的五種創(chuàng)建方式

    SpringBoot項(xiàng)目的五種創(chuàng)建方式

    這篇文章主要介紹了SpringBoot項(xiàng)目的五種創(chuàng)建方式,文中通過圖文結(jié)合的方式講解的非常詳細(xì),對大家的學(xué)習(xí)或工作有一定的幫助,需要的朋友可以參考下
    2024-12-12
  • ES結(jié)合java代碼聚合查詢詳細(xì)示例

    ES結(jié)合java代碼聚合查詢詳細(xì)示例

    es查詢有一個(gè)很常用的一種叫聚合查詢,相當(dāng)于mysql中的分組group by 后拿各組數(shù)量進(jìn)行統(tǒng)計(jì),實(shí)現(xiàn)起來也是很簡單,下面這篇文章主要給大家介紹了關(guān)于ES結(jié)合java代碼聚合查詢的相關(guān)資料,需要的朋友可以參考下
    2023-05-05
  • 詳解java的四舍五入與保留位示例

    詳解java的四舍五入與保留位示例

    本篇文章主要介紹了java的四舍五入與保留位示例,小編覺得挺不錯(cuò)的,現(xiàn)在分享給大家,也給大家做個(gè)參考。一起跟隨小編過來看看吧
    2017-08-08
  • Java中Boolean引發(fā)缺陷的解決

    Java中Boolean引發(fā)缺陷的解決

    本文主要介紹了Java中Boolean引發(fā)缺陷的解決,文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧
    2023-06-06
  • java通過url下載文件并輸出的方法

    java通過url下載文件并輸出的方法

    下面小編就為大家分享一篇java通過url下載文件并輸出的方法,具有很好的參考價(jià)值,希望對大家有所幫助。一起跟隨小編過來看看吧
    2018-01-01
  • SpringBoot自定義starter啟動器的實(shí)現(xiàn)思路

    SpringBoot自定義starter啟動器的實(shí)現(xiàn)思路

    這篇文章主要介紹了SpringBoot如何自定義starter啟動器,通過starter的自定義過程,能夠加深大家對SpringBoot自動配置原理的理解,需要的朋友可以參考下
    2022-10-10

最新評論

河西区| 余姚市| 井冈山市| 汉源县| 九龙城区| 黑山县| 馆陶县| 昌黎县| 汉源县| 宣城市| 吴忠市| 德江县| 绍兴市| 广河县| 芦溪县| 民和| 日喀则市| 莱阳市| 巴楚县| 曲阜市| 简阳市| 江华| 沧源| 凤台县| 巴东县| 安达市| 石首市| 卢龙县| 龙井市| 曲阜市| 苍溪县| 加查县| 福海县| 漳州市| 拉萨市| 富裕县| 丹阳市| 农安县| 灵石县| 西藏| 彭阳县|