小男孩‘自慰网亚洲一区二区,亚洲一级在线播放毛片,亚洲中文字幕av每天更新,黄aⅴ永久免费无码,91成人午夜在线精品,色网站免费在线观看,亚洲欧洲wwwww在线观看

分享

Java基礎(chǔ)增強(qiáng)-反射機(jī)制

 小世界的野孩子 2020-05-31

1 反射機(jī)制簡介

Java的反射(reflection)機(jī)制是指在程序的運(yùn)行狀態(tài)中,可以構(gòu)造任意一個類的對象,可以了解任意一個對象所屬的類,可以了解任意一個類的成員變量和方法,可以調(diào)用任意一個對象的屬性和方法。這種動態(tài)獲取程序信息以及動態(tài)調(diào)用對象的功能稱為Java語言的反射機(jī)制。反射被視為動態(tài)語言的關(guān)鍵。

反射這一概念最早由編程開發(fā)人員Smith在1982年提出,主要指應(yīng)用程序訪問、檢測、修改自身狀態(tài)與行為的能力。這一概念的提出立刻吸引了編程界的極大關(guān)注,各種研究工作隨之展開,隨之而來引發(fā)編程革命,出現(xiàn)了多種支持反射機(jī)制的面向?qū)ο笳Z言。

在計(jì)算機(jī)科學(xué)領(lǐng)域,反射是指一類能夠自我描述和自控制的應(yīng)用。在Java編程語言中,反射是一種強(qiáng)有力的工具,是面向抽象編程一種實(shí)現(xiàn)方式,它能使代碼語句更加靈活,極大提高代碼的運(yùn)行時裝配能力。

2 Class類

對于一個字節(jié)碼文件.class,雖然表面上我們對該字節(jié)碼文件一無所知,但該文件本身卻記錄了許多信息。Java在將.class字節(jié)碼文件載入時,JVM將產(chǎn)生一個java.lang.Class對象代表該.class字節(jié)碼文件,從該Class對象中可以獲得類的許多基本信息,這就是反射機(jī)制。所以要想完成反射操作,就必須首先認(rèn)識Class類。 [1]

反射機(jī)制所需的類主要有java.lang包中的Class類和java.lang.reflet包中的Constructor類、Field類、Method類和Parameter類。Class類是一個比較特殊的類,它是反射機(jī)制的基礎(chǔ),Class類的對象表示正在運(yùn)行的Java程序中的類或接口,也就是任何一個類被加載時,即將類的.class文件(字節(jié)碼文件)讀入內(nèi)存的同時,都自動為之創(chuàng)建一個java.lang.Class對象。Class類沒有公共構(gòu)造方法,其對象是JVM在加載類時通過調(diào)用類加載器中的defineClass()方法創(chuàng)建的,因此不能顯式地創(chuàng)建一個Class對象。通過這個Class對象,才可以獲得該對象的其他信息

3 反射思維導(dǎo)圖

4 反射的具體體現(xiàn)

4.1 準(zhǔn)備工作

1、新建@InheritedAnnotation注解

@Target({ElementType.FIELD, ElementType.TYPE, ElementType.CONSTRUCTOR})
@Documented
@Retention(RetentionPolicy.RUNTIME)
@Inherited
public @interface InheritedAnnotation {
    String value();
}

2、新建@MyAnnotation注解

@Target({ElementType.FIELD, ElementType.TYPE, ElementType.CONSTRUCTOR})
@Documented
@Retention(RetentionPolicy.RUNTIME)
public @interface MyAnnotation {
    String value();
}

3、新建一個Person類

@InheritedAnnotation("Inherited")
public class Person {

    private Integer id;

    public Person() {
    }

    public void say() {
        System.out.println("Hello Person");
    }
}

4、新建一個User類繼承Person類

@MyAnnotation("myAnnotation")
public class User extends Person {

    @MyAnnotation("name")
    public String name;

    @MyAnnotation("sex")
    private String sex;

    protected int age;

    public User() {
    }

