day27-Java反射/設(shè)計模式

27.01_類的加載概述和加載時機

  • 當(dāng)程序要使用某個類時潮改,如果該類還未被加載到內(nèi)存中徙菠,則系統(tǒng)會通過加載連接鹤盒,初始化三步來實現(xiàn)對這個類進行初始化。

  • 加載

    • 就是指將class文件讀入內(nèi)存侦副,并為之創(chuàng)建一個Class對象侦锯。任何類被使用時系統(tǒng)都會建立一個Class對象。
  • 連接

    • 1.驗證 是否有正確的內(nèi)部結(jié)構(gòu)秦驯,并和其他類協(xié)調(diào)一致
    • 2.準備 負責(zé)為類的靜態(tài)成員分配內(nèi)存尺碰,并設(shè)置默認初始化值
    • 3.解析 將類的二進制數(shù)據(jù)中的符號引用替換為直接引用
  • 初始化 就是我們以前講過的初始化步驟

  • B:加載時機

* 創(chuàng)建類的實例
* 訪問類的靜態(tài)變量,或者為靜態(tài)變量賦值
* 調(diào)用類的靜態(tài)方法
* 使用反射方式來強制創(chuàng)建某個類或接口對應(yīng)的java.lang.Class對象
* 初始化某個類的子類
* 直接使用java.exe命令來運行某個主類

27.02_類加載器的概述和分類

  • A:類加載器的概述 : 負責(zé)將.class文件加載到內(nèi)存中译隘,并為之生成對應(yīng)的Class對象亲桥。雖然我們不需要關(guān)心類加載機制,但是了解這個機制我們就能更好的理解程序的運行固耘。
  • B:類加載器的分類
    • Bootstrap ClassLoader根類加載器
    • Extension ClassLoader擴展類加載器
    • Sysetm ClassLoader 系統(tǒng)類加載器
  • C:類加載器的作用
- Bootstrap ClassLoader 根類加載器
    - 也被稱為引導(dǎo)類加載器题篷,負責(zé)Java核心類的加載
    - 比如System,String等。在JDK中JRE的lib目錄下rt.jar文件中
- Extension ClassLoader 擴展類加載器
    - 負責(zé)JRE的擴展目錄中jar包的加載厅目。
    - 在JDK中JRE的lib目錄下ext目錄
- Sysetm ClassLoader 系統(tǒng)類加載器
    - 負責(zé)在JVM啟動時加載來自java命令的class文件番枚,以及classpath環(huán)境變量所指定的jar包和類路徑

27.03_反射概述

  • 1.1JAVA反射機制是在運行狀態(tài)中,對于任意一個類损敷,都能夠知道這個類的所有屬性和方法葫笼;
  • 1.2對于任意一個對象,都能夠調(diào)用它的任意一個方法和屬性拗馒;
  • 1.3這種動態(tài)獲取的信息以及動態(tài)調(diào)用對象的方法的功能稱為java語言的反射機制路星。
  • 1.4要想解剖一個類,必須先要獲取到該類的字節(jié)碼文件對象。
  • 1.5而解剖使用的就是Class類中的方法诱桂,所以先要獲取到每一個字節(jié)碼文件對應(yīng)的Class類型的對象洋丐。
  • 推薦2篇詳細講解Java反射的優(yōu)秀文章:
    Java基礎(chǔ)與提高干貨系列——Java反射機制
    Java反射詳解
Class clazz1 = Class.forName("com.bean.Person");
Class<?> clazz2 = Person.class;
Class<?> clazz3 = new Person().getClass();   //加不加<?>都一樣呈昔,

System.out.println(clazz1 == clazz2);

Class<?> 相當(dāng)于 Class<? extends Object>
?是個通配符,可以用任何由Object派生的類型代替
反射的三個階段.png

27.04_反射(Class.forName()讀取配置文件舉例)

