亚洲乱码中文字幕综合,中国熟女仑乱hd,亚洲精品乱拍国产一区二区三区,一本大道卡一卡二卡三乱码全集资源,又粗又黄又硬又爽的免费视频

基于java中反射的總結(jié)分析

 更新時(shí)間:2013年05月03日 19:05:51   作者:  
所謂反射,就是根據(jù)一個(gè)已經(jīng)實(shí)例化了的對(duì)象來(lái)還原類(lèi)的完整信息 至少對(duì)我而言,我認(rèn)為它帶給我的好處是,讓我從下往上的又了解了一遍面向?qū)ο?

剛開(kāi)始學(xué)習(xí)java的時(shí)候真的很難理解反射到底是個(gè)什么東西

一些書(shū)籍,哪怕是很經(jīng)典的書(shū)籍都解釋的讓人感覺(jué)懵懵的,或許的確是我太笨

況且,網(wǎng)上說(shuō)在將來(lái)學(xué)習(xí)框架的時(shí)候需要經(jīng)常應(yīng)用到反射機(jī)制,這樣一來(lái)總讓人心里有些不安

就方才偶然又把講解反射的章節(jié)和視頻看了一點(diǎn),覺(jué)得能理解一些了

現(xiàn)在決定一鼓作氣,邊看邊寫(xiě),順便把一些主要的內(nèi)容和操作都記載到這里

我想,對(duì)于我這么一個(gè)笨笨的人來(lái)說(shuō),學(xué)習(xí)的最好方法也許就是不斷重復(fù)

遇到不懂的知識(shí)就停下來(lái)把以往的重新學(xué)一遍,雖然浪費(fèi)了很多時(shí)間,但對(duì)我也有些效果

 

我的理解是:所謂反射,就是根據(jù)一個(gè)已經(jīng)實(shí)例化了的對(duì)象來(lái)還原類(lèi)的完整信息

至少對(duì)我而言,我認(rèn)為它帶給我的好處是,讓我從下往上的又了解了一遍面向?qū)ο?/P>

x_x 在此又痛恨一邊那些厚部頭們,把我的腦細(xì)胞搞死一片

 

Class類(lèi)

如果要完成反射,那么必須了解Class類(lèi)

實(shí)例1:通過(guò)對(duì)象取得包名和類(lèi)名
復(fù)制代碼 代碼如下:

package org.siu;

class Test {

}

public class Demo {
    public static void main(String[] args) {
        Test t = new Test();
        System.out.println(t.getClass());
        System.out.println(t.getClass().getName());
    }
}

編譯結(jié)果如下,注意包的編譯方式即可

此處的getClass()方法是默認(rèn)繼承自O(shè)bject類(lèi)的

 

在java中,Object類(lèi)是所有類(lèi)的父類(lèi),同樣,所有類(lèi)的實(shí)例化對(duì)象也都是Class類(lèi)的實(shí)例

因此,這樣一來(lái)就會(huì)牽扯到向上轉(zhuǎn)型和向下轉(zhuǎn)型的概念

由于向下轉(zhuǎn)型的不安全因素,在這里泛型也會(huì)接踵而來(lái)

(不過(guò)我想說(shuō)的是,此處的泛型設(shè)計(jì)很刺眼!尼瑪,整個(gè)java的語(yǔ)法設(shè)計(jì)同樣刺眼,超惡心!?。。?/P>

 

實(shí)例2:Class類(lèi)的實(shí)例化

由于Class類(lèi)沒(méi)有構(gòu)造方法,所以實(shí)例化Class類(lèi)的方式有點(diǎn)特殊,有三種方式:

對(duì)象.getClass( )
類(lèi).Class
forName( )
復(fù)制代碼 代碼如下:

class Test {

}

public class Demo {
    public static void main(String[] args) {
        //方式一:
        Test t = new Test();
        Class<? extends Test> c1 = t.getClass();
        System.out.println(c1);

        //方式二:
        //為了避免特殊性,這里不用Test類(lèi),而用java庫(kù)中的String類(lèi)
        Class<String> c2 = String.class;
        System.out.println(c2);

        //方式三:
        //forName()方法會(huì)拋出異常
        Class<?> c3 = null;
        try {
            c3 = Class.forName("Test");
        } catch (ClassNotFoundException e) {
            e.printStackTrace();
        }
        System.out.println(c3);
    }
}

其中,forName( )方法需要重點(diǎn)掌握,因?yàn)樗梢栽陬?lèi)不確定的情況下實(shí)例化Class,更具靈活性

 

