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

java中的反射及其優(yōu)點說明

 更新時間:2022年05月11日 14:34:03   作者:TimeTDIT  
這篇文章主要介紹了java中的反射及其優(yōu)點說明,具有很好的參考價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教

java反射及優(yōu)點

反射是java的一大特性,而且是有些框架實現(xiàn)了IoC/DI的原理,本文就來探討下java中的反射及其優(yōu)點。

首先是普通的java靜態(tài)類加載,java靜態(tài)類是通過new實現(xiàn)的,在編譯時刻就要加載所有可能用到的類,這樣實際上存在一些缺點的,比如只要有一個類沒有找到或者出現(xiàn)重大的問題編譯便不會通過,導(dǎo)致其他存在的類也無法使用。另一方面,如果要加載其他的類就要重新進(jìn)行編譯,有的時候是非常不方便的。下面就引入反射機制來動態(tài)加載類來解決這個問題。

首先創(chuàng)建一個ClassInterface接口,放在com.classTest包下:

package com.classTest;?
public interface ClassInterface {
? ? public void start(); ? ? ? //接口約定start()方法
}

然后分別使用Class1Impl和Class2Impl類去實現(xiàn)這個接口,也放在com.classTest包下:

package com.classTest;?
public class Class1Impl implements ClassInterface {
?
? ? @Override
? ? public void start() {
? ? ? ? // TODO Auto-generated method stub
? ? ? ? System.out.println("This is Class1Impl"); ? //實現(xiàn)start()
? ? }
}
package com.classTest;?
public class Class2Impl implements ClassInterface {
?
? ? @Override
? ? public void start() {
? ? ? ? // TODO Auto-generated method stub
? ? ? ? System.out.println("This is Class2Impl"); ? //實現(xiàn)start()
? ? }?
}

下面先用正常的類加載來說明正常類加載的缺點:

package com.test;?
import java.util.Scanner;?
import com.classTest.ClassInterface;
?
public class LoadClassTest {
? ? ClassInterface c1 = new Class1Impl();
? ? ClassInterface c2 = new Class2Impl();
? ? c1.start();
? ? c2.start();
}

上面是正常的new方法生成的對象,然后調(diào)用接口里的方法,但是一旦Class1Impl類或者Class2Impl類沒有,那有的哪個類也就無法使用,而且想要使用新的ClassInterface接口下的方法還是需要重新寫類,重新寫測試方法,重新生成測試對象,重新編譯...

下面介紹利用反射機制動態(tài)加載類來解決這個問題:

package com.test;?
import java.util.Scanner;?
import com.classTest.ClassInterface;
?
public class LoadClassTest {
? ? public static void main(String[] args) throws InstantiationException, IllegalAccessException, ClassNotFoundException{
? ? ? ? //new 創(chuàng)建對象是靜態(tài)加載類,在編譯時刻就需要加載所有可能用到的類
? ? ? ? //動態(tài)記載類可以解決這個問題
? ? ? ? Scanner sc = new Scanner(System.in);
? ? ? ? String className = sc.nextLine();
? ? ? ? //動態(tài)加載類,在運行的時刻進(jìn)行加載
? ? ? ? //使用類類型(class type) 通過Class這個類的forName(className)方法動態(tài)創(chuàng)建類對象
? ? ? ? Class c = Class.forName(className);
? ? ? ? //通過類類型 用newInstance()方法創(chuàng)建該類對象
? ? ? ? ClassInterface ci = (ClassInterface) c.newInstance();
? ? ? ? ci.start();//動態(tài)加載類 調(diào)用其方法
? ? }
}

有沒有看出這其中的差異,想要加載其他類只需要輸入另外的類名即可(這里的類名是包含包的),forName()方法可以通過類名動態(tài)創(chuàng)建類類型的對象,然后用類類型的對象的newInstance()方法創(chuàng)建該類類型對象(也就是一個類)的對象(調(diào)用newInstance()方法的類類型對象需要進(jìn)行轉(zhuǎn)化),之后就可以用生成對象調(diào)用接口下的方法了。