// 反射和配置文件
BufferedReader br = new BufferedReader(new FileReader("config.plist"));
Class<?> clazz = Class.forName(br.readLine());  //從文件中讀取了類名(全類名)
br.close();

Juicer j = new Juicer();
j.run( (Apple)clazz.newInstance() ); //使用 Class 創(chuàng)建了對象

--------------------分割線-----------------------------
class Juicer {
    public void run(Apple a) {  a.squeeze();  }
}
class Apple {
    public void squeeze() { System.out.println("炸出一杯蘋果汁"); }
}

27.05_通過反射獲取帶參構(gòu)造方法并使用

  • 關(guān)鍵類:Constructor構(gòu)造方法類
    Class類的newInstance()方法是使用該類無參的構(gòu)造函數(shù)創(chuàng)建對象, 如果一個類沒有無參的構(gòu)造函數(shù), 就不能這樣創(chuàng)建了,可以調(diào)用Class類的getConstructor(String.class,int.class)方法獲取一個指定的構(gòu)造函數(shù)然后再調(diào)用Constructor類的newInstance("張三",20)方法創(chuàng)建對象
Class<?> clazz = Class.forName("com.bean.Person");
Constructor<?> c = clazz.getConstructor(String.class,int.class); //獲取class的構(gòu)造(有參)方法類
Person p = (Person) c.newInstance("張六",23); //使用有參構(gòu)造方法類創(chuàng)建對象
System.out.println(p);
System.out.println(clazz.getConstructors());  //獲取所有構(gòu)造方法

27.06_通過反射獲取成員變量并使用

  • 關(guān)鍵類: Field成員變量類
    Class.getField(String)方法可以獲取類中的指定字段(可見的), 如果是私有的可以用getDeclaedField("name")方法獲取,通過set(obj, "李四")方法可以設(shè)置指定對象上該字段的值, 如果是私有的需要先調(diào)用setAccessible(true)設(shè)置訪問權(quán)限,用獲取的指定的字段調(diào)用get(obj)可以獲取指定對象中該字段的值
// 通過反射友绝,獲取 成員變量
Class<?> clazz = Class.forName("com.bean.Person");
Constructor<?> c = clazz.getConstructor(String.class,int.class); //獲取class的構(gòu)造(有參)方法類
Person p = (Person) c.newInstance("張六",23); //使用有參構(gòu)造方法類創(chuàng)建對象

//Field f = clazz.getField("name");  //獲取name成員屬性  只能獲取public的成員屬性

Field f = clazz.getDeclaredField("name"); //暴力反射堤尾,獲取私有字段(成員屬性/變量)
f.setAccessible(true);  //去除私有權(quán)限,必須這樣只會九榔,才能修改值
f.set(p, "我日哀峻,這也可以");  //修改字段的值
System.out.println(p);

27.07_通過反射獲取方法并使用

  • 關(guān)鍵類: Method成員方法類
    Class.getMethod(String, Class...)Class.getDeclaredMethod(String, Class...)方法可以獲取類中的指定方法,調(diào)用invoke(Object, Object...)可以調(diào)用該方法,比如Class.getMethod("eat") invoke(obj)Class.getMethod("eat",int.class) invoke(obj,10)
Class<?> clazz = Class.forName("com.bean.Person");
Constructor<?> c = clazz.getConstructor(String.class , int.class);
Person p = (Person) c.newInstance("大叔",40);

Method m = clazz.getMethod("eat");  //獲取eat方法,沒有參數(shù)
m.invoke(p); //運行獲取的eat方法哲泊,沒有參數(shù)

Method m3 = clazz.getMethod("eat", int.class); //獲取eat方法剩蟀,帶參數(shù)的
m3.invoke(p, 12); //運行獲取的eat方法。帶參數(shù)切威。

Method m2 = clazz.getDeclaredMethod("sleep"); //獲取私有方法育特,沒有參數(shù)
m2.setAccessible(true);  //想要運行私有方法,必須先讓方法可見
m2.invoke(p); //運行獲取的私有方法先朦,沒有參數(shù)

