java-静态-单例-继承
概要圖
一.靜態
1.1 靜態方法
創建對象就是為了產生實例,并進行數據的封裝。
而調用功能時,確沒有用到這些對象中封裝的數據。
該對象的創建有意義嗎?雖然可以編譯并運行,但是在堆內存中空間較為浪費。
不建議創建對象。那該怎么調用呢?java中的解決方案就是 使用 static關鍵字,這是一個成員修飾符。
被靜態static修飾的方法除了可以被對象調用外,還可以被類名調用。
靜態看上去很美,是不是所有的方法都靜態呢?不行!
那么什么時候需要將方法定義成靜態的呢?
定義功能時,如果功能不需要訪問類中定義的成員變量(非靜態)時,該功能就需要靜態修飾
1.2 靜態方法使用注意事項:
1,靜態方法不能訪問非靜態的成員。
但是非靜態可以訪問靜態成員的。
說明:靜態的弊端在于訪問出現局限性。好處是可以直接被類名調用。
2,靜態方法中不允許出現this,super關鍵字。
為什么不行呢?
1.3 原理揭秘:
1,靜態是隨著類的加載就加載了。也是隨著類的消失而消失了。
2,靜態優先于對象存在,被對象共享。
3,因為靜態先存在于內存中無法訪問后來的對象的中的數據,所以靜態無法訪問非靜態。
而且內部無法書寫this。因為這時對象有可能不存在,this沒有任何指向。
1.4 靜態的主函數:
public static void main(String[] args)
public : 權限最大。
static :不需要對象。直接用給定的類名就可以訪問該函數了。
void : 不需要返回值。
main : 函數名,該名稱是固定的。
(String[] args) : 主函數的參數列表:字符串屬性類型的參數。
args : arguments :參數。該名稱就是一個變量名。
1.5靜態變量
什么時候定義靜態變量呢?
當該成員變量的值,每一個對象都一致時,就對該成員變量進行靜態修飾。
靜態變量和成員變量的區別:
1,所屬范圍不同。
靜態變量所屬于類,成員變量所屬對象。
靜態變量也稱為:類變量;成員變量也稱為實例變量。
2,調用不同。
靜態變量可以被對象和類調用(一般都用類名調用)
成員變量只能被對象調用。
3,加載時期不同。
靜態變量隨著類的加載而加載。
成員變量隨著對象的加載而加載。
4,內存存儲區域不同。
靜態變量存儲在方法區中。
成員變量存儲在堆內存中。
1.6 靜態加載的內存圖解
注意:這個過程對應上面代碼
1 運行一個類 這個類要加載 先在方法區開空間 加載的是字節碼文件 也就是.class文件.這里的類是.cirleDemo.classs
2 在方法區中會開一個專門用來存儲靜態的static code. ps:main在circleDemo類中.******
3 從main方法開始入口,把main方法調入到棧中,
4 加載.class 文件到方法區 這里的是circle.class
5 在加載cirle.class時,要把里面的static修飾的成員加載到static code中去.
6 加載完后 new開空間到堆里面. radius=0(默認),0x44 構造函數進棧.對成員變量初始化后構造函數彈棧
7 main方法中 c=0x44 getArea()進棧.
內存總體分為了4個部分
包括 stack segment、heap segment、code segment、data segment。
其中我們程序中用關鍵字new出來的東西都是存放在heap segment。
程序中的局部變量存放在stack segment,這些局部變量是在具體方法執行結束之后,系統自動釋放內存資源(而heap segment中的資源需要java垃圾回收機制來處理)。
程序中的方法,是內存中的code segment中的,而且是多個對象 共享一個代碼空間區域。
static靜態變量,需要放在內存中的data segment中。
?1.7 靜態代碼塊和局部代碼塊
1?靜態代碼塊
需求:類一加載,需要做一些動作。不一定需要對象。
學習目標:必須了解加載的順序。
靜態代碼塊:
特點:隨著類的加載而執行,僅執行一次。
作用:給類進行初始化。
2? 局部代碼塊(構造代碼塊)
/* 構造代碼塊:用于給所有的對象初始化。很少用并很少見。*/class Demo {int x = 4;//成員變量 1,默認初始化,2,顯示初始化。{// 構造代碼塊。只要創建對象就會被調用。給所有對象初始化,構造函數只給對應的對象針對性的初始化。//這里面可以定義不同構造函數的共性代碼。System.out.println("code run..."+x); 1 // System.out.println("----->hahah");}Demo(){System.out.println("demo run");}Demo(int x){System.out.println("demo run...."+x); // System.out.println("----->hahah");}}class ConstructorCodeDemo {public static void main(String[] args) {new Demo();new Demo(5);{//局部代碼塊,作用:就可以控制局部變量的生命周期。 2int x = 5;System.out.println(" 局部代碼塊..."+x);}System.out.println(" over...");} }二.單例
2.1?對象的初始化過程@
注意:這部分和上面的靜態加載內存圖解類似
下面講解的更加詳細
//對象的初始化過程。 class Demo { static int x = 1; int y = 1;static { System.out.println("static code...x="+x); }{ System.out.println("cons code ...y="+y); }Demo() { System.out.println("cons function ...y="+y); } }class CreateObjectTest { public static void main(String[] args) {/* 1,加載Demo.class文件進方法區,并進行空間分配。 2,如果有靜態變量,先默認初始化,顯示初始化。 3,如果有靜態代碼塊,要執行,僅一次。 4,通過new在堆內存中開辟空間,并明確首地址。 5,對對象中的屬性進行默認初始化。 6,調用對應的構造函數進行初始化。 7,構造函數內部。 7.1 調用父類構造函數super(); 7.2 成員變量的顯示初始化。 7.3 構造代碼塊初始化。 7.4 構造函數內容自定義內容初始化。 8,對象初始化完畢后,將地址賦值給d引用變量。 */ Demo d = new Demo(); } }2.2 單例@@
設計模式:解決某一類問題行之有效的解決辦法(思想)。
單例(Singleton)設計模式:
學習設計模式必須先弄清楚它是解決什么問題的@@@。
單例是解決什么問題的呢?
可以保證一個類的對象唯一性。
場景:比如多個程序都要使用一個配置文件中的數據,而且要實現數據共享和交換。
必須要將多個數據封裝到一個對象中。而且多個程序操作的是同一個對象。
那也就是說必須保證這個配置文件對象的唯一性。
怎么能保證對象的唯一性呢?
1,一個類只要提供了構造函數,就可以產生多個對象。
完全無法保證唯一。
既然數量不可控,干脆,不讓其他程序建立對象。
2,不讓其他程序創建,對象何在?
干脆,自己在本類中創建一個對象,這樣好處是什么,可控。
3,創建完成后,是不是要給其他程序提供訪問的方式。
怎么實現這個步驟呢?
1,怎么就能不其他程序創建對象呢?
直接私有化構造函數,不讓其他程序創建的對象初始化。
2,直接在本類中new一個本類對象。
3,定義一個功能,其他程序可以通過這個功能獲取到本類的對象。
哦耶。?
代碼體現。
//餓漢式
//懶漢式
//單例的延遲加載方式。面試最多的是懶漢式。
注意:上面的兩種方式的區別在于因為是靜態的,一個是在類加載就生成對象,另一個是在調用方法時才產和對象
//練習:將兩種方式的內存圖畫出來。
class SingleDemo { public static void main(String[] args) { //要想獲取Single的對象。調用getInstance方法。既然無法通過對象調用,只能用類名調用,所以這個方法必須是static。 Single ss = Single.getInstance(); Single ss2 = Single.getInstance();// Single ss = Single.s;//這種方式是可以實現,加入訪問來獲取就是為了對對象可控。 // Single ss2 = Single.s; } }?三 ,?繼承
3.1?繼承
/* //描述學生。 class Student { //屬性。 String name; int age;//行為。 void study() { System.out.println("good good study"); } }//描述工人。 class Worker { //屬性。 String name; int age;//行為 void work() { System.out.println("hard work"); } } *//*為了提高復用,只建立一份代碼。
一個類只要和另一個類產生關系就可以了
關系:繼承。
發現了獲取到所需內容的同時也獲取到不該具備的內容。
為什么?
發現原來這個兩個類之間根本就不存在繼承關系。
怎么解決呢?
找到學生和工人的共性類型。將需要提供復用的代碼進行抽取。
定義到一個共性類型的類中。
Person name age。
怎么在代碼體現中讓學生和Person產生關系呢?
面向對象 另一個特征:繼承。
好處:提高了代碼的復用性。讓類與類產生了關系,給另一個特征 多態 提供了前提。
什么時候定義繼承?
必須保證類與類之間有所屬(is a)關系。 xxx是zzz中的一種。
蘋果是水果中一種。狗是犬科中一種。
在Java中繼承的體現:
Java允許單繼承。不直接支持多繼承,將多繼承進行其他方式的體現。
單繼承:一個子類只能有一個父類。
多繼承:一個子類可以有多個父類。
看上起,多繼承很厲害!為什么。
z.show();//調用就會產生不確定性。所以java保留的多繼承的好處,改良它的弊端。用多實現來體現,即將學到。
java還支持多重繼承。
class A {} class B extends A {} class C extends B {}形成繼承體系。 學習繼承體系時,應該參閱頂層的類中的內容。 了解這個體系的基本功能。使用這個體系功能,需要創建最子類的對象。看頂層,建底層。*/class ExtendsDemo { public static void main(String[] args) { Student stu = new Student(); stu.name = "xiaoqiang"; stu.age = 12; stu.study();} }?
轉載于:https://www.cnblogs.com/liu-wang/p/8182024.html
總結
以上是生活随笔為你收集整理的java-静态-单例-继承的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: npm 报错: npm ERR! Ple
- 下一篇: ssh终端远程登陆主机命令--笔记