那這時候可能就會有人問了,要是在我們不知道接口名稱為ClassInterface的情況下,我們該如何訪問className這個類類型生成的c這個類對象下面的方法呢?我們來實現(xiàn)一下:

Class c = Class.forName("com.classTest.Foo");//創(chuàng)建一個類對象c
Method m1 = c.getMethod("fun1", int.class,int.class);//通過getMethod方法獲取c的方法,第一個參數(shù)表示想要獲取的方法名稱fun1,之后的參數(shù)列表表示fun1這個函數(shù)的所有參數(shù)的類類型。
Object o = m1.invoke(foo1,new Object[]{10,20} );//通過invoke方法來調(diào)用我們前面通過getMethod()獲得的方法,第一個參數(shù)表示執(zhí)行我們所獲得方法的對象,第二個參數(shù)表示我們所獲取方法的參數(shù),這里是兩個int類型。如果沒有返回值返回null,有返回值則返回具體的返回值,這里將返回結(jié)果保存在o對象里。

這樣的優(yōu)點是顯而易見的,類無需在編譯前全部加載,而且修改接口實現(xiàn)類的時候也不用重新編譯。

這只是反射的一小部分,但是也是很重要的一部分,也是Spring中IoC/DI的實現(xiàn)基礎(chǔ)。

(另外告訴大家一個小tip:所謂的泛型數(shù)據(jù)容器的數(shù)據(jù)類型(也就是HashMap<String,String>中的<String,String>)不能寫入其他數(shù)據(jù)類型實際上只是存在于編譯層面的,是為了防止開發(fā)者往里面誤寫入自己不想寫入的東西,然而通過泛型可以跳過編譯層面實現(xiàn)往這個泛型數(shù)據(jù)容器里存入和這個泛型數(shù)據(jù)容器數(shù)據(jù)類型不一樣的數(shù)據(jù),雖然這樣之后用foreach遍歷就會報錯...)

java反射機制(Reflection)

1.什么是反射?反射有什么作用?

能夠分析類能力的程序稱為反射。反射機制允許程序在運行狀態(tài)借助Reflection API取得任何類的內(nèi)部信息,并能直接操作任意對象的內(nèi)部屬性及方法。

反射機制的作用

  • 在運行時判斷任意一個對象所屬的類
  • 在運行時構(gòu)造任意一個類的對象
  • 在運行時判斷任意一個類所具有的成員變量和方法
  • 在運行時調(diào)用任意一個對象的成員變量和方法
  • 在運行時獲取泛型信息
  • 在運行時處理注解
  • 生成 動態(tài)代理

2.反射相關(guān)的主要API

  • java.lang.Class:代表一個類
  • java.lang.reflect.Method:代表類的方法
  • java.lang.reflect. Field:代表類的成員變量
  • java.lang.reflect.Constructor:代表類的構(gòu)造器

3.什么是Class類

對Class類的深入理解

  • Class本身也是一個類
  • Class 對象只能由系統(tǒng)建立對象(Class 對象是在加載類時由Java 虛擬機以及通過調(diào)用類加載器中的 defineClass 方法自動構(gòu)造的)
  • 一個類在 JVM 中只會有一個Class實例
  • 一個Class對象對應(yīng)的是一個加載到JVM中的一個.class文件
  • 每個類的實例都會記得自己是由哪個 Class 實例所生成
  • 通過Class可以完整地得到一個類中的完整結(jié)構(gòu)

類的加載過程:

程序經(jīng)過javac.exe命令以后,會生成一 個或多個字節(jié)碼文件(.class結(jié)尾)。

接著我們使用java.exe命令對某個字節(jié)碼文件進(jìn)行解釋運行。相當(dāng)于將某個字節(jié)碼文件加載到內(nèi)存中。此過程就稱為類的加載。加載到內(nèi)存中的類,我們就稱為運行時類,此運行時類,就作為CLass的一個實例。

java.Lang.Class實例的獲?。ㄋ姆N方式) 