Class類(lèi)的應(yīng)用

Class類(lèi)中有一個(gè)方法叫做newInstance( ),它可以用來(lái)創(chuàng)建一個(gè)Class類(lèi)對(duì)象的新實(shí)例

怎么說(shuō)呢?Class對(duì)象包含的內(nèi)容就是反射好的那個(gè)類(lèi),我們要構(gòu)造那個(gè)類(lèi)的新實(shí)例(新對(duì)象)

實(shí)例3:Class類(lèi)的無(wú)參構(gòu)造對(duì)象
復(fù)制代碼 代碼如下:

public class Demo {
    public static void main(String[] args) {
        //實(shí)例化Class對(duì)象,forName()方法會(huì)拋異常
        Class<?> c = null;
        try {
            //這里需要完整的包名和類(lèi)名
            c = Class.forName("java.lang.String");
        } catch (ClassNotFoundException e) {
            e.printStackTrace();
        }

        //生成一個(gè)字符串的引用
        String s = null;
        try {
            //將構(gòu)造好的對(duì)象向下轉(zhuǎn)型為String類(lèi)
            //newInstance()方法會(huì)拋異常
            s = (String) c.newInstance();
        } catch (InstantiationException e) {
            e.printStackTrace();
        } catch (IllegalAccessException e) {
            e.printStackTrace();
        }
        System.out.println("字符串長(zhǎng)度: " + s.length());
    }
}

這樣就通過(guò)無(wú)參數(shù)的形式構(gòu)造了一個(gè)新的對(duì)象,如同正常模式中

通過(guò)無(wú)參構(gòu)造方法來(lái)構(gòu)造新對(duì)象一樣

我們知道,類(lèi)中除了有無(wú)參構(gòu)造方法,還會(huì)存在有參數(shù)的構(gòu)造方法

那在反射中如何通過(guò)有參數(shù)的形式構(gòu)造對(duì)象呢?接著看

 

實(shí)例4:Class類(lèi)的有參構(gòu)造對(duì)象
復(fù)制代碼 代碼如下:

import java.lang.reflect.Constructor;

public class Demo {
    //下面的幾個(gè)方法拋出來(lái)的異常太多,為了代碼的緊湊性,這里就直接拋給虛擬機(jī)了
    public static void main(String[] args) throws Exception {
        Class<?> c = null;
        try {
            c = Class.forName("java.lang.String");
        } catch (ClassNotFoundException e) {
            e.printStackTrace();
        }
        char[] ch = {'h','e','l','l','o'};
        String s = null;
        //獲得Class類(lèi)對(duì)象的有參構(gòu)造方法,括號(hào)里面參數(shù)的寫(xiě)法是:類(lèi)型.class
        Constructor<?> con = c.getConstructor(char[].class);
        //用此構(gòu)造方法構(gòu)造一個(gè)新的字符串對(duì)象,參數(shù)為一個(gè)char數(shù)組
        s = (String) con.newInstance(ch);
        System.out.println("構(gòu)造的字符串:" + s);
    }
}

我們還是使用String類(lèi)做例,因?yàn)镾tring類(lèi)用的比較多,便于理解

這里需要注意的是,構(gòu)造方法需要使用getConstructor( )方法獲得

至于參數(shù)類(lèi)型則是:原有類(lèi)型.class

還有一點(diǎn),無(wú)論是有參還是無(wú)參,這里所使用的構(gòu)造方法,原本的類(lèi)里面必須對(duì)應(yīng)存在

那么,如何才能知道原有類(lèi)里面的構(gòu)造方法,普通方法,繼承的父類(lèi)等詳細(xì)信息呢?接著看

 

獲取類(lèi)的結(jié)構(gòu)

要通過(guò)反射獲取類(lèi)的結(jié)構(gòu)我們這里要導(dǎo)入一個(gè)新的包java.lang.reflect

