天天看點

Java小試牛刀3

[align=center][size=xx-large][b]Java小試牛刀3[/b][/size][/align]

[size=large]1、為什麼在面向對象程式中,調用類的成員方法可以操作該類的屬性?[/size]

答:1)、在一個類中無論屬性的通路修飾成什麼(例如最低通路修飾private),隻要是成員方法的局域之外,都能被所有成員方法操作,當然如果屬性是定義在方法局部之内,其它方法是有能通路到的。

2)、正是因為上一個特點,是以我們可以通過調用類的成員方法來操作該類的,其實這是通過間接的方式來操作其它類中的方法,而非直接操作其它類的屬性;但這裡有一個前提是,類中的方法是可見的,如果不可見談何操作類的屬性呢!

[img]http://dl.iteye.com/upload/attachment/0084/3792/3d91f786-c7ab-3a34-b053-7606c00278b9.jpeg[/img]

[size=large]2、Object類中所有方法重寫的意義?[/size]

答:這裡隻是通過一個普通類舉例,與重寫Object類的意義相同。

1)、重寫的前提是有繼承。

2)、重寫可以修改父類已有的方法:

首先,修改方法的目的可以是擴充父類的方法功能;例如:Student類的對象有一個paly()方法,那麼當College繼承Student之後,我們可以重寫父類Student中的paly()這個方法,這樣就相當于擴充了paly()方法的功能。

另外,修改父類方法可以屏蔽父類中的方法;例如:把paly()重寫後,方法體不寫任何内容,這樣paly()方法就沒有任何作用了。

[img]http://dl.iteye.com/upload/attachment/0084/3794/1ea89ab2-5af2-3453-893a-38e23023a4a8.jpeg[/img]

[size=large]3、抽象類中的方法可不可以執行個體化(有聲明、有定義)?[/size]

[img]http://dl.iteye.com/upload/attachment/0084/3796/a909bf3c-18b6-3ceb-a9ed-8d7117918d31.jpeg[/img]

通過執行個體證明抽象類中的普通方法可以聲明和定義,但是抽象方法是不可以實作方法體,隻能聲明;同時抽象類是不能直接建立對象,就如上圖所示,編輯器會提示錯誤!

[size=large]4、驗證main()、靜态代碼塊、初始化代碼塊哪個執行次序?[/size]

[img]http://dl.iteye.com/upload/attachment/0084/3798/ba18ce81-67af-3dee-9b54-3e557785a250.jpeg[/img]

通過執行個體驗證靜态代碼塊及靜态變量比main()先,也發現在靜态代碼塊和靜态變量中不能使用類中其它普通成員變量值,進而也間接的證明,靜态代碼塊和靜态變量比普通變量和main()要先執行。

[size=large]5、實作一個單件模式的類:[/size]

[img]http://dl.iteye.com/upload/attachment/0084/3800/66bf29e1-91e8-38f7-b038-770fe454c722.jpeg[/img]

[size=large]6、通路修飾符[/size]

1.transient 關鍵字

首先是JAVA的序列化,簡單來說就是将某一個類存儲以檔案形式存儲在實體空間,下次再從本地還原的時候,還可以将它轉換回來,這種形式便利了網絡上的一些操作。

序列化隻能儲存對象的非靜态成員交量,不能儲存任何的成員方法和靜态的成員變量,而且串行化儲存的隻是變量的值,對于變量的任何修飾符都不能儲存。

以檔案形式描述某些資訊時,容易涉及到安全問題,因為資料位于Java運作環境之外,不在Java安全機制的控制之中。對于這些需要保密的字段,不應儲存在永久媒體中,或者不應簡單地不加處理地儲存下來 ,為了保證安全性。應該在這些字段前加上transient關鍵字。它的意思是臨時的,即不會随類一起序列化到本地,是以當還原後,這個關鍵字定義的變量也就不再存在。

如果TransTest 類的一個對象被序列化,i的内容不被儲存,但j的将被儲存。

Java代碼

class TransTest {

transient int i; //不需要儲存

int j; //需要儲存

2. volatile關鍵字 不常用

Volatile修飾的成員變量在每次被線程通路時,都強迫從共享記憶體中重讀該成員變量的值。而且,當成員變量發生變化時,強迫線程将變化值回寫到共享記憶體。這樣在任何時刻,兩個不同的線程總是看到某個成員變量的同一個值。

Java語言規範中指出:為了獲得最佳速度,允許線程儲存共享成員變量的私有拷貝,而且隻當線程進入或者離開同步代碼塊時才與共享成員變量的原始值對比。

這樣當多個線程同時與某個對象互動時,就必須要注意到要讓線程及時的得到共享成員變量的變化。

而volatile關鍵字就是提示VM:對于這個成員變量不能儲存它的私有拷貝,而應直接與共享成員變量互動。

使用建議:在兩個或者更多的線程通路的成員變量上使用volatile。當要通路的變量已在synchronized代碼塊中,或者為常量時,不必使用。

由于使用volatile屏蔽掉了VM中必要的代碼優化,是以在效率上比較低,是以一定在必要時才使用此關鍵字。

3、Synchronize 關鍵字

先提出問題,如果開啟多線程同時操作同一執行個體變量,Thread-0線程從主記憶體中取出的值a 為 1,然後a++; Thread-1線程也從主記憶體中取出的值 a 進行 a+=2操作;Thread-0存入2到主記憶體中,Thread-1也存入,這樣就覆寫了Thread-0存入的值.

原因是在JAVA 的記憶體模型中,是每一個程序都有一個主記憶體,每個線程都有自己的記憶體,線程從主記憶體取得資料,計算後再存回到主記憶體中.

解決這個問題就可以使用 synchronize關鍵字.

使用synchronized修飾此方法後,把下面的這幾個步驟當作一個原子操作:取資料,操作資料,存資料。原子操作是不能夠被打斷的,是以就保證了資料的一緻性,這樣在同一時間有線程再執行,雖然在效率上比較有影響,但是能夠保證在同一時間隻有一個線程能夠通路到這一塊記憶體單元。

[size=large]7、為什麼final不能修飾構造方法?[/size]

final使得被修飾的變量"不變",但是由于對象型變量的本質是“引用”,使得“不變”也有了兩種含義:引用本身的不變,和引用指向的對象不變。那麼如果用final來修飾構造方法是沒有意義的。

[img]http://dl.iteye.com/upload/attachment/0084/3802/8d7350eb-9dcc-33a8-abf4-ef3848006ad3.jpeg[/img]

[size=large]8、Visio畫圖[/size]

[img]http://dl.iteye.com/upload/attachment/0084/3804/7ce8c997-cc55-3038-9588-25239dd8f3b4.jpeg[/img]