    @MyAnnotation("User(name, sex, age)")
    public User(String name, String sex, int age) {
        this.name = name;
        this.sex = sex;
        this.age = age;
    }

    @MyAnnotation("name")
    private User(String name) {
        this.name = name;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public String getSex() {
        return sex;
    }

    public void setSex(String sex) {
        this.sex = sex;
    }

    public int getAge() {
        return age;
    }

    public void setAge(int age) {
        this.age = age;
    }

    @Override
    public String toString() {
        return "User{" +
                "name='" + name + '\'' +
                ", sex='" + sex + '\'' +
                ", age=" + age +
                '}';
    }

    private void sayHello() {
        System.out.println("Hello World");
    }
}

4.2 獲取Class類的三種方式

	/**
     * 三種獲取Class對象的方式
     * @param obj
     * @return
     * @throws ClassNotFoundException
     */
    public static Class getClazz(Object obj) throws ClassNotFoundException {
        //第一種方式:通過對象的全路徑名獲取Class對象
        Class clazz = Class.forName("com.base.domain.User");
        System.out.println("1、通過對象的路徑獲取Class對象:" + clazz);
        //第二種方式:通過對象的getClass方法獲取Class對象
        Class clazz1 = obj.getClass();
        System.out.println("2、通過對象實(shí)例的getClass方法獲取Class對象:" + clazz1);
        //第三種方式:通過對象的.class方法獲取Class對象
        Class clazz2 = User.class;
        System.out.println("3、通過對象.class方法獲取Class對象:" + clazz2);
        return clazz;
    }

執(zhí)行:

public class ReflectTest {
    public static void main(String[] args) throws Exception {
        User user = new User();
        Class clazz = ReflectUtils.getClazz(user);
    }
}

執(zhí)行結(jié)果:

1、通過對象的路徑獲取Class對象:class com.base.domain.User
2、通過對象實(shí)例的getClass方法獲取Class對象:class com.base.domain.User
3、通過對象.class方法獲取Class對象:class com.base.domain.User

4.3 獲取類的所有屬性

	/**
     * 獲取類的所有屬性
     * @param clazz
     * @throws NoSuchFieldException
     */
    public static void getAllFields(Class clazz) throws NoSuchFieldException {
        Field[] fields = clazz.getDeclaredFields();
        for (Field field : fields) {
            System.out.println("獲取類中的所有屬性:" + field);
        }
        Field field = clazz.getDeclaredField("name");
        System.out.println("通過屬性名獲取類的屬性:" + field);
    }

執(zhí)行結(jié)果:

獲取類中的所有屬性:public java.lang.String com.base.domain.User.name
獲取類中的所有屬性:private java.lang.String com.base.domain.User.sex
獲取類中的所有屬性:protected int com.base.domain.User.age
通過屬性名獲取類的屬性:public java.lang.String com.base.domain.User.name

4.4 獲取類的公開屬性

	/**
     * 獲取類中的公開屬性
     * @param clazz
     * @throws NoSuchFieldException
     */
    public static void getPublicFields(Class clazz) throws NoSuchFieldException {
        Field[] fields = clazz.getFields();
        for (Field field : fields) {
            System.out.println("獲取類中的共開屬性:" + field);
        }

        //clazz.getField(String name)方式不能獲取私有的屬性,會拋出NoSuchFieldException異常
        Field field1 = clazz.getField("name");
        System.out.println("通過屬性名獲取類的公開屬性:" + field1);
    }

執(zhí)行結(jié)果:

獲取類中的共開屬性:public java.lang.String com.base.domain.User.name
通過屬性名獲取類的公開屬性:public java.lang.String com.base.domain.User.name

4.5 獲取本類的所有方法