實(shí)例5:取得類(lèi)的構(gòu)造方法
復(fù)制代碼 代碼如下:

import java.lang.reflect.Constructor;
import java.util.Arrays;

public class Demo {
    //下面的幾個(gè)方法拋出來(lái)的異常太多,為了代碼的緊湊性,這里就直接拋給虛擬機(jī)了
    public static void main(String[] args) throws Exception {
        Class<?> c = null;
        try {
            c = Class.forName("java.lang.Boolean");
        } catch (ClassNotFoundException e) {
            e.printStackTrace();
        }
        //這里的getConstructors()方法返回的是一個(gè)Constructor數(shù)組
        Constructor<?>[] cons = c.getConstructors();
        //打印的方式你可以自己寫(xiě),為了方便我用Arrays.toString(),湊合著看
        System.out.println(Arrays.toString(cons));
    }
}

我選擇了Boolean類(lèi)來(lái)做例,因?yàn)锽oolean類(lèi)的構(gòu)造方法就兩個(gè),方便看

 

實(shí)例6:取得類(lèi)所實(shí)現(xiàn)的接口
復(fù)制代碼 代碼如下:

import java.util.Arrays;

public class Demo {
    public static void main(String[] args) throws Exception {
        Class<?> c = null;
        try {
            c = Class.forName("java.lang.Boolean");
        } catch (ClassNotFoundException e) {
            e.printStackTrace();
        }
        Class<?>[] in = c.getInterfaces();
        System.out.println(Arrays.toString(in));
    }
}

沒(méi)什么好說(shuō)的,看結(jié)果

 

實(shí)例7:取得父類(lèi)
復(fù)制代碼 代碼如下:

public class Demo {
    public static void main(String[] args) throws Exception {
        Class<?> c = null;
        try {
            c = Class.forName("java.lang.Boolean");
        } catch (ClassNotFoundException e) {
            e.printStackTrace();
        }
        //注意了,這里不會(huì)是數(shù)組,why?
        Class<?> su = c.getSuperclass();
        System.out.println(su);
    }
}

別忘了,java中是單繼承,父類(lèi)只有一個(gè)

 

實(shí)例8:取得類(lèi)的全部方法
復(fù)制代碼 代碼如下:

import java.lang.reflect.Method;

public class Demo {
    public static void main(String[] args) throws Exception {
        Class<?> c = null;
        try {
            c = Class.forName("java.lang.Boolean");
        } catch (ClassNotFoundException e) {
            e.printStackTrace();
        }
        Method[] m = c.getMethods();
        //好吧,這次我就大發(fā)慈悲的寫(xiě)個(gè)打印列表出來(lái)
        for (int i = 0; i < m.length; i++) {
            System.out.println(m[i]);
        }
    }
}

截取一部分,看看,意思下就行了……這幾個(gè)例子都比較簡(jiǎn)單

 

實(shí)例9:取得本類(lèi)的全部屬性
復(fù)制代碼 代碼如下:

import java.lang.reflect.Field;

class Person {
    private String name;
    private int age;
}

public class Demo {
    public static void main(String[] args) throws Exception {
        Class<?> c = null;
        try {
            c = Class.forName("Person");
        } catch (ClassNotFoundException e) {
            e.printStackTrace();
        }
        Field[] f = c.getDeclaredFields();
        for (int i = 0; i < f.length; i++) {
            System.out.println(f[i]);
        }
    }
}

getDeclaredFielsd()方法可以獲取全部屬性,getFields()只能獲取公共屬性

 

實(shí)例10:獲取本類(lèi)中屬性的值
復(fù)制代碼 代碼如下:

import java.lang.reflect.Field;

class Person {
    public String name;
    private int age;

    public Person(String name, int age) {
        this.name = name;
        this.age = age;
    }
}

public class Demo {
    public static void main(String[] args) throws Exception {
        Person p = new Person("zhangsan",12);

        Class<?> c = p.getClass();

        //獲取公共屬性的值
        Field f1 = c.getField("name");
        //get(p)表明要獲取是哪個(gè)對(duì)象的值
        String str = (String) f1.get(p);
        System.out.println("姓名: " + str);

        //獲取私有屬性的值
        Field f2 = c.getDeclaredField("age");
        //age是私有屬性,所以要設(shè)置安全檢查為true
        f2.setAccessible(true);
        int age = (int) f2.get(p);
        System.out.println("年齡: " + age);
    }
}

