
當我們編寫一個類時,其實就是在描述其對象的屬性和行為,而并沒有產(chǎn)生實質(zhì)上 的對象,只有通過new關(guān)鍵字才會產(chǎn)生出對象,這時系統(tǒng)才會分配內(nèi)存空間給對象, 其方法才可以供外部調(diào)用。我們有時候希望無論是否產(chǎn)生了對象或無論產(chǎn)生了多少 對象的情況下,某些特定的數(shù)據(jù)在內(nèi)存空間里只有一份,例如所有的中國人都有個 國家名稱,每一個中國人都共享這個國家名稱,不必在每一個中國人的實例對象中 都單獨分配一個用于代表國家名稱的變量。
如果想讓一個類的所有實例共享數(shù)據(jù),就用類變量!
class Person { private int id; public static int total = 0; public Person() { total++; id = total; }public static void main(String args[]){ Person Tom=new Person(); Tom.id=0; total=100; // 不用創(chuàng)建對象就可以訪問靜態(tài)成員 }}
public class StaticDemo {public static void main(String args[]) { Person.total = 100; // 不用創(chuàng)建對象就可以訪問靜態(tài)成員 //訪問方式:類名.類屬性,類名.類方法 System.out.println(Person.total); Person c = new Person(); System.out.println(c.total); //輸出101 } }
懶漢式暫時還存在線 程安全問題,講到多 線程時,可修復(fù)
(相關(guān)資料圖)
public class Runtime { private static Runtime currentRuntime = new Runtime(); /** * Returns the runtime object associated with the current Java application. * Most of the methods of class網(wǎng)站的計數(shù)器,一般也是單例模式實現(xiàn),否則難以同步。應(yīng)用程序的日志應(yīng)用,一般都使用單例模式實現(xiàn),這一般是由于共享的日志文件一直處于打開狀態(tài),因為只能有一個實例去操作,否則內(nèi)容不好追加。數(shù)據(jù)庫連接池的設(shè)計一般也是采用單例模式,因為數(shù)據(jù)庫連接是一種數(shù)據(jù)庫資源。項目中,讀取配置文件的類,一般也只有一個對象。沒有必要每次使用配置 文件數(shù)據(jù),都生成一個對象去讀取。Application也是單例的典型應(yīng)用Windows的==Task Manager (任務(wù)管理器)==就是很典型的單例模式Windows的==Recycle Bin (回收站)==也是典型的單例應(yīng)用。在整個系統(tǒng)運行過程中,回收站一直維護著僅有的一個實例。Runtime
are instance * methods and must be invoked with respect to the current runtime object. * * @return theRuntime
object associated with the current * Java application. */ public static Runtime getRuntime() { return currentRuntime; } /** Don"t let anyone else instantiate this class */ private Runtime() {}
public class CommandPara { public static void main(String[] args) { for (int i = 0; i < args.length; i++) { System.out.println("args[" + i + "] = " + args[i]); } }}
//運行程序CommandPara.javajava CommandPara “Tom" “Jerry" “Shkstart"http://輸出結(jié)果:args[0] = Tomargs[1] = Jerryargs[2] = Shkstart
class Person { public static int total; static { total = 100;//為total賦初值 } …… //其它屬性或方法聲明}靜態(tài)代碼塊:用static 修飾的代碼塊可以有輸出語句。可以對類的屬性、類的聲明進行初始化操作。不可以對非靜態(tài)的屬性初始化。即:不可以調(diào)用非靜態(tài)的屬性和方法。若有多個靜態(tài)的代碼塊,那么按照從上到下的順序依次執(zhí)行。靜態(tài)代碼塊的執(zhí)行要先于非靜態(tài)代碼塊。靜態(tài)代碼塊隨著類的加載而加載,且只執(zhí)行一次。非靜態(tài)代碼塊:沒有static修飾的代碼塊可以有輸出語句。可以對類的屬性、類的聲明進行初始化操作。除了調(diào)用非靜態(tài)的結(jié)構(gòu)外,還可以調(diào)用靜態(tài)的變量或方法。若有多個非靜態(tài)的代碼塊,那么按照從上到下的順序依次執(zhí)行。每次創(chuàng)建對象的時候,都會執(zhí)行一次。且先于構(gòu)造器執(zhí)行。
class Person { public static int total; static { total = 100; System.out.println("in static block!"); }}
public class PersonTest { public static void main(String[] args) { System.out.println("total = " + Person.total); System.out.println("total = " + Person.total); }}//輸出://in static block//total=100//total=100
總結(jié):程序中成員變量賦值的執(zhí)行順序
聲明成員變量的默認初始化顯式初始化、多個初始化塊依次被執(zhí)行(同級別下按先后順序執(zhí)行)構(gòu)造器再對成員進行初始化操作通過”對象.屬性”或”對象.方法”的方式,可多次給屬性賦值中國古代,什么人不能有后代,就可以被final聲明,稱為“太監(jiān)類”!
隨著繼承層次中一個個新子類的定義,類變得越來越具體,而父類則更一 般,更通用。類的設(shè)計應(yīng)該保證父類和子類能夠共享特征。有時將一個父 類設(shè)計得非常抽象,以至于它沒有具體的實例,這樣的類叫做抽象類。
用abstract關(guān)鍵字來修飾一個類,這個類叫做抽象類。用abstract來修飾一個方法,該方法叫做抽象方法。抽象方法:只有方法的聲明,沒有方法的實現(xiàn)。以分號結(jié)束:比如:public abstract void talk();含有抽象方法的類必須被聲明為抽象類。抽象類不能被實例化。抽象類是用來被繼承的,抽象類的子類必須重 寫父類的抽象方法,并提供方法體。若沒有重寫全部的抽象方法,仍 為抽象類。不能用abstract修飾變量、代碼塊、構(gòu)造器;不能用abstract修飾私有方法、靜態(tài)方法、final的方法、final的類。抽象類體現(xiàn)的就是一種模板模式的設(shè)計,抽象類作為多個子類的通用模 板,子類在抽象類的基礎(chǔ)上進行擴展、改造,但子類總體上會保留抽象 類的行為方式。
解決的問題:
當功能內(nèi)部一部分實現(xiàn)是確定的,一部分實現(xiàn)是不確定的。這時可以 把不確定的部分暴露出去,讓子類去實現(xiàn)。換句話說,在軟件開發(fā)中實現(xiàn)一個算法時,整體步驟很固定、通用, 這些步驟已經(jīng)在父類中寫好了。但是某些部分易變,易變部分可以抽 象出來,供不同子類實現(xiàn)。這就是一種模板模式。模板方法設(shè)計模式是編程中經(jīng)常用得到的模式。各個框架、類庫中都有他的 影子,比如常見的有:
數(shù)據(jù)庫訪問的封裝Junit單元測試JavaWeb的Servlet中關(guān)于doGet/doPost方法調(diào)用Hibernate中模板程序Spring中JDBCTemlate、HibernateTemplate等?class SubClass extends SuperClass implements InterfaceA{ }?
?一個類可以實現(xiàn)多個接口,接口也可以繼承其它接口。實現(xiàn)接口的類中必須提供接口中所有方法的具體實現(xiàn)內(nèi)容,方可實 例化。否則,仍為抽象類。接口的主要用途就是被實現(xiàn)類實現(xiàn)。(面向接口編程)與繼承關(guān)系類似,接口與實現(xiàn)類之間存在多態(tài)性接口和類是并列關(guān)系,或者可以理解為一種特殊的類。從本質(zhì)上講, 接口是一種特殊的抽象類,這種抽象類中只包含常量和方法的定義 (JDK7.0及之前),而沒有變量和方法的實現(xiàn)。概述:代理模式是Java開發(fā)中使用較多的一種設(shè)計模式。代理設(shè)計就是為其 他對象提供一種代理以控制對這個對象的訪問。
public interface Network { public void browse();}//被代理類class RealServer implements Network{ @Override public void browse() { System.out.println("真是服務(wù)i其上網(wǎng)瀏覽信息"); }}//代理類class ProxyServer implements Network{ private Network network; public ProxyServer(Network network) { this.network = network; } public ProxyServer() { } public void check(){ System.out.println("檢查網(wǎng)絡(luò)連接"); } public void browse(){ check(); network.browse(); }}
public class ProxyDemo { public static void main(String[] args) { Network net = new ProxyServer(new ProxyServer()); net.browse(); }}應(yīng)用場景:安全代理:屏蔽對真實角色的直接訪問。遠程代理:通過代理類處理遠程方法調(diào)用(RMI)延遲加載:先加載輕量級的代理對象,真正需要再加載真實對象 比如你要開發(fā)一個大文檔查看軟件,大文檔中有大的圖片,有可能一個圖片有 100MB,在打開文件時,不可能將所有的圖片都顯示出來,這樣就可以使用代理模式,當需要查看圖片時,用proxy來進行大圖片的打開。分類
靜態(tài)代理(靜態(tài)定義代理類)
動態(tài)代理(動態(tài)生成代理類)
JDK自帶的動態(tài)代理,需要反射等知識
No. | 區(qū)別點 | 抽象類 | 接口 |
1 | 定義 | 包含抽象方法的類 | 主要是抽象方法和全局常量的集合 |
2 | 組成 | 構(gòu)造方法、抽象方法、普通方法、常量、變量 | 常量、抽象方法、(jdk:默認方法、靜態(tài)方法) |
3 | 使用 | 子類繼承抽象類(extends) | 子類實現(xiàn)接口(implements) |
4 | 關(guān)系 | 抽象類可以實現(xiàn)多個接口 | 接口不能繼承抽象類,只能繼承多個接口 |
5 | 常見設(shè)計模式 | 模板方法 | 簡單工廠、工廠方法、代理模式 |
6 | 對象 | 都通過對象的多態(tài)性產(chǎn)生實例化對象 | 都通過對象的多態(tài)性產(chǎn)生實例化對象 |
7 | 局限 | 抽象類有單繼承的局限 | 接口沒有此局限 |
8 | 實際 | 作為一個模板 | 只作為一個標準或者是一種能力 |
9 | 選擇 | 如果抽象類和接口都可以使用的話,優(yōu)先使用接口,避免單繼承的局限性 |
Java 8中,你可以為接口添加靜態(tài)方法和默認方法。從技術(shù)角度來說,這是完 全合法的,只是它看起來違反了接口作為一個抽象定義的理念。
靜態(tài)方法:使用 static關(guān)鍵字修飾。可以通過接口直接調(diào)用靜態(tài)方法,并執(zhí)行 其方法體。我們經(jīng)常在相互一起使用的類中使用靜態(tài)方法。你可以在標準庫中 找到像Collection/Collections或者Path/Paths這樣成對的接口和類。
默認方法:默認方法使用 default關(guān)鍵字修飾??梢酝ㄟ^實現(xiàn)類對象來調(diào)用。 我們在已有的接口中提供新方法的同時,還保持了與舊版本代碼的兼容性。 比如:java 8 API中對Collection、List、Comparator等接口提供了豐富的默認 方法。
【注意】
非static的成員內(nèi)部類中的成員不能聲明為static的,只有在外部類或static的成員 內(nèi)部類中才可聲明static成員。外部類訪問成員內(nèi)部類的成員,需要“內(nèi)部類.成員”或“內(nèi)部類對象.成員”的方式成員內(nèi)部類可以直接使用外部類的所有成員,包括私有的數(shù)據(jù)當想要在外部類的靜態(tài)成員部分使用內(nèi)部類時,可以考慮內(nèi)部類聲明為靜態(tài)的內(nèi)部類舉例1
class Outer{ private int s; public class Inner{ public void mb(){ s=100; System.out.println("在內(nèi)部類Inner中s=" + s); } } public void ma(){ Inner i = new Inner(); i.mb(); }}public class InnerTest { public static void main(String[] args) { Outer2 o = new Outer2(); o.ma(); }}
public class Outer2 { private int s =111; public class Inner{ private int s =222; public void mb(int s){ System.out.println(s);//局部變量s System.out.println(this.s);//內(nèi)部類對象的屬性s System.out.println(Outer2.this.s);//外部類對象屬性s } } public static void main(String[] args) { Outer2 a = new Outer2(); Outer2.Inner b = a.new Inner(); b.mb(333); }}如何聲明局部內(nèi)部類
class 外部類{ 方法(){ class 局部內(nèi)部類{ } } { class 局部內(nèi)部類{ } }}如何使用局部內(nèi)部類只能在聲明它的方法或代碼塊中使用,而且是先聲明后使用。除此之外的任何地方 都不能使用該類但是它的對象可以通過外部方法的返回值返回使用,返回值類型只能是局部內(nèi)部類的父類或父接口類型局部內(nèi)部類的特點內(nèi)部類仍然是一個獨立的類,在編譯之后內(nèi)部類會被編譯成獨立的.class文件,但 是前面冠以外部類的類名和$符號,以及數(shù)字編號。只能在聲明它的方法或代碼塊中使用,而且是先聲明后使用。除此之外的任何地方 都不能使用該類。局部內(nèi)部類可以使用外部類的成員,包括私有的。局部內(nèi)部類可以使用外部方法的局部變量,但是必須是final的。由局部內(nèi)部類和局 部變量的聲明周期不同所致。局部內(nèi)部類和局部變量地位類似,不能使用public,protected,缺省,private局部內(nèi)部類不能使用static修飾,因此也不能包含靜態(tài)成員
new 父類構(gòu)造器(實參列表)|實現(xiàn)接口(){ //匿名內(nèi)部類的類體部分}匿名內(nèi)部類的特點匿名內(nèi)部類必須繼承父類或?qū)崿F(xiàn)接口匿名內(nèi)部類只能有一個對象匿名內(nèi)部類對象只能使用多態(tài)形式引用
public class Test { public Test() { Inner s1 = new Inner(); s1.a = 10; System.out.println("s1.a" + s1.a); Inner s2 = new Inner(); s2.a = 20; System.out.println("s2.a" + s2.a); Test.Inner s3 = new Inner(); System.out.println(s3.a); } class Inner { public int a =5; } public static void main(String[] args) { Test t = new Test(); Inner r = t.new Inner(); System.out.println(r.a); }}
interface car { void run();}
public class Audi implements car{ public void run(){ System.out.println("Audi is running"); }}
public class BYD implements car{ @Override public void run() { System.out.println("BYD running"); }}
public class Client01 { public static void main(String[] args) { Audi audi = new Audi(); BYD byd = new BYD(); audi.run(); byd.run(); }}
interface Car { void run();}class Audi implements Car{ @Override public void run() { System.out.println("Audi running..."); }}class BYD implements Car { @Override public void run() { System.out.println("BYD running"); }}
class CarFactory { public static Car getCar(String type) { if ("Audi".equals(type)){ return new Audi(); }else if ("BYD".equals(type)) { return new BYD(); }else { return null; } }}
public class Client02 { public static void main(String[] args) { Car audi = CarFactory.getCar("Audi"); audi.run(); Car byd = CarFactory.getCar("BYD"); byd.run(); }}
調(diào)用者只要知道他要什么,從哪里拿,如何創(chuàng)建,不需要知道。分工,多出了一 個專門生產(chǎn) Car 的實現(xiàn)類對象的工廠類。把調(diào)用者與創(chuàng)建者分離。
小結(jié):
簡單工廠模式也叫靜態(tài)工廠模式,就是工廠類一般是使用靜態(tài)方法,通過接收的 參數(shù)的不同來返回不同的實例對象。 缺點:對于增加新產(chǎn)品,不修改代碼的話,是無法擴展的。違反了開閉原則(對 擴展開放;對修改封閉)。
為了避免簡單工廠模式的缺點,不完全滿足 OCP(對擴展開放,對修改關(guān)閉)。 工廠方法模式和簡單工廠模式最大的不同在于,簡單工廠模式只有一個(對于一 個項目或者一個獨立的模塊而言)工廠類,而工廠方法模式有一組實現(xiàn)了相同接 口的工廠類。這樣在簡單工廠模式里集中在工廠方法上的壓力可以由工廠方法模 式里不同的工廠子類來分擔。
interface Car { void run();}class Audi implements Car { @Override public void run() { System.out.println("Audi is running"); }}class BYD implements Car{ @Override public void run() { System.out.println("BYD is running"); }}
//工廠接口public interface Factory { Car getCar();}class AudiFactory implements Factory { @Override public Audi getCar() { return new Audi(); }}class BydFactory implements Factory { @Override public BYD getCar() { return new BYD(); }}
public class Client { public static void main(String[] args) { Car a = new AudiFactory().getCar(); Car b = new BydFactory().getCar(); a.run(); b.run(); }}
總結(jié): 簡單工廠模式與工廠方法模式真正的避免了代碼的改動了?沒有。在簡單工廠模 式中,新產(chǎn)品的加入要修改工廠角色中的判斷語句;而在工廠方法模式中,要么 將判斷邏輯留在抽象工廠角色中,要么在客戶程序中將具體工廠角色寫死(就像 上面的例子一樣)。而且產(chǎn)品對象創(chuàng)建條件的改變必然會引起工廠角色的修改。 面對這種情況,Java 的反射機制與配置文件的巧妙結(jié)合突破了限制——這在 Spring 中完美的體現(xiàn)了出來。
==抽象工廠模式和工廠方法模式的區(qū)別就在于需要創(chuàng)建對象的復(fù)雜程度上。==而且抽象工廠模式是三個里面最為抽象、最具一般性的。
抽象工廠模式的用意為:給客戶端提供一個接口,可以創(chuàng)建多個產(chǎn)品族中的產(chǎn)品對象。
而且使用抽象工廠模式還要滿足一下條件:
系統(tǒng)中有多個產(chǎn)品族,而系統(tǒng)一次只可能消費其中一族產(chǎn)品。同屬于同一個產(chǎn)品族的產(chǎn)品以其使用。看過了前兩個模式,對這個模式各個角色之間的協(xié)調(diào)情況應(yīng)該心里有個數(shù)了,我 就不舉具體的例子了
標簽: 工廠模式 抽象方法 匿名內(nèi)部類