單例模式
編程中出現(xiàn)了一個(gè)問題?
如果讓一個(gè)類在java內(nèi)存中只創(chuàng)建一個(gè)對(duì)象 ?
懶漢式/飽漢式
//懶漢式 ? 飽漢式
publicclassMyTool{
?
? ? privatestaticMyToolmyTool=null;
? ? //私有話構(gòu)造方法, 讓使用者無法new對(duì)象
? ? //這樣使用者就沒有辦法創(chuàng)建多個(gè)對(duì)象了
? ? privateMyTool(){}
? ? //提供一個(gè)靜態(tài)方法, 使用者調(diào)用這個(gè)方法可以獲取對(duì)象
? ? //這樣,我們就可以控制創(chuàng)建的對(duì)象了
? ? publicstaticMyToolgetInstance(){
? ? ? ? //第一次訪問時(shí),發(fā)現(xiàn)變量中沒有記錄對(duì)象, 就新建對(duì)象
? ? ? ? //如果已經(jīng)創(chuàng)建過對(duì)象,就直接返回
? ? ? ? if(myTool==null){
? ? ? ? ? ? myTool=newMyTool();
? ? ? ? }
? ? ? ? returnmyTool;
? ? }
? ? publicStringencoding(Stringstr){
? ? ? ? return"";
? ? }
}
?
餓漢式
//餓漢式
publicclassMyTool2{
?
? ? privatestaticMyTool2myTool=newMyTool2();
? ? //私有話構(gòu)造方法, 讓使用者無法new對(duì)象
? ? //這樣使用者就沒有辦法創(chuàng)建多個(gè)對(duì)象了
? ? privateMyTool2(){}
? ? //提供一個(gè)靜態(tài)方法, 使用者調(diào)用這個(gè)方法可以獲取對(duì)象
? ? //這樣,我們就可以控制創(chuàng)建的對(duì)象了
? ? publicstaticMyTool2getInstance(){
? ? ? ? returnmyTool;
? ? }
? ? publicStringencoding(Stringstr){
? ? ? ? return"";
? ? }
}
?
//餓漢式
publicclassMyTool3{
?
? ? publicstaticfinalMyTool3MY_TOOL=newMyTool3();
? ? //私有話構(gòu)造方法, 讓使用者無法new對(duì)象
? ? //這樣使用者就沒有辦法創(chuàng)建多個(gè)對(duì)象了
? ? privateMyTool3(){}
?
? ? publicStringencoding(Stringstr){
? ? ? ? return"";
? ? }
}
實(shí)現(xiàn)步驟
私有化構(gòu)造方法
自己創(chuàng)建對(duì)象并記錄住
保證這個(gè)變量的安全
總結(jié)
優(yōu)點(diǎn) :? 節(jié)省靜態(tài)方法區(qū)的內(nèi)存, 使用時(shí)效率高
缺點(diǎn) :? 相對(duì)于靜態(tài)來說, 效率還是要低一些
一. 枚舉
定義
枚舉是一個(gè)概念,列舉的意思,將所有的情況都列舉出來那么取值的時(shí)候只能是這幾種情況的一種,不能是別的
在Java中枚舉可以理解為有限制的多例,在當(dāng)前類中定義多個(gè)實(shí)例供別人使用
應(yīng)用場景
一個(gè)星期只有七天, 我們就可以把這些字符串裝在一個(gè)數(shù)組或者集合中供我們使用(這也是枚舉), 但是, 擴(kuò)展性非常差, 比如, 我們想顯示英文的就必須重寫一次, 使用枚舉類來實(shí)現(xiàn), 就是將變量放到一個(gè)類中,然后有限制的定義幾個(gè)對(duì)象使用
格式
空參構(gòu)造的枚舉類(沒有意義)
publicclassWeek{
? ? publicstaticfinalWeekMON=newWeek();
? ? publicstaticfinalWeekTUE=newWeek();
? ? publicstaticfinalWeekWED=newWeek();
? ? publicstaticfinalWeekTHU=newWeek();
? ? publicstaticfinalWeekFRI=newWeek();
? ? publicstaticfinalWeekSAT=newWeek();
? ? publicstaticfinalWeekSUN=newWeek();
}
有參構(gòu)造的枚舉類
publicclassWeek{
? ? publicstaticfinalWeekMON=newWeek("星期一");
? ? publicstaticfinalWeekTUE=newWeek("星期二");
? ? publicstaticfinalWeekWED=newWeek("星期三");
? ? publicstaticfinalWeekTHU=newWeek("星期四");
? ? publicstaticfinalWeekFRI=newWeek("星期五");
? ? publicstaticfinalWeekSAT=newWeek("星期六");
? ? publicstaticfinalWeekSUN=newWeek("星期日");
? ? privateStringname;
? ? //私有化構(gòu)造
? ? privateWeek(Stringname){
? ? ? ? this.name=name;
? ? }
? ? //提供getter方法,便于別人使用
? ? publicStringgetName() {
? ? ? ? returnname;
? ? }
?
}
有方法的枚舉類
publicclassWeek{
? ? publicstaticfinalWeekMON=newWeek("星期一");
? ? publicstaticfinalWeekTUE=newWeek("星期二");
? ? publicstaticfinalWeekWED=newWeek("星期三");
? ? publicstaticfinalWeekTHU=newWeek("星期四");
? ? publicstaticfinalWeekFRI=newWeek("星期五");
? ? publicstaticfinalWeekSAT=newWeek("星期六");
? ? publicstaticfinalWeekSUN=newWeek("星期日");
? ? publicStringname;
? ? //私有化構(gòu)造
? ? privateWeek(Stringname){
? ? ? ? this.name=name;
? ? }
? ? //提供getter方法,便于別人使用
? ? publicStringgetName() {
? ? ? ? returnname;
? ? }
? ? //提供特殊方法
? ? publicvoidshow(){
? ? ? ? System.out.println("今天是"+name);
? ? }
}
包含抽象方法的枚舉類
publicabstractclassWeek{
? ? privatestaticfinalWeekMON=newWeek("星期一"){
? ? ? ? publicvoidshow(){
? ? ? ? ? ? System.out.println("星期一好難受");
? ? ? ? }
? ? };
? ? privatestaticfinalWeekTUE=newWeek("星期二"){
? ? ? ? publicvoidshow(){
? ? ? ? ? ? System.out.println("星期二暈暈乎乎");
? ? ? ? }
? ? };
? ? privatestaticfinalWeekWED=newWeek("星期三"){
? ? ? ? publicvoidshow(){
? ? ? ? ? ? System.out.println("咦,星期三了...");
? ? ? ? }
? ? };
? ? privatestaticfinalWeekTHU=newWeek("星期四"){
? ? ? ? publicvoidshow(){
? ? ? ? ? ? System.out.println("趕緊,趕緊,今天快點(diǎn)結(jié)束");
? ? ? ? }
? ? };
? ? privatestaticfinalWeekFRI=newWeek("星期五"){
? ? ? ? publicvoidshow(){
? ? ? ? ? ? System.out.println("哇,好棒,星期五了");
? ? ? ? }
? ? };
? ? privatestaticfinalWeekSAT=newWeek("星期六"){
? ? ? ? publicvoidshow(){
? ? ? ? ? ? System.out.println("睡的真舒服");
? ? ? ? }
? ? };
? ? privatestaticfinalWeekSUN=newWeek("星期日"){
? ? ? ? publicvoidshow(){
? ? ? ? ? ? System.out.println("好開心哦, 時(shí)間慢慢走哈");
? ? ? ? }
? ? };
? ? privateStringname;
? ? //私有化構(gòu)造
? ? privateWeek(Stringname){
? ? ? ? this.name=name;
? ? }
? ? //提供getter方法,便于別人使用
? ? publicStringgetName() {
? ? ? ? returnname;
? ? }
? ? publicabstractvoidshow();
}
注意事項(xiàng)
枚舉多用于將一組信息裝載到一個(gè)對(duì)象中
測試題
使用枚舉模擬撲克牌的制作牌的過程
二. enum關(guān)鍵字的枚舉(jdk1.5)
定義
jdk1.5推出了enum關(guān)鍵字來幫助我們簡化格式
省略了static final 關(guān)鍵字和創(chuàng)建對(duì)象
enum關(guān)鍵字還能對(duì)格式進(jìn)行檢查
演示
publicenumWeek2{
? ? //定義變量,指向?qū)ο?/p>
? ? MON("星期一") ,TUE("星期二") ,WED("星期三") ,THU("星期四") ,FRI("星期五") ,SAT("星期六") ,SUN("星期日") ;
? ? Stringname;
? ? //私有化構(gòu)造
? ? privateWeek2(Stringname){
? ? ? ? this.name=name;
? ? }
?
? ? publicStringgetName() {
? ? ? ? returnname;
? ? }
}
注意事項(xiàng)
定義枚舉類要用關(guān)鍵字enum
所有枚舉類都是Enum的子類
枚舉類的第一行上必須是枚舉項(xiàng)逗爹,最后一個(gè)枚舉項(xiàng)后的分號(hào)是可以省略的昔期,但是如果枚舉類有其他的東西怀吻,這個(gè)分號(hào)就不能省略。建議不要省略
枚舉類可以有構(gòu)造器约啊,但必須是private的,它默認(rèn)的也是private的。
枚舉類也可以有抽象方法拙徽,但是枚舉項(xiàng)必須重寫該方法
swicth語句可以使用枚舉
案例
publicstaticvoidmain(String[]args) {
? ? Week2week2=Week2.MON;
? ? switch(week2) {
? ? caseFRI:
? ? ? ? ? ? System.out.println("好高興哦");
? ? ? ? break;
? ? caseMON:
? ? ? ? System.out.println("過了星期三,越過越心寬");
? ? ? ? break;
? ? default:
? ? ? ? System.out.println("沒有了");
? ? ? ? break;
? ? }
}
常用方法
int ordinal() 獲取枚舉項(xiàng)的序號(hào)
int compareTo(E o)? 比較兩個(gè)枚舉項(xiàng)
String name() 獲取枚舉枚舉項(xiàng)的名稱
String toString() 獲取枚舉項(xiàng)的字符串表現(xiàn)形式
<T> T valueOf(Class<T> type,String name) 使用字節(jié)碼和名稱獲取枚舉項(xiàng)
values()
此方法雖然在JDK文檔中查找不到,但每個(gè)枚舉類都具有該方法诗宣,它遍歷枚舉類的所有枚舉值非常方便
三. 類加載
定義
當(dāng)程序要使用某個(gè)類時(shí)膘怕,如果該類還未被加載到內(nèi)存中,則系統(tǒng)會(huì)通過加載梧田,連接淳蔼,初始化三步來實(shí)現(xiàn)對(duì)這個(gè)類進(jìn)行初始化
加載
就是指將.class文件讀入內(nèi)存,并為之創(chuàng)建一個(gè)Class對(duì)象裁眯。任何類被使用時(shí)系統(tǒng)都會(huì)建立一個(gè)Class對(duì)象鹉梨。
連接
驗(yàn)證 是否有正確的內(nèi)部結(jié)構(gòu),并和其他類協(xié)調(diào)一致
準(zhǔn)備 負(fù)責(zé)為類的靜態(tài)成員分配內(nèi)存穿稳,并設(shè)置默認(rèn)初始化值
解析 將類的二進(jìn)制數(shù)據(jù)中的符號(hào)引用替換為直接引用
初始化 就是我們以前講過的初始化步驟
加載的時(shí)機(jī)(在類真正被使用時(shí))
創(chuàng)建類的實(shí)例
訪問類的靜態(tài)變量存皂,或者為靜態(tài)變量賦值
調(diào)用類的靜態(tài)方法
使用反射方式來強(qiáng)制創(chuàng)建某個(gè)類或接口對(duì)應(yīng)的java.lang.Class對(duì)象
加載某個(gè)類的子類
直接使用java.exe命令來運(yùn)行某個(gè)主類
四. 類加載器的概述和分類
定義
負(fù)責(zé)將.class文件加載到內(nèi)存中,并為之生成對(duì)應(yīng)的Class對(duì)象。雖然我們不需要關(guān)心類加載機(jī)制旦袋,但是了解這個(gè)機(jī)制我們就能更好的理解程序的運(yùn)行
類加載器的分類
Bootstrap ClassLoader 根類加載器
Extension ClassLoader 擴(kuò)展類加載器
Sysetm ClassLoader 系統(tǒng)類加載器
AppClassLoader 應(yīng)用類加載器
類加載器的作用
BootstrapClassLoader 根類加載器
也被稱為引導(dǎo)類加載器骤菠,負(fù)責(zé)Java核心類的加載
比如System,String等。在JDK中JRE的lib目錄下rt.jar文件中
ExtensionClassLoader 擴(kuò)展類加載器
負(fù)責(zé)JRE的擴(kuò)展目錄中jar包的加載疤孕。
在JDK中JRE的lib目錄下ext目錄
SysetmClassLoader 系統(tǒng)類加載器
負(fù)責(zé)在JVM啟動(dòng)時(shí)加載來自java命令的class文件商乎,以及classpath環(huán)境變量所指定的jar包和類路徑
AppClassLoader 加載其他類
負(fù)載一些非核心類和程序猿自己寫的類
演示
publicstaticvoidmain(String[]args) {
? ? //獲取TestDemo類的類加載器
? ? System.out.println(TestDemo.class.getClassLoader());
}
五. 自定義類加載器
雙親委派模型
當(dāng)前類加載器從自己已經(jīng)加載的類中查詢是否此類已經(jīng)加載,如果已經(jīng)加載則直接返回原來已經(jīng)加載的類祭阀。
如果沒有找到鹉戚,就去委托父類加載器去加載(如代碼c = parent.loadClass(name, false)所示)。父類加載器也會(huì)采用同樣的策略专控,查看自己已經(jīng)加載過的類中是否包含這個(gè)類抹凳,有就返回,沒有就委托父類的父類去加載伦腐,一直到根類加載器赢底。因?yàn)槿绻讣虞d器為空了,就代表使用根類類加載器作為父加載器去加載
如果根類類加載器加載失敯啬ⅰ(例如在$JAVA_HOME/jre/lib里未查找到該class)幸冻,會(huì)使用拓展類加載器來嘗試加載,繼續(xù)失敗則會(huì)使用AppClassLoader來加載辩越,繼續(xù)失敗則會(huì)拋出一個(gè)異常ClassNotFoundException嘁扼,然后再調(diào)用當(dāng)前加載器的findClass()方法進(jìn)行加載
好處
主要是為了安全性,避免用戶自己編寫的類動(dòng)態(tài)替換 Java的一些核心類黔攒,比如 String趁啸。
同時(shí)也避免了類的重復(fù)加載,因?yàn)?JVM中區(qū)分不同類督惰,不僅僅是根據(jù)類名不傅,相同的 class文件被不同的 ClassLoader加載就是不同的兩個(gè)類
案例演示
publicclassMyClassLoaderextendsClassLoader{
? ? privateStringpath;
? ? publicMyClassLoader(Stringpath) {
? ? ? ? super();
? ? ? ? this.path=path;
? ? }
? ? @Override
? ? protectedClass<?>findClass(Stringname)throwsClassNotFoundException{
? ? ? ? //讀取本地文件
? ? ? ? byte[]bs=getBytes(path);
? ? ? ? //將字節(jié)數(shù)組裝載成Class對(duì)象
? ? ? ? Class<?>clazz=this.defineClass(name,bs,0,bs.length);
? ? ? ? returnclazz;
? ? }
? ? privatebyte[]getBytes(Stringpath){
? ? ? ? try(
? ? ? ? ? ? FileInputStreamfis=newFileInputStream(path);
? ? ? ? ? ? ByteArrayOutputStreambos=newByteArrayOutputStream();
? ? ? ? ) {
? ? ? ? ? ? byte[]bs=newbyte[1024];
? ? ? ? ? ? intlen;
? ? ? ? ? ? while((len=fis.read(bs))!=-1){
? ? ? ? ? ? ? ? bos.write(bs,0,len);
? ? ? ? ? ? }
? ? ? ? ? ? returnbos.toByteArray();
? ? ? ? }catch(Exceptione) {
? ? ? ? }
? ? ? ? returnnull;
? ? }
}
publicstaticvoidmain(String[]args)throwsException{
? ? MyClassLoaderclassLoader=newMyClassLoader("D:\\Student.class");
? ? Class<?>clazz=classLoader.findClass("com.qianfeng.Student");
? ? //Class<?> class1 = Class.forName("com.qianfeng.Student", true, classLoader);
? ? Objectobj=clazz.newInstance();
? ? System.out.println(obj.getClass().getClassLoader());
}
六. 反射
定義
JAVA反射機(jī)制是在運(yùn)行狀態(tài)中,對(duì)于任意一個(gè)類赏胚,都能夠知道這個(gè)類的所有屬性和方法
對(duì)于任意一個(gè)對(duì)象访娶,都能夠調(diào)用它的任意一個(gè)方法和屬性
這種動(dòng)態(tài)獲取的信息以及動(dòng)態(tài)調(diào)用對(duì)象的方法的功能稱為java語言的反射機(jī)制
要想解剖一個(gè)類,必須先要獲取到該類的字節(jié)碼文件對(duì)象
而解剖使用的就是Class類中的方法,所以先要獲取到每一個(gè)字節(jié)碼文件對(duì)應(yīng)的Class類型的對(duì)象
說白了就是獲取一個(gè)類的骨架
獲取字節(jié)碼的三種方式
對(duì)象.getClass()
類名.class
Class類中靜態(tài)方法forName("類名")
演示
publicstaticvoidmain(String[]args)throwsException{
? ? Studentstudent=newStudent();
? ? Class<?>clazz1=student.getClass();
? ? Class<?>clazz2=Student.class;
? ? Class<?>clazz3=Class.forName("com.qianfeng.Student");
}
七. 反射獲取構(gòu)造函數(shù)
定義
Class類的newInstance()方法是使用該類無參的構(gòu)造函數(shù)創(chuàng)建對(duì)象
如果一個(gè)類沒有無參的構(gòu)造函數(shù), 就不能這樣創(chuàng)建了,可以調(diào)用Class類的getConstructor(String.class,int.class)方法獲取一個(gè)指定的構(gòu)造函數(shù)然后再調(diào)用Constructor類的newInstance("張三",20)方法創(chuàng)建對(duì)象
演示
publicstaticvoidmain(String[]args)throwsException{
? ? Class<?>clazz=Class.forName("com.qianfeng.Student");
? ? Studentobject=(Student)clazz.newInstance();
? ? object.method();
}
榨汁機(jī)案例
分別有水果(Fruit)蘋果(Apple)香蕉(Banana)桔子(Orange)榨汁(squeeze)
根據(jù)客戶的需求, 隨時(shí)更換果汁
interfaceFruit{
? ? publicvoidsqueeze();
}
?
classAppleimplementsFruit{
? ? publicvoidsqueeze() {
? ? ? ? System.out.println("榨出一杯蘋果汁兒");
? ? }
}
?
classOrangeimplementsFruit{
? ? publicvoidsqueeze() {
? ? ? ? System.out.println("榨出一杯桔子汁兒");
? ? }
}
?
classJuicer{
? ? publicvoidrun(Fruitf) {
? ? ? ? f.squeeze();
? ? }
?
}
publicstaticvoidmain(String[]args)throwsException{
? ? //從本地讀取配置文件
? ? BufferedReaderbr=newBufferedReader(newFileReader("config.txt"));
//創(chuàng)建輸入流對(duì)象,關(guān)聯(lián)配置文件?
? ? Class<?>clazz=Class.forName(br.readLine());? //讀取配置文件一行內(nèi)容,獲取該類的字節(jié)碼對(duì)象
? ? Fruitf=(Fruit)clazz.newInstance();? ? ? //通過字節(jié)碼對(duì)象創(chuàng)建實(shí)例對(duì)象
? ? Juicerj=newJuicer();
? ? j.run(f);
}
八. 反射獲取成員變量
定義
Class.getField(String)方法可以獲取類中的指定字段(可見的)
如果是私有的可以用getDeclaedField("name")方法獲取
通過get(obj) 和set(obj, "李四")方法可以獲取和設(shè)置指定對(duì)象上該字段的值, obj指的是這個(gè)類的對(duì)象
如果是私有的需要先調(diào)用setAccessible(true)設(shè)置訪問權(quán)限放開
演示
publicstaticvoidmain(String[]args)throwsException{
? ? Studentstudent=newStudent();
? ? Class<?>clazz=Class.forName("com.qianfeng.Student");
? //獲取共有的屬性
? ? Fieldfield=clazz.getField("name");
? //獲取所有的屬性
? ? Fieldfield2=clazz.getDeclaredField("name");
? ? //取消語言檢查
? ? field2.setAccessible(true);
? ? //給一個(gè)對(duì)象的屬性設(shè)置值
? ? field2.set(student,"333");
? ? //獲取這個(gè)對(duì)象的屬性的值
? ? Stringstr=(String)field2.get(student);
? ? System.out.println(str);
}
測試題
需求: 寫一個(gè)方法, 通過此方法可以給任意對(duì)象的任意屬性設(shè)置值
九. 反射獲取成員方法
定義
Class.getMethod(String, Class...) 和 Class.getDeclaredMethod(String, Class...)方法可以獲取類中的指定方法
調(diào)用invoke(Object, Object...)可以調(diào)用對(duì)象的這個(gè)方法
演示
publicstaticvoidmain(String[]args)throwsException{
? ? Studentstudent=newStudent();
? ? Class<?>clazz=Class.forName("com.qianfeng.Student");
? ? Methodmethod=clazz.getMethod("method");
? ? method.invoke(student);
? ? //獲取私有方法
? ? Methodmethod2=clazz.getDeclaredMethod("method2");
? ? //取消語言檢查
? ? method2.setAccessible(true);
? ? //調(diào)用對(duì)象的方法
? ? method2.invoke(student);
}
測試題
需求: 往一個(gè)ArrayList<Integer> 的對(duì)象中添加String類型的值
十. 動(dòng)態(tài)代理
定義
代理: 本來應(yīng)該自己做的事情觉阅,請(qǐng)了別人來做崖疤,被請(qǐng)的人就是代理對(duì)象
動(dòng)態(tài)代理:在程序運(yùn)行過程中產(chǎn)生的這個(gè)對(duì)象,而程序運(yùn)行過程中產(chǎn)生對(duì)象其實(shí)就是我們剛才反射講解的內(nèi)容,所以典勇,動(dòng)態(tài)代理其實(shí)就是通過反射來生成一個(gè)代理對(duì)象
代理可以使我們?cè)诓黄茐脑创a的情況下增加新的功能
java中動(dòng)態(tài)代理的使用
在Java中java.lang.reflect包下提供了一個(gè)Proxy類和一個(gè)InvocationHandler接口劫哼,通過使用這個(gè)類和接口就可以生成動(dòng)態(tài)代理對(duì)象
public static Object newProxyInstance(ClassLoader loader,Class<?>[] interfaces,InvocationHandler h)
最終會(huì)調(diào)用InvocationHandler的方法
InvocationHandler Object invoke(Object proxy,Method method,Object[] args)
演示
publicstaticvoidmain(String[]args)throwsException{
? ? Studentstudent=newStudent();
? ? //創(chuàng)建Student的代理對(duì)象
? ? MyInterfacep=(MyInterface)Proxy.newProxyInstance(Student.class.getClassLoader(),Student.class.getInterfaces(),newInvocationHandler() {
? ? ? ? @Override
? ? ? ? publicObjectinvoke(Objectproxy,Methodmethod,Object[]args)throwsThrowable{
? ? ? ? ? ? System.out.println("你好");
? ? ? ? ? ? method.invoke(student);
? ? ? ? ? ? returnnull;
? ? ? ? }
? ? });
? ? p.method();
}
原理
利用對(duì)象的類的字節(jié)碼接口,寫出一個(gè)新的類到本地區(qū),通過編譯器直接編譯成.class文件,再通過類加載器加載進(jìn)來
弊端: 代理的對(duì)象必須實(shí)現(xiàn)接口
十一. cglib
定義
非java原生的動(dòng)態(tài)代理, 效率更高,限制更小
可以代理沒有接口的類
使用
導(dǎo)包
演示
publicstaticvoidmain(String[]args) {
? ? //導(dǎo)入包? cglib-core? asm? ? ant? ? ant-launcher
? ? //創(chuàng)建運(yùn)行器
? ? MethodInterceptormi=newMethodInterceptor() {
? ? ? ? @Override
? ? ? ? publicObjectintercept(Objectarg0,Methodarg1,Object[]arg2,MethodProxyarg3)throwsThrowable{
? ? ? ? ? ? System.out.println("運(yùn)行前");
? ? ? ? ? ? arg3.invokeSuper(arg0,arg2);
? ? ? ? ? ? System.out.println("運(yùn)行后");
? ? ? ? ? ? returnnull;
? ? ? ? }
? ? };
? ? //獲取代理類
? ? Enhancerenhancer=newEnhancer();
? ? //設(shè)置父類
? ? enhancer.setSuperclass(Demo.class);
? ? //運(yùn)行任務(wù)
? ? enhancer.setCallback(mi);
? ? //創(chuàng)建代理對(duì)象
? ? Demod=(Demo)enhancer.create();
? ? d.method();
}
總結(jié)
單例模式
模式: 針對(duì)某種問題的最優(yōu)解
懶漢式, 餓漢式 , 餓漢式的變形體
如何寫單例模式
私有化構(gòu)造方法
提供自己創(chuàng)建的對(duì)象給使用者
優(yōu)點(diǎn) :
節(jié)省內(nèi)存空間,? 提升訪問的速度
缺點(diǎn) :
相對(duì)于靜態(tài)來說, 效率還是要低一些
枚舉
枚舉就是多例的簡寫形式
枚舉項(xiàng)的權(quán)限, 修飾符, 類型, new 省略
枚舉的注意事項(xiàng)
類加載
就是將.class文件從硬盤上讀取到內(nèi)存中,變成一個(gè)java可以使用的類
類加載器
四個(gè)類加載器和他們的應(yīng)用范圍
根類加載器不是java代碼寫的
雙親委派模型
加載一個(gè)類的時(shí)候,從最底層的類加載器開始逐層上傳, 一直到頂層, 整個(gè)過程要檢測這個(gè)類有沒有被加載過
作用 : 保持類的唯一性
反射
反射其實(shí)就是java提供的另外一種編程模式
提高了代碼的兼容性, 擴(kuò)展性
反射操作構(gòu)造方法, 操作成員變量, 操作成員方法
作業(yè)
把今天的案例都敲一遍