要注意的是:setAccessible()方法可以設(shè)置是否訪問(wèn)和修改私有屬性

 

坦白說(shuō),java學(xué)到現(xiàn)在我還沒(méi)發(fā)現(xiàn)什么能亮瞎我鈦金眼的知識(shí)在里邊

每次都是寫(xiě)一堆繁瑣的語(yǔ)法實(shí)現(xiàn)個(gè)小玩意兒,不然就是拼命調(diào)用API,拼命的拋異常

讓本身顯得不夠緊湊的代碼變得愈發(fā)累贅

如果我喜歡一門(mén)語(yǔ)言,在我利用它做出東西來(lái)之前,它本身的特性必須能夠打動(dòng)我

顯然,java并不讓我快樂(lè),也許很多程序員跟我一樣是被迫使用java的

僅以此來(lái)安撫我那顆孤獨(dú)編碼的心,下面接著看內(nèi)容

 

反射的應(yīng)用實(shí)例11:通過(guò)反射修改屬性
復(fù)制代碼 代碼如下:

import java.lang.reflect.Field;

class Person {
    private String name;

    public Person(String name) {
        this.name = name;
    }

    public String toString() {
        return "姓名: " + this.name;
    }
}

public class Demo {
    public static void main(String[] args) throws Exception {
        Person p = new Person("王二狗");
        System.out.println(p);
        Class<?> c = p.getClass();

        //定義要修改的屬性
        Field f = c.getDeclaredField("name");
        f.setAccessible(true);
        //修改屬性,傳入要設(shè)置的對(duì)象和值
        f.set(p, "張二蛋");
        System.out.println(p);
    }
}

幾個(gè)方法都是有聯(lián)系的,如果看不懂就先熟悉上面幾個(gè)例子

 

實(shí)例12:通過(guò)反射調(diào)用方法
復(fù)制代碼 代碼如下:

import java.lang.reflect.Method;

class Person {
    public void print(int i) {
        System.out.println("我在寫(xiě)數(shù)字: " + i);
    }

    public static void say(String str) {
        System.out.println("我在說(shuō): " + str);
    }
}

public class Demo {
    public static void main(String[] args) throws Exception {
        Person p = new Person();
        Class<?> c = p.getClass();

        //getMethod()方法需要傳入方法名,和參數(shù)類(lèi)型
        Method m1 = c.getMethod("print", int.class);
        //invoke()表示調(diào)用的意思,需要傳入對(duì)象和參數(shù)
        m1.invoke(p, 10);

        Method m2 = c.getMethod("say", String.class);
        //這里的null表示不由對(duì)象調(diào)用,也就是靜態(tài)方法
        m2.invoke(null, "你妹");
    }
}

這里演示了一個(gè)普通的有參方法和一個(gè)靜態(tài)方法

既然有參數(shù)的都寫(xiě)出來(lái)了,那么無(wú)參的就更簡(jiǎn)單了,直接傳入一個(gè)對(duì)象即可

 

實(shí)例13:通過(guò)反射操作數(shù)組
復(fù)制代碼 代碼如下:

import java.lang.reflect.Array;

public class Demo {
    public static void main(String[] args) throws Exception {
        int[] arr = {1,2,3,4,5};
        Class<?> c = arr.getClass().getComponentType();

        System.out.println("數(shù)組類(lèi)型: " + c.getName());
        int len = Array.getLength(arr);
        System.out.println("數(shù)組長(zhǎng)度: " + len);
        System.out.print("遍歷數(shù)組: ");
        for (int i = 0; i < len; i++) {
            System.out.print(Array.get(arr, i) + " ");
        }
        System.out.println();
        //修改數(shù)組
        System.out.println("修改前的第一個(gè)元素: " + Array.get(arr, 0));
        Array.set(arr, 0, 3);
        System.out.println("修改后的第一個(gè)元素: " + Array.get(arr, 0));
    }
}

這里要注意一點(diǎn),getComponentType( )返回的是數(shù)組元素的Class

 

暫時(shí)就寫(xiě)這么多,我看的書(shū)中還有反射在工廠模式中的應(yīng)用

無(wú)非是用forName()方法替換一下,沒(méi)什么可說(shuō)的

我是個(gè)java初級(jí)黑,我恨java那種惡心的語(yǔ)法和設(shè)計(jì)

這都是為了Android,為了打基礎(chǔ),為了適應(yīng)以后的工作

相關(guān)文章

  • IDEA配置Maven并版本統(tǒng)一管理的實(shí)現(xiàn)

    IDEA配置Maven并版本統(tǒng)一管理的實(shí)現(xiàn)

    本文主要介紹了IDEA配置Maven并版本統(tǒng)一管理的實(shí)現(xiàn),文中通過(guò)示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下
    2021-09-09
  • 詳解使用Spring Boot的AOP處理自定義注解

    詳解使用Spring Boot的AOP處理自定義注解

    本篇文章主要介紹了詳解使用Spring Boot的AOP處理自定義注解,小編覺(jué)得挺不錯(cuò)的,現(xiàn)在分享給大家,也給大家做個(gè)參考。一起跟隨小編過(guò)來(lái)看看吧
    2018-01-01
  • mybatis框架xml下trim中的prefix與suffix等標(biāo)簽的用法

    mybatis框架xml下trim中的prefix與suffix等標(biāo)簽的用法

    這篇文章主要介紹了mybatis框架xml下trim中的prefix與suffix等標(biāo)簽的用法,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教
    2021-07-07
  • 帶你詳細(xì)了解Spring Security的注解方式開(kāi)發(fā)

    帶你詳細(xì)了解Spring Security的注解方式開(kāi)發(fā)

    這篇文章主要介紹了詳解spring security四種實(shí)現(xiàn)方式,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧
    2021-08-08
  • SpringMVC的Body參數(shù)攔截的問(wèn)題

    SpringMVC的Body參數(shù)攔截的問(wèn)題

    SpringMVC對(duì)出參和入?yún)⒂蟹浅S押玫耐卣怪С?方便你對(duì)數(shù)據(jù)的輸入和輸出有更大的執(zhí)行權(quán),我們?nèi)绾瓮ㄟ^(guò)SpringMVC定義的結(jié)果做一系列處理呢,需要的朋友可以參考下
    2018-06-06
  • 搭建公司私有MAVEN倉(cāng)庫(kù)的方法

    搭建公司私有MAVEN倉(cāng)庫(kù)的方法

    這篇文章主要介紹了搭建公司私有MAVEN倉(cāng)庫(kù)的方法,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧
    2020-11-11
  • Nacos后臺(tái)頻繁打印get changedGroupKeys:[]的問(wèn)題及解決

    Nacos后臺(tái)頻繁打印get changedGroupKeys:[]的問(wèn)題及解決

    這篇文章主要介紹了Nacos后臺(tái)頻繁打印get changedGroupKeys:[]的問(wèn)題及解決方案,具有很好的參考價(jià)值,希望對(duì)大家有所幫助,如有錯(cuò)誤或未考慮完全的地方,望不吝賜教
    2024-01-01
  • Java對(duì)象級(jí)別與類(lèi)級(jí)別的同步鎖synchronized語(yǔ)法示例

    Java對(duì)象級(jí)別與類(lèi)級(jí)別的同步鎖synchronized語(yǔ)法示例

    這篇文章主要為大家介紹了Java對(duì)象級(jí)別與類(lèi)級(jí)別的同步鎖synchronized語(yǔ)法示例,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步
    2022-03-03
  • java使用dbcp2數(shù)據(jù)庫(kù)連接池

    java使用dbcp2數(shù)據(jù)庫(kù)連接池

    這篇文章主要為大家詳細(xì)介紹了java使用dbcp2數(shù)據(jù)庫(kù)連接池的相關(guān)資料,具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下
    2016-10-10
  • Spring Boot下如何自定義Repository中的DAO方法

    Spring Boot下如何自定義Repository中的DAO方法

    這篇文章主要介紹了Spring Boot下如何自定義Repository中的DAO方法,需要的朋友可以參考下
    2017-06-06

最新評(píng)論