package package03;
import org.junit.Test;
public class ReflectiveTeat01 {
    //獲取 Class 類的實例
    @Test
    public void test01() throws Exception {
        //方式一:通過調(diào)用運行時類得屬性:.class
        Class clazz1 = Person.class;
        System.out.println(clazz1);//class package03.Person
        //方式二:通過運行時類的對象,調(diào)用 getClass() 方法
        Person p1 = new Person();
        Class clazz2 = p1.getClass();
        System.out.println(clazz2);//class package03.Person
        //方式三:調(diào)用 Class 的靜態(tài)方法:forName(String classPath)
        Class clazz3 = Class.forName("package03.Person");
        System.out.println(clazz3);//class package03.Person
        //方法四:使用類的加載器:ClassLoader
        ClassLoader classLoader = ReflectiveTeat01.class.getClassLoader();
        Class clazz4 = classLoader. loadClass("package03.Person") ;
        System. out . println(clazz4);//class package03.Person
    }
}

4.調(diào)用運行時類的指定結(jié)構(gòu)

如何操作運行時類中指定的屬性

@Test
    public void testField() throws Exception {
        Class clazz = Person.class;
        //創(chuàng)建運行時類的對象 P
        Person p = (Person) clazz.newInstance();
        //獲取指定的屬性
        Field fieldName = clazz.getDeclaredField("id");
        //fieldName 要操作的屬性名賦值給 fieldName 變量名
        
        //保證當(dāng)前屬性是可訪問的
        fieldName .setAccessible(true);
        /*
        設(shè)置當(dāng)前屬性的值
        set():參數(shù)1:指明設(shè)置哪個對象的屬性
              參數(shù)2:將此屬性值設(shè)置為多少
         */
        fieldName.set(p,1001);
        /*
        獲取當(dāng)前屬性的值
        get():參數(shù)1:獲取哪個對象的當(dāng)前屬性值
         */
        int intName = (int) fieldName.get(p);
        System.out.println(intName );
    }

操作運行時類的方法

已調(diào)用 show 方法例子:該方法有 注解,參數(shù),返回值,權(quán)限?。╬rivate)

@MyAnonotation//自定義注解
? ? private String show(String nation) {
? ? ? ? System.out.println("我的國籍是:" + nation);
? ? ? ? return nation;
? ? }
 @Test
    public void testMethod() throws Exception {
        Class clazz = Person.class;
        //創(chuàng)建運行時類對象
        Person p = (Person) clazz.newInstance();
       /* 1.獲取指定的某個方法
       getDeclaredMethod():參數(shù)1:指明獲取的方法的名稱
                           參數(shù)2:指明獲取的方法的形參列表
       * */
        Method show = clazz.getDeclaredMethod("show", String.class);
        //2.保證當(dāng)前方法時可訪問的
        show.setAccessible(true);
        /*
        3.調(diào)用方法的invoke():參數(shù)1:方法的調(diào)用者
                            參數(shù)2:給方法形參賦值的實參
          invoke()方法的返回值即為對應(yīng)類中調(diào)用的方法的返回值
         */
        show.invoke(p, "CHN");
        
        //調(diào)用靜態(tài)方法時:
        //private static void showDesc()
        Method showDesc = clazz.getDeclaredMethod("showDesc");
        showDesc.setAccessible(true);
        //如果調(diào)用的運行時類中的方法沒有返回值,則 invoke() 返回 null
        Object invoke = showDesc.invoke(Person.class);
        System.out.println(invoke);
    }

上面代碼用到的 Person 類

public class Person {
    private String name;
    private int age;
    public int id;
    //空參構(gòu)造器
    public Person() {
    }
    //全參構(gòu)造器
    public Person(String name, int age, int id) {
        this.name = name;
        this.age = age;
        this.id = id;
    }
    @MyAnonotation
    private String show(String nation) {
        System.out.println("我的國籍是:" + nation);
        return nation;
    }
    //靜態(tài)方法
    private static void showDesc(){
        System.out.println("我是一個可愛的人");
    }
    // get、set 方法
    public String getName() {
        return name;
    }
    public void setName(String name) {
        this.name = name;
    }
    public int getAge() {
        return age;
    }
    public void setAge(int age) {
        this.age = age;
    }
    public int getId() {
        return id;
    }
    public void setId(int id) {
        this.id = id;
    }
}