	/**
     * 獲取本類中的所有方法
     * @param clazz
     */
    public static void getAllMethods(Class clazz) throws NoSuchMethodException {
        Method[] methods = clazz.getDeclaredMethods();
        for (Method method : methods) {
            System.out.println("獲取本類的所有方法:" + method);
        }

        Method method = clazz.getDeclaredMethod("setSex", String.class);
        System.out.println("通過方法名獲取setSex方法" + method);
    }

執(zhí)行結(jié)果:

獲取本類的所有方法:public java.lang.String com.base.domain.User.toString()
獲取本類的所有方法:public java.lang.String com.base.domain.User.getName()
獲取本類的所有方法:public void com.base.domain.User.setName(java.lang.String)
獲取本類的所有方法:public java.lang.String com.base.domain.User.getSex()
獲取本類的所有方法:public void com.base.domain.User.setSex(java.lang.String)
獲取本類的所有方法:public int com.base.domain.User.getAge()
獲取本類的所有方法:public void com.base.domain.User.setAge(int)
獲取本類的所有方法:private void com.base.domain.User.sayHello()
通過方法名獲取setSex方法public void com.base.domain.User.setSex(java.lang.String)

4.6 獲取本類及父類的公開方法

	/**
     * 獲取本類及父類的所有公開方法,私有方法不會被獲取
     * @param clazz
     */
    public static void getPublicMethods(Class clazz) throws NoSuchMethodException {
        Method[] methods = clazz.getMethods();
        for (Method method : methods) {
            System.out.println("獲取類的所有公開方法,包括父類的方法:" + method);
        }

        Method method = clazz.getMethod("getSex");
        System.out.println("通過方法名獲取getSex方法" + method);
    }

執(zhí)行結(jié)果:

獲取類的所有公開方法,包括父類的方法:public java.lang.String com.base.domain.User.toString()
獲取類的所有公開方法,包括父類的方法:public java.lang.String com.base.domain.User.getName()
獲取類的所有公開方法,包括父類的方法:public void com.base.domain.User.setName(java.lang.String)
獲取類的所有公開方法,包括父類的方法:public java.lang.String com.base.domain.User.getSex()
獲取類的所有公開方法,包括父類的方法:public void com.base.domain.User.setSex(java.lang.String)
獲取類的所有公開方法,包括父類的方法:public int com.base.domain.User.getAge()
獲取類的所有公開方法,包括父類的方法:public void com.base.domain.User.setAge(int)
獲取類的所有公開方法,包括父類的方法:public void com.base.domain.Person.say()
獲取類的所有公開方法,包括父類的方法:public final void java.lang.Object.wait() throws java.lang.InterruptedException
獲取類的所有公開方法,包括父類的方法: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 boolean java.lang.Object.equals(java.lang.Object)
獲取類的所有公開方法,包括父類的方法: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()
通過方法名獲取getSex方法public java.lang.String com.base.domain.User.getSex()

4.7 獲取類的所有構(gòu)造方法

**
     * 獲取類的所有構(gòu)造方法
     * @param clazz
     */
    public static void getAllConstructors(Class clazz) throws NoSuchMethodException {
        Constructor[] constructors = clazz.getDeclaredConstructors();
        for (Constructor constructor : constructors) {
            System.out.println("獲取類的所有構(gòu)造方法:" + constructor);
        }

        Constructor constructor = clazz.getDeclaredConstructor(String.class);
        System.out.println("通過參數(shù)個數(shù)及類型獲取構(gòu)造方法:" + constructor);
    }

執(zhí)行結(jié)果:

獲取類的所有構(gòu)造方法:private com.base.domain.User(java.lang.String)
獲取類的所有構(gòu)造方法:public com.base.domain.User(java.lang.String,java.lang.String,int)
獲取類的所有構(gòu)造方法:public com.base.domain.User()
通過參數(shù)個數(shù)及類型獲取構(gòu)造方法:private com.base.domain.User(java.lang.String)

4.8 獲取類的公開構(gòu)造方法