27.08_通過反射越過泛型檢查)

  • ArrayList<Integer>的一個對象缰冤,在這個集合中添加一個字符串?dāng)?shù)據(jù),如何實現(xiàn)呢喳魏?
// 1.不通過反射的辦法, 泛型擦除棉浸,泛型只是在編譯期做語法檢查的,運行期泛型會被擦除掉
ArrayList list = null;
ArrayList<Integer> intList = new ArrayList<>();
intList.add(100);
list = intList;  //改變list的內(nèi)存指向
list.add("XXOO...我是字符串...");   //實際此時已經(jīng)把字符串 添加到  ArrayList<Integer> 里面了
System.out.println(intList);


// 2.通過 反射 
ArrayList<Integer> intList = new ArrayList<>();
intList.add(100);

Class<?> clazz = Class.forName("java.util.ArrayList");
Method m = clazz.getMethod("add", Object.class);  //獲取add方法
m.invoke(intList, "我是字符串刺彩,我進入int泛型集合了迷郑!");
System.out.println(intList);

27.09_通過反射寫一個通用的設(shè)置某個對象的某個屬性為指定的值

/**
 * 把某個對象的屬性,改成自己想要的值
 * @param obj 對象
 * @param k 對象的屬性名稱创倔,字符串
 * @param v 要改成的值
 */
public static void setPropertyByName(Object obj, String k, Object v) throws Exception {
    Class<?> clazz = obj.getClass();
    Field f = clazz.getDeclaredField(k); //不管私有方法還是public的嗡害,都能獲取 暴力反射
    f.setAccessible(true);  //去除權(quán)限
    f.set(obj, v);
}

27.11_動態(tài)代理的概述和實現(xiàn)

  • 動態(tài)代理:在程序運行過程中產(chǎn)生的這個對象,而程序運行過程中產(chǎn)生對象其實就是我們剛才反射講解的內(nèi)容,所以畦攘,動態(tài)代理其實就是通過反射來生成一個代理霸妹。
  • 在Java中java.lang.reflect包下提供了一個Proxy類和一個InvocationHandler接口,通過使用這個類和接口就可以生成動態(tài)代理對象知押。JDK提供的代理只能針對接口做代理叹螟。我們有更強大的代理cglib(JavaEE講),Proxy類中的方法創(chuàng)建動態(tài)代理類對象.
interface Animal {  void eat();  }

class Dog implements Animal {
    public void eat() {
        System.out.println("狗改不了吃屎朗徊!");
    }
}

---------------分割線---------------
class MyInvocationHandler implements InvocationHandler { //自定義代理功能類
    private Object target;
    public MyInvocationHandler(Object target) {
        this.target = target;
    }
    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
        System.out.println("先做一些事情...");
        method.invoke(target, args);  //執(zhí)行被代理target對象的方法首妖,多個參數(shù)本的本質(zhì)是數(shù)組
        System.out.println("后做一些事情...");
        return null;
    }
}
---------------分割線---------------
Dog dog = new Dog();

MyInvocationHandler delegate = new MyInvocationHandler(dog);
ClassLoader l = dog.getClass().getClassLoader();  //固定寫法
Class<?>[] inter = dog.getClass().getInterfaces(); //固定寫法

Animal animal = (Animal) Proxy.newProxyInstance(l, inter, delegate);
animal.eat();  //等于是讓代理類,在方法運行時 多處理了一些事情爷恳。

27.12_設(shè)計模式(模版(Template)設(shè)計模式概述和使用)

模版方法模式就是定義一個算法的骨架,而將具體的算法延遲到子類中來實現(xiàn)

  • a:優(yōu)點 : 使用模版方法模式象踊,在定義算法骨架的同時温亲,可以很靈活的實現(xiàn)具體的算法棚壁,滿足用戶靈活多變的需求
  • b:缺點 : 如果算法骨架有修改的話,則需要修改抽象類
