日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

java-静态-单例-继承

發布時間:2024/8/26 编程问答 42 豆豆
生活随笔 收集整理的這篇文章主要介紹了 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 :參數。該名稱就是一個變量名。

class MainDemo {public static void main(String[] args) {System.out.println(args);//[Ljava.lang.String;@1afae45//根據這個結果,說明jvm傳遞了一個字符串類型的數組實體。System.out.println(args.length);//0,得出結論 jvm傳遞的是 new String[0];for (int i = 0; i<args.length ;i++ ){System.out.println(args[i]);}}void show(){System.out.println("show run");} }

1.5靜態變量

什么時候定義靜態變量呢?
當該成員變量的值,每一個對象都一致時,就對該成員變量進行靜態修飾。

靜態變量和成員變量的區別:
1,所屬范圍不同。
靜態變量所屬于,成員變量所屬對象
靜態變量也稱為:類變量;成員變量也稱為實例變量

2,調用不同。
靜態變量可以被對象和類調用(一般都用類名調用)
成員變量只能被對象調用。

3,加載時期不同。
靜態變量隨著的加載而加載。
成員變量隨著對象的加載而加載。

4,內存存儲區域不同。
靜態變量存儲在方法區中。
成員變量存儲在堆內存中。

class Circle {private double radius;//圓的半徑。private static double pi = 3.14;//每一個圓對象中都存儲一份,有點浪費內存空間。實現對象的共享。加入靜態關鍵字修飾。Circle(double radius){this.radius = radius;}//獲取圓的面積。double getArea(){return radius*radius*pi;}static void show(){System.out.println("circle show run.."+pi);} } class CircleDemo {public static void main(String[] args) {Circle c = new Circle(3);} }

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 segmentheap segmentcode segmentdata segment


其中我們程序中用關鍵字new出來的東西都是存放在heap segment

程序中的局部變量存放在stack segment,這些局部變量是在具體方法執行結束之后,系統自動釋放內存資源(而heap segment中的資源需要java垃圾回收機制來處理)。

程序中的方法,是內存中的code segment中的,而且是多個對象 共享一個代碼空間區域。

static靜態變量,需要放在內存中的data segment中。

?1.7 靜態代碼塊和局部代碼塊

1?靜態代碼塊

需求:類一加載,需要做一些動作。不一定需要對象。
學習目標:必須了解加載的順序。
靜態代碼塊:
特點:隨著類的加載而執行,僅執行一次
作用:給類進行初始化。

class Demo {static int x = 9;//靜態變量有兩次初始化。 一次默認初始化一次顯示初始化。static //靜態代碼塊。在靜態變量顯示初始化以后在執行。{System.out.println("類加載就執行的部..."+x);}static void show(){System.out.println("show run");} } class StaticCodeDemo {public static void main(String[] args) {Demo.show();Demo.show();} }

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 Single { //2,創建一個本類對象。 private static /*final*/ Single s = new Single();//1,私有化構造函數。 private Single(){}//3,定義一個方法返回這個對象。 public static Single getInstance() { return s; } }  

//懶漢式
//單例的延遲加載方式。面試最多的是懶漢式。

class Single2 { private static Single2 s2 = null;private Single2(){}public static Single2 getInstance() { if(s2==null) s2 = new Single2(); return s2; } }

注意:上面的兩種方式的區別在于因為是靜態的,一個是在類加載就生成對象,另一個是在調用方法時才產和對象

//練習:將兩種方式的內存圖畫出來。

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"); } } *//*

了提高復用,只建立一份代碼。
一個類只要和另一個類產生關系就可以了
關系:繼承。
發現了獲取到所需內容的同時也獲取到不該具備的內容。
為什么?
發現原來這個兩個類之間根本就不存在繼承關系。

只要通過關鍵字 extends(繼承) 就哦了。*/class Person { String name; int age;}class Student extends Person//學生繼承了Person 學生就是子類 Person就是父類(基類,超類) { void study() { System.out.println("good good study"); } } class Worker extends Person { void work() { System.out.println("hard work"); } } /*

怎么解決呢?
找到學生和工人的共性類型。將需要提供復用的代碼進行抽取。
定義到一個共性類型的類中。
Person name age。

怎么在代碼體現中讓學生和Person產生關系呢?

面向對象 另一個特征:繼承。
好處:提高了代碼的復用性。讓類與類產生了關系,給另一個特征 多態 提供了前提。

什么時候定義繼承?
必須保證類與類之間有所屬(is a)關系。 xxx是zzz中的一種。
蘋果是水果中一種。狗是犬科中一種。


在Java中繼承的體現:
Java允許單繼承。不直接支持多繼承,將多繼承進行其他方式的體現。
單繼承:一個子類只能有一個父類。
多繼承:一個子類可以有多個父類。


看上起,多繼承很厲害!為什么。

class Fu1 { void show1() {} } class Fu2 { void show2() {} } //多繼承。 class Zi extends Fu1,Fu2 {}Zi z = new Zi(); z.show1(); z.show2(); //問題隨之而來 萬一多個父類具備了相同的功能呢? class Fu1 { void show() { sop("fu1 show run"); } } class Fu2 { void show() { sop("fu2 show run"); } } //多繼承。 class Zi extends Fu1,Fu2 {}Zi z = new Zi();

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-静态-单例-继承的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。