	/**
     * 獲取類的公開構(gòu)造方法
     * @param clazz
     */
    public static void getPublicConstructors(Class clazz) throws NoSuchMethodException {
        Constructor[] constructors = clazz.getConstructors();
        for (Constructor constructor : constructors) {
            System.out.println("獲取類的公開構(gòu)造方法:" + constructor);
        }
        Constructor constructor = clazz.getConstructor(String.class, String.class, int.class);
        System.out.println("通過參數(shù)個數(shù)及類型獲取公開的構(gòu)造方法:" + constructor);
    }

執(zhí)行結(jié)果:

獲取類的公開構(gòu)造方法:public com.base.domain.User(java.lang.String,java.lang.String,int)
獲取類的公開構(gòu)造方法:public com.base.domain.User()
通過參數(shù)個數(shù)及類型獲取公開的構(gòu)造方法:public com.base.domain.User(java.lang.String,java.lang.String,int)

4.9 獲取本類上的注解

	/**
     * 獲取類上的注解
     * @param clazz
     */
    public static void getClassAnnotations(Class clazz) {
        Annotation[] annotations = clazz.getDeclaredAnnotations();
        for (Annotation annotation : annotations) {
            System.out.println("獲取類上的注解" + annotation);
        }

        Annotation annotation = clazz.getDeclaredAnnotation(MyAnnotation.class);
        System.out.println("通過注解類獲取注解:" + annotation);
    }

執(zhí)行結(jié)果:

獲取類上的注解@com.base.annotation.MyAnnotation(value=myAnnotation)
通過注解類獲取注解:@com.base.annotation.MyAnnotation(value=myAnnotation)

4.10 獲取本類及父類的注解

/**
 * 獲取類上的注解,會將父類中用@Inherited修飾的注解獲取到
 * @param clazz
 */
public static void getAnnotations(Class clazz) {
    Annotation[] annotations = clazz.getAnnotations();
    for (Annotation annotation : annotations) {
        System.out.println("獲取父類中可繼承的及本類中的類注解" + annotation);
    }
    Annotation annotation = clazz.getAnnotation(InheritedAnnotation.class);
    System.out.println("通過注解類獲取注解:" + annotation);
}

執(zhí)行結(jié)果:

獲取父類中可繼承的及本類中的類注解@com.base.annotation.InheritedAnnotation(value=Inherited)
獲取父類中可繼承的及本類中的類注解@com.base.annotation.MyAnnotation(value=myAnnotation)
通過注解類獲取注解:@com.base.annotation.InheritedAnnotation(value=Inherited)

4.11 通過反射實(shí)例化對象

	/**
     * 通過反射實(shí)例化對象
     * @param clazz
     * @return
     * @throws Exception
     */
    public static  Object newInstanceObject(Class clazz) throws Exception {
        User user = (User)clazz.newInstance();
        System.out.println("通過newInstance方式實(shí)例化對象:" + user.toString());

        Constructor constructor = clazz.getDeclaredConstructor(String.class, String.class, int.class);
        user = (User) constructor.newInstance("張三", "男", 18);
        System.out.println("通過公開的構(gòu)造方法方式實(shí)例化對象:" + user.toString());

        constructor = clazz.getDeclaredConstructor(String.class);
        constructor.setAccessible(true);//訪問私有的方法及屬性需要將Accessible設(shè)置為true
        user = (User) constructor.newInstance("李四");
        System.out.println("通過私有的構(gòu)造方法方式實(shí)例化對象:" + user.toString());

        return user;
    }

執(zhí)行結(jié)果:

通過newInstance方式實(shí)例化對象:User{name='null', sex='null', age=0}
通過公開的構(gòu)造方法方式實(shí)例化對象:User{name='張三', sex='男', age=18}
通過私有的構(gòu)造方法方式實(shí)例化對象:User{name='李四', sex='null', age=0}

4.12 通過反射調(diào)用方法

/**
     * 通過反射調(diào)用方法
     * @param clazz
     * @throws Exception
     */
    public static void  invokeMethod(Class clazz) throws Exception {
        Method method = clazz.getDeclaredMethod("setAge", int.class);
        User user = (User) newInstanceObject(clazz);
        method.invoke(user, 28);
        System.out.println("通過反射調(diào)用setAge方法:" + user.toString());
    }

執(zhí)行結(jié)果:

通過反射調(diào)用setAge方法:User{name='李四', sex='null', age=28}

4.13 通過反射修改屬性