// 一個抽象類栈虚,目的是計算一段代碼運行的耗時
// 但是運行什么代碼袖外,是不知道的,需要子類去實現(xiàn)具體的代碼
abstract class GetTime {
    public final void getTime() {  // final目的是不讓子類重寫
        long s = System.currentTimeMillis();
        code();
        long e = System.currentTimeMillis();
        System.out.println(e - s);
    }

    public abstract void code() ; // abstract必須讓子類重寫 
}

27.14_設(shè)計模式

  • 目前已學(xué)已講的設(shè)計模式:
1,裝飾 : 在不必改變原類文件和使用繼承的情況下魂务,動態(tài)地擴展一個對象的功能曼验。典型就是JavaIO框架。
2,單例 : 一個類有且僅有一個實例粘姜,并且自行實例化向整個系統(tǒng)提供鬓照。
3,簡單工廠 : 專門生產(chǎn)勢力的類,把類的實例過程抽取到一個專門的類里孤紧。
4,工廠方法 : 創(chuàng)建一個工廠接口和創(chuàng)建多個工廠實現(xiàn)類豺裆,這樣一旦需要增加新的功能,直接增加新的工廠類就可以了
5,適配器 : 將一個類的接口轉(zhuǎn)換成客戶希望的另外一個接口号显。典型就是GUI里各種事件的處理臭猜。
6,模版 : 定義一個操作中的算法的骨架,而將步驟延遲到子類中。
7,動態(tài)代理 : 在實現(xiàn)階段不用關(guān)心代理類押蚤,而在運行階段才指定哪一個對象蔑歌。
  • 總體來說設(shè)計模式分為三大類:
  • 創(chuàng)建型模式,共五種:工廠方法模式揽碘、抽象工廠模式次屠、單例模式、建造者模式钾菊、原型模式帅矗。
  • 結(jié)構(gòu)型模式,共七種:適配器模式煞烫、裝飾器模式浑此、代理模式、外觀模式滞详、橋接模式凛俱、組合模式、享元模式料饥。
  • 行為型模式蒲犬,共十一種:策略模式、模板方法模式岸啡、觀察者模式原叮、迭代子模式、責(zé)任鏈模式、命令模式奋隶、備忘錄模式擂送、狀態(tài)模式、訪問者模式唯欣、中介者模式嘹吨、解釋器模式。
    其實還有兩類:并發(fā)型模式和線程池模式境氢。用一個圖片來整體描述一下:
設(shè)計模式1.png
設(shè)計模式2.png

