亚洲香蕉成人av网站在线观看_欧美精品成人91久久久久久久_久久久久久久久久久亚洲_热久久视久久精品18亚洲精品_国产精自产拍久久久久久_亚洲色图国产精品_91精品国产网站_中文字幕欧美日韩精品_国产精品久久久久久亚洲调教_国产精品久久一区_性夜试看影院91社区_97在线观看视频国产_68精品久久久久久欧美_欧美精品在线观看_国产精品一区二区久久精品_欧美老女人bb

首頁 > 編程 > Java > 正文

基于java中反射的總結分析

2019-11-26 16:08:30
字體:
來源:轉載
供稿:網友

剛開始學習java的時候真的很難理解反射到底是個什么東西

一些書籍,哪怕是很經典的書籍都解釋的讓人感覺懵懵的,或許的確是我太笨

況且,網上說在將來學習框架的時候需要經常應用到反射機制,這樣一來總讓人心里有些不安

就方才偶然又把講解反射的章節和視頻看了一點,覺得能理解一些了

現在決定一鼓作氣,邊看邊寫,順便把一些主要的內容和操作都記載到這里

我想,對于我這么一個笨笨的人來說,學習的最好方法也許就是不斷重復

遇到不懂的知識就停下來把以往的重新學一遍,雖然浪費了很多時間,但對我也有些效果

 

我的理解是:所謂反射,就是根據一個已經實例化了的對象來還原類的完整信息

至少對我而言,我認為它帶給我的好處是,讓我從下往上的又了解了一遍面向對象

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

 

Class類

如果要完成反射,那么必須了解Class類

實例1:通過對象取得包名和類名
復制代碼 代碼如下:

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());
    }
}

編譯結果如下,注意包的編譯方式即可

此處的getClass()方法是默認繼承自Object類的

 

在java中,Object類是所有類的父類,同樣,所有類的實例化對象也都是Class類的實例

因此,這樣一來就會牽扯到向上轉型和向下轉型的概念

由于向下轉型的不安全因素,在這里泛型也會接踵而來

(不過我想說的是,此處的泛型設計很刺眼!尼瑪,整個java的語法設計同樣刺眼,超惡心?。。。?/P>

 

實例2:Class類的實例化

由于Class類沒有構造方法,所以實例化Class類的方式有點特殊,有三種方式:

對象.getClass( )
類.Class
forName( )
復制代碼 代碼如下:

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類,而用java庫中的String類
        Class<String> c2 = String.class;
        System.out.println(c2);

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

其中,forName( )方法需要重點掌握,因為它可以在類不確定的情況下實例化Class,更具靈活性

 

Class類的應用

Class類中有一個方法叫做newInstance( ),它可以用來創建一個Class類對象的新實例

怎么說呢?Class對象包含的內容就是反射好的那個類,我們要構造那個類的新實例(新對象)

實例3:Class類的無參構造對象
復制代碼 代碼如下:

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

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

這樣就通過無參數的形式構造了一個新的對象,如同正常模式中

通過無參構造方法來構造新對象一樣

我們知道,類中除了有無參構造方法,還會存在有參數的構造方法

那在反射中如何通過有參數的形式構造對象呢?接著看

 

實例4:Class類的有參構造對象
復制代碼 代碼如下:

import java.lang.reflect.Constructor;

public class Demo {
    //下面的幾個方法拋出來的異常太多,為了代碼的緊湊性,這里就直接拋給虛擬機了
    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類對象的有參構造方法,括號里面參數的寫法是:類型.class
        Constructor<?> con = c.getConstructor(char[].class);
        //用此構造方法構造一個新的字符串對象,參數為一個char數組
        s = (String) con.newInstance(ch);
        System.out.println("構造的字符串:" + s);
    }
}

我們還是使用String類做例,因為String類用的比較多,便于理解

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

至于參數類型則是:原有類型.class

還有一點,無論是有參還是無參,這里所使用的構造方法,原本的類里面必須對應存在

那么,如何才能知道原有類里面的構造方法,普通方法,繼承的父類等詳細信息呢?接著看

 

獲取類的結構

要通過反射獲取類的結構我們這里要導入一個新的包java.lang.reflect

實例5:取得類的構造方法
復制代碼 代碼如下:

import java.lang.reflect.Constructor;
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();
        }
        //這里的getConstructors()方法返回的是一個Constructor數組
        Constructor<?>[] cons = c.getConstructors();
        //打印的方式你可以自己寫,為了方便我用Arrays.toString(),湊合著看
        System.out.println(Arrays.toString(cons));
    }
}

我選擇了Boolean類來做例,因為Boolean類的構造方法就兩個,方便看

 