	/**
     * 通過反射修改屬性值
     * @param clazz
     * @throws Exception
     */
    public static void invokeUpdateField(Class clazz) throws Exception {
        Field field = clazz.getDeclaredField("sex");
        User user = (User) newInstanceObject(clazz);
        field.setAccessible(true);//如果是公開的屬性,則不需要setAccessible為true
        field.set(user, "女");
        System.out.println("通過反射修改對象的私有屬性值:" + user.toString());
    }

執(zhí)行結(jié)果:

通過反射修改對象的私有屬性值:User{name='李四', sex='女', age=0}

5 反射意義

首先,反射機(jī)制極大的提高了程序的靈活性和擴(kuò)展性,降低模塊的耦合性,提高自身的適應(yīng)能力。

其次,通過反射機(jī)制可以讓程序創(chuàng)建和控制任何類的對象,無需提前硬編碼目標(biāo)類。

再次,使用反射機(jī)制能夠在運(yùn)行時構(gòu)造一個類的對象、判斷一個類所具有的成員變量和方法、調(diào)用一個對象的方法。

最后,反射機(jī)制是構(gòu)建框架技術(shù)的基礎(chǔ)所在,使用反射可以避免將代碼寫死在框架中。

正是反射有以上的特征,所以它能動態(tài)編譯和創(chuàng)建對象,極大的激發(fā)了編程語言的靈活性,強(qiáng)化了多態(tài)的特性,進(jìn)一步提升了面向?qū)ο缶幊痰某橄竽芰Γ蚨艿骄幊探绲那嗖A。

6 反射特點(diǎn)

盡管反射機(jī)制帶來了極大的靈活性及方便性,但反射也有缺點(diǎn)。反射機(jī)制的功能非常強(qiáng)大,但不能濫用。在能不使用反射完成時,盡量不要使用,原因有以下幾點(diǎn):

1、性能問題。

Java反射機(jī)制中包含了一些動態(tài)類型,所以Java虛擬機(jī)不能夠?qū)@些動態(tài)代碼進(jìn)行優(yōu)化。因此,反射操作的效率要比正常操作效率低很多。我們應(yīng)該避免在對性能要求很高的程序或經(jīng)常被執(zhí)行的代碼中使用反射。而且,如何使用反射決定了性能的高低。如果它作為程序中較少運(yùn)行的部分,性能將不會成為一個問題。

2、安全限制。

使用反射通常需要程序的運(yùn)行沒有安全方面的限制。如果一個程序?qū)Π踩蕴岢鲆?,則最好不要使用反射。

3、程序健壯性。

反射允許代碼執(zhí)行一些通常不被允許的操作,所以使用反射有可能會導(dǎo)致意想不到的后果。反射代碼破壞了Java程序結(jié)構(gòu)的抽象性,所以當(dāng)程序運(yùn)行的平臺發(fā)生變化的時候,由于抽象的邏輯結(jié)構(gòu)不能被識別,代碼產(chǎn)生的效果與之前會產(chǎn)生差異。

7 總結(jié)

1、Calss.getAnnotations();方法獲取注解,父類的注解必須含有元注解@Inherited才能被獲??;

2、通過私有的構(gòu)造函數(shù)實(shí)例化對象或者修改私有屬性時需要設(shè)置setAccessible為true,才能正常執(zhí)行;

3、本文列舉了反射機(jī)制使用過程中常用的、重要的一些類及其方法,其他用法請自行查看官方文檔。

    本站是提供個人知識管理的網(wǎng)絡(luò)存儲空間,所有內(nèi)容均由用戶發(fā)布,不代表本站觀點(diǎn)。請注意甄別內(nèi)容中的聯(lián)系方式、誘導(dǎo)購買等信息,謹(jǐn)防詐騙。如發(fā)現(xiàn)有害或侵權(quán)內(nèi)容,請點(diǎn)擊一鍵舉報。
    轉(zhuǎn)藏 分享 獻(xiàn)花(0

    0條評論

    發(fā)表

    請遵守用戶 評論公約

    類似文章 更多