END蟀拷。
我是小侯爺。
在魔都艱苦奮斗萍聊,白天是上班族问芬,晚上是知識服務(wù)工作者。
如果讀完覺得有收獲的話脐区,記得關(guān)注和點贊哦愈诚。
非要打賞的話,我也是不會拒絕的牛隅。

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末炕柔,一起剝皮案震驚了整個濱河市,隨后出現(xiàn)的幾起案子媒佣,更是在濱河造成了極大的恐慌匕累,老刑警劉巖,帶你破解...
    沈念sama閱讀 221,331評論 6 515
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件默伍,死亡現(xiàn)場離奇詭異欢嘿,居然都是意外死亡,警方通過查閱死者的電腦和手機也糊,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 94,372評論 3 398
  • 文/潘曉璐 我一進店門炼蹦,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人狸剃,你說我怎么就攤上這事掐隐。” “怎么了钞馁?”我有些...
    開封第一講書人閱讀 167,755評論 0 360
  • 文/不壞的土叔 我叫張陵虑省,是天一觀的道長。 經(jīng)常有香客問我僧凰,道長探颈,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 59,528評論 1 296
  • 正文 為了忘掉前任训措,我火速辦了婚禮伪节,結(jié)果婚禮上光羞,老公的妹妹穿的比我還像新娘。我一直安慰自己架馋,他們只是感情好狞山,可當(dāng)我...
    茶點故事閱讀 68,526評論 6 397
  • 文/花漫 我一把揭開白布全闷。 她就那樣靜靜地躺著叉寂,像睡著了一般。 火紅的嫁衣襯著肌膚如雪总珠。 梳的紋絲不亂的頭發(fā)上屏鳍,一...
    開封第一講書人閱讀 52,166評論 1 308
  • 那天,我揣著相機與錄音局服,去河邊找鬼钓瞭。 笑死,一個胖子當(dāng)著我的面吹牛淫奔,可吹牛的內(nèi)容都是我干的山涡。 我是一名探鬼主播,決...
    沈念sama閱讀 40,768評論 3 421
  • 文/蒼蘭香墨 我猛地睜開眼唆迁,長吁一口氣:“原來是場噩夢啊……” “哼鸭丛!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起唐责,我...
    開封第一講書人閱讀 39,664評論 0 276
  • 序言:老撾萬榮一對情侶失蹤鳞溉,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后鼠哥,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體熟菲,經(jīng)...
    沈念sama閱讀 46,205評論 1 319
  • 正文 獨居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 38,290評論 3 340
  • 正文 我和宋清朗相戀三年朴恳,在試婚紗的時候發(fā)現(xiàn)自己被綠了抄罕。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 40,435評論 1 352
  • 序言:一個原本活蹦亂跳的男人離奇死亡于颖,死狀恐怖呆贿,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情恍飘,我是刑警寧澤榨崩,帶...
    沈念sama閱讀 36,126評論 5 349
  • 正文 年R本政府宣布,位于F島的核電站章母,受9級特大地震影響母蛛,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜乳怎,卻給世界環(huán)境...
    茶點故事閱讀 41,804評論 3 333
  • 文/蒙蒙 一彩郊、第九天 我趴在偏房一處隱蔽的房頂上張望前弯。 院中可真熱鬧,春花似錦秫逝、人聲如沸恕出。這莊子的主人今日做“春日...
    開封第一講書人閱讀 32,276評論 0 23
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽浙巫。三九已至,卻和暖如春刷后,著一層夾襖步出監(jiān)牢的瞬間的畴,已是汗流浹背殉了。 一陣腳步聲響...
    開封第一講書人閱讀 33,393評論 1 272
  • 我被黑心中介騙來泰國打工状蜗, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人巧号。 一個月前我還...
    沈念sama閱讀 48,818評論 3 376
  • 正文 我出身青樓含衔,卻偏偏與公主長得像煎娇,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子贪染,可洞房花燭夜當(dāng)晚...
    茶點故事閱讀 45,442評論 2 359

推薦閱讀更多精彩內(nèi)容

  • Spring Cloud為開發(fā)人員提供了快速構(gòu)建分布式系統(tǒng)中一些常見模式的工具(例如配置管理缓呛,服務(wù)發(fā)現(xiàn),斷路器抑进,智...
    卡卡羅2017閱讀 134,693評論 18 139
  • Android 自定義View的各種姿勢1 Activity的顯示之ViewRootImpl詳解 Activity...
    passiontim閱讀 172,265評論 25 707
  • 積極主動强经;以終為始;要事第一 思想決定行動寺渗,行動決定習(xí)慣匿情,習(xí)慣決定品德,品德決定命運 承認自己的無知往往是求知的第...
    huangming003閱讀 190評論 0 1
  • 年齡二十好幾的人信殊,突然想寫我這一輩子這樣一個話題炬称,真不知道是受到了什么挫折還是生活讓你如此不堪,他剛看到她發(fā)的動態(tài)...
    涵辰閱讀 269評論 0 0
  • 孔老師要去生寶寶了涡拘,接下來的時間不能再每天和她朝夕相對玲躯,我很舍不得,會很想她吧鳄乏! 他其實是很自我的一個人跷车,這個假期...
    劉piano閱讀 121評論 0 0