以上為個人經(jīng)驗,希望能給大家一個參考,也希望大家多多支持腳本之家。

相關(guān)文章

  • Java中Double除保留后小數(shù)位的幾種方法(小結(jié))

    Java中Double除保留后小數(shù)位的幾種方法(小結(jié))

    這篇文章主要介紹了Java中Double保留后小數(shù)位的幾種方法,文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧
    2019-07-07
  • IDEA將Maven項目中指定文件夾下的xml等文件編譯進(jìn)classes的方法

    IDEA將Maven項目中指定文件夾下的xml等文件編譯進(jìn)classes的方法

    這篇文章主要介紹了IDEA將Maven項目中指定文件夾下的xml等文件編譯進(jìn)classes的方法,幫助大家更好的利用IDEA進(jìn)行Java的開發(fā)學(xué)習(xí),感興趣的朋友可以了解下
    2021-01-01
  • javaweb 項目初始配置的方法步驟

    javaweb 項目初始配置的方法步驟

    本文主要介紹了javaweb 項目初始配置的方法步驟,文中通過示例代碼介紹的非常詳細(xì),具有一定的參考價值,感興趣的小伙伴們可以參考一下
    2021-11-11
  • 基于Spring中的事務(wù)@Transactional細(xì)節(jié)與易錯點、幻讀

    基于Spring中的事務(wù)@Transactional細(xì)節(jié)與易錯點、幻讀

    這篇文章主要介紹了基于Spring中的事務(wù)@Transactional細(xì)節(jié)與易錯點、幻讀,具有很好的參考價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教
    2021-11-11
  • 詳解Java動態(tài)代理的實現(xiàn)機制

    詳解Java動態(tài)代理的實現(xiàn)機制

    這篇文章主要為大家詳細(xì)介紹了Java動態(tài)代理的實現(xiàn)機制,感興趣的小伙伴們可以參考一下
    2016-03-03
  • java shiro實現(xiàn)退出登陸清空緩存

    java shiro實現(xiàn)退出登陸清空緩存

    本篇文章主要介紹了java shiro實現(xiàn)退出登陸清空緩存,小編覺得挺不錯的,現(xiàn)在分享給大家,也給大家做個參考。一起跟隨小編過來看看吧
    2017-02-02
  • java中double強制轉(zhuǎn)換int引發(fā)的OOM問題記錄

    java中double強制轉(zhuǎn)換int引發(fā)的OOM問題記錄

    這篇文章主要介紹了java中double強制轉(zhuǎn)換int引發(fā)的OOM問題記錄,本文給大家分享問題排查過程,感興趣的朋友跟隨小編一起看看吧
    2024-10-10
  • 一文深入理解Java中的深拷貝機制

    一文深入理解Java中的深拷貝機制

    在Java編程中,我們經(jīng)常需要處理對象的復(fù)制問題,深拷貝和淺拷貝是兩種常見的復(fù)制方式,它們在內(nèi)存管理和對象引用方面存在不同特點,本文將帶大家深入探究Java中的深拷貝機制,需要的朋友可以參考下
    2023-09-09
  • elasticsearch的zenDiscovery和master選舉機制原理分析

    elasticsearch的zenDiscovery和master選舉機制原理分析

    這篇文章主要介紹了elasticsearch的zenDiscovery和master選舉機制原理分析,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪
    2022-04-04
  • ES結(jié)合java代碼聚合查詢詳細(xì)示例

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

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

最新評論

阿荣旗| 天水市| 甘南县| 恭城| 台东市| 乳源| 罗定市| 阜南县| 马关县| 九台市| 彩票| 图们市| 香港 | 邯郸市| 内黄县| 泰兴市| 天等县| 同德县| 平远县| 舞钢市| 漯河市| 星子县| 德州市| 乐安县| 广汉市| 九江市| 宣恩县| 厦门市| 民权县| 石柱| 濉溪县| 内丘县| 金堂县| 定远县| 天柱县| 沙湾县| 延津县| 丹寨县| 剑河县| 太仆寺旗| 淮滨县|