實例6:取得類所實現的接口
復制代碼 代碼如下:

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));
    }
}

沒什么好說的,看結果

 

實例7:取得父類
復制代碼 代碼如下:

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();
        }
        //注意了,這里不會是數組,why?
        Class<?> su = c.getSuperclass();
        System.out.println(su);
    }
}

別忘了,java中是單繼承,父類只有一個

 

實例8:取得類的全部方法
復制代碼 代碼如下:

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();
        //好吧,這次我就大發慈悲的寫個打印列表出來
        for (int i = 0; i < m.length; i++) {
            System.out.println(m[i]);
        }
    }
}

截取一部分,看看,意思下就行了……這幾個例子都比較簡單

 

實例9:取得本類的全部屬性
復制代碼 代碼如下:

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()只能獲取公共屬性

 

實例10:獲取本類中屬性的值
復制代碼 代碼如下:

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)表明要獲取是哪個對象的值
        String str = (String) f1.get(p);
        System.out.println("姓名: " + str);

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

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

 

坦白說,java學到現在我還沒發現什么能亮瞎我鈦金眼的知識在里邊

每次都是寫一堆繁瑣的語法實現個小玩意兒,不然就是拼命調用API,拼命的拋異常

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

如果我喜歡一門語言,在我利用它做出東西來之前,它本身的特性必須能夠打動我

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

僅以此來安撫我那顆孤獨編碼的心,下面接著看內容

 

反射的應用實例11:通過反射修改屬性
復制代碼 代碼如下:

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);
        //修改屬性,傳入要設置的對象和值
        f.set(p, "張二蛋");
        System.out.println(p);
    }
}

幾個方法都是有聯系的,如果看不懂就先熟悉上面幾個例子

 

實例12:通過反射調用方法
復制代碼 代碼如下:

import java.lang.reflect.Method;

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

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

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

        //getMethod()方法需要傳入方法名,和參數類型
        Method m1 = c.getMethod("print", int.class);
        //invoke()表示調用的意思,需要傳入對象和參數
        m1.invoke(p, 10);

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

這里演示了一個普通的有參方法和一個靜態方法

既然有參數的都寫出來了,那么無參的就更簡單了,直接傳入一個對象即可

 

實例13:通過反射操作數組
復制代碼 代碼如下:

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("數組類型: " + c.getName());
        int len = Array.getLength(arr);
        System.out.println("數組長度: " + len);
        System.out.print("遍歷數組: ");
        for (int i = 0; i < len; i++) {
            System.out.print(Array.get(arr, i) + " ");
        }
        System.out.println();
        //修改數組
        System.out.println("修改前的第一個元素: " + Array.get(arr, 0));
        Array.set(arr, 0, 3);
        System.out.println("修改后的第一個元素: " + Array.get(arr, 0));
    }
}

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

 

暫時就寫這么多,我看的書中還有反射在工廠模式中的應用

無非是用forName()方法替換一下,沒什么可說的

我是個java初級黑,我恨java那種惡心的語法和設計

這都是為了Android,為了打基礎,為了適應以后的工作

發表評論 共有條評論
用戶名: 密碼:
驗證碼: 匿名發表
亚洲香蕉成人av网站在线观看_欧美精品成人91久久久久久久_久久久久久久久久久亚洲_热久久视久久精品18亚洲精品_国产精自产拍久久久久久_亚洲色图国产精品_91精品国产网站_中文字幕欧美日韩精品_国产精品久久久久久亚洲调教_国产精品久久一区_性夜试看影院91社区_97在线观看视频国产_68精品久久久久久欧美_欧美精品在线观看_国产精品一区二区久久精品_欧美老女人bb
色综合久综合久久综合久鬼88| 欧美午夜www高清视频| 午夜欧美大片免费观看| 亚洲精品网址在线观看| 自拍偷拍亚洲一区| 成人激情春色网| 97在线免费观看| 日本久久久久亚洲中字幕| 日韩成人中文字幕在线观看| 久久久精品免费视频| 国产精品久久久久久中文字| 亚洲精品98久久久久久中文字幕| 日韩视频免费在线| 国产欧美精品在线播放| 国产精品日日做人人爱| 日韩电视剧免费观看网站| 亚洲美女www午夜| 色中色综合影院手机版在线观看| 国产一区二区三区在线播放免费观看| 久久久久国产精品免费网站| 色综合久久久久久中文网| 国产成人精品亚洲精品| 91牛牛免费视频| 国产精品爽爽爽爽爽爽在线观看| 91中文字幕在线| 国产精品青青在线观看爽香蕉| 亚洲国产精品国自产拍av秋霞| 青草热久免费精品视频| 日韩a**中文字幕| 国内揄拍国内精品少妇国语| 一本色道久久88亚洲综合88| 久久久久久久久久久免费精品| 成人免费网视频| 日韩国产激情在线| 亚洲国产精品久久精品怡红院| 国产精品久久久久影院日本| 91丝袜美腿美女视频网站| 亚洲天堂av电影| 亚洲精品国产电影| 亚洲开心激情网| 日韩中文字幕国产精品| 欧美激情精品久久久久久黑人| 久久久成人精品视频| 欧美性xxxxxxxxx| 亚洲黄页视频免费观看| 精品一区二区三区四区| 亚洲精品日韩激情在线电影| 精品视频在线播放| 午夜精品福利在线观看| 亚洲成人av在线播放| 国产日韩在线播放| 亚洲码在线观看| 国产精品狼人色视频一区| 国产精品视频网址| 国产亚洲美女精品久久久| 欧美一级视频一区二区| 91国偷自产一区二区三区的观看方式| 久久久精品2019中文字幕神马| 日韩免费看的电影电视剧大全| 亚洲老头老太hd| 国产精品视频久| 久久久精品电影| 亚洲精品v欧美精品v日韩精品| 亚洲国产精品久久久久秋霞蜜臀| 亚洲性av在线| 日韩h在线观看| 国产精品扒开腿爽爽爽视频| 欧美国产日本在线| 中文字幕欧美视频在线| 午夜剧场成人观在线视频免费观看| 欧美乱大交xxxxx另类电影| 国产福利精品视频| 国产成人精品久久亚洲高清不卡| 亚洲丝袜在线视频| 国产精品入口免费视频一| 日韩在线观看你懂的| 日韩电影中文字幕av| 人妖精品videosex性欧美| 久久艹在线视频| 狠狠躁夜夜躁人人爽天天天天97| 色中色综合影院手机版在线观看| 成人免费福利在线| 欧美精品电影免费在线观看| 最近中文字幕日韩精品| 亚洲欧洲成视频免费观看| 69av在线播放| 国产精品黄色av| 一本久久综合亚洲鲁鲁| 国产精品午夜视频| 韩国19禁主播vip福利视频| 欧美视频中文字幕在线| 日本乱人伦a精品| 成人精品久久av网站| 国产精品99久久久久久久久久久久| 欧美日韩视频免费播放| 午夜欧美大片免费观看| 久久久极品av| 7777kkkk成人观看| 亚洲精品suv精品一区二区| 日本精品久久久久久久| 国产偷亚洲偷欧美偷精品| 91九色精品视频| 这里只有精品视频| 成人久久一区二区| 91精品国产91久久久久久不卡| 日本久久久a级免费| 91精品久久久久久久久中文字幕| 97视频人免费观看| 揄拍成人国产精品视频| 国产免费一区二区三区香蕉精| 国产精品入口免费视| 亚洲精品小视频在线观看| 一区二区在线视频| 456国产精品| 亚洲精品久久久久久久久久久久| 亚洲国产中文字幕在线观看| 91在线直播亚洲| 91麻豆国产语对白在线观看| 精品国产一区久久久| 日韩电影中文字幕在线| 九色成人免费视频| 啪一啪鲁一鲁2019在线视频| 91最新在线免费观看| 欧美激情xxxxx| 精品国产欧美一区二区三区成人| 欧美一级黑人aaaaaaa做受| 欧美日本亚洲视频| 成人亚洲激情网| 98精品在线视频| 日韩中文在线视频| 日本一区二区三区四区视频| 欧美激情精品久久久久久大尺度| 国产成人精品免高潮在线观看| 精品美女国产在线| 欧美超级免费视 在线| 少妇精69xxtheporn| 国产成人极品视频| 精品一区二区三区电影| 欧美日韩免费在线| 亚洲永久免费观看| 久久精品视频网站| 日韩av综合网| 久久精品国产91精品亚洲| 日韩av免费在线观看| 欧美老少配视频| 亚洲人成网站999久久久综合| 欧美大学生性色视频| 欧美性开放视频| 亚洲国产精品久久久久| 精品久久久久久久中文字幕| 91久久精品一区| 国产精品盗摄久久久| 国产精品亚洲网站| www欧美日韩| 亚洲资源在线看| 久久99视频免费| 久久精品久久久久电影| 亚洲国产精品va在线看黑人动漫| 欧美性生交xxxxx久久久| 国产精品视频地址| 91免费版网站入口| 国产欧美一区二区白浆黑人| 日韩av网站电影| 国产精品美女呻吟|