java编程思想 初始化_《java编程思想》_第五章_初始化与清理
初始化和清理是涉及安全的兩個(gè)問(wèn)題,java中采用了構(gòu)造器,并額外提供了“垃圾回收器”,對(duì)于不再使用的內(nèi)存資源,垃圾回收器能自動(dòng)將其釋放。
一、用構(gòu)造器確保初始化
java中,通過(guò)提供構(gòu)造器,類的設(shè)計(jì)者可以確保每個(gè)對(duì)象都會(huì)得到初始化。創(chuàng)建對(duì)象時(shí),如果其類具有構(gòu)造器,java就會(huì)在用戶有能力操作對(duì)象之前自動(dòng)調(diào)用相應(yīng)的構(gòu)造器,從而保證了初始化的進(jìn)行??紤]到在初始化期間要自動(dòng)調(diào)用構(gòu)造器,所以構(gòu)造器與類的名稱必須相同。public class IfElse {
public static void main(String[] args){
new Test();//在創(chuàng)建對(duì)象時(shí),會(huì)為對(duì)象分配存儲(chǔ)空間,并調(diào)用相應(yīng)的構(gòu)造器。
}
}
class Test{
Test(){
System.out.println("this is test");
}
}
運(yùn)行結(jié)果:this is test
不接受任何參數(shù)的構(gòu)造器叫做默認(rèn)構(gòu)造器(無(wú)參構(gòu)造器),構(gòu)造器也能帶有形式參數(shù),以便指定如何創(chuàng)建對(duì)象。public class IfElse {
public static void main(String[] args){
new Test(5);
}
}
class Test{
Test(int i){
System.out.println("this is test"+i);
}
}
運(yùn)行結(jié)果:this is test5
從概念上講,“初始化”與“創(chuàng)建”是彼此獨(dú)立的,然而在java中,“初始化”與“創(chuàng)建”捆綁在一起,兩者不能分離。
二、方法重載
1.區(qū)分重載方法
重載的方法具有相同的名字,但是每個(gè)重載的方法都必須有一個(gè)獨(dú)一無(wú)二的參數(shù)列表,甚至參數(shù)順序的不同也足以區(qū)分兩個(gè)方法,不過(guò)一般情況下別這么做,這會(huì)使代碼難以維護(hù)。
2.涉及基本類型的重載
基本類型能從一個(gè)“較小”的類型自動(dòng)提升為一個(gè)“較大”的類型,此過(guò)程一旦涉及到重載,可能會(huì)造成一些混淆。如果傳入的數(shù)據(jù)類型(實(shí)際參數(shù)類型),小于方法中聲明的形式參數(shù)類型,實(shí)際數(shù)據(jù)類型就會(huì)被提升。char型略有不同,如果無(wú)法找到剛好接受char參數(shù)的方法,就會(huì)把char直接提升至int。如果傳入的實(shí)際參數(shù)類型大于方法中聲明的參數(shù)類型,就要通過(guò)類型轉(zhuǎn)化做窄化轉(zhuǎn)換,否則編譯器會(huì)報(bào)錯(cuò)。
三、默認(rèn)構(gòu)造器
如果寫(xiě)的類中沒(méi)有構(gòu)造器,則編譯器會(huì)自動(dòng)幫你創(chuàng)建一個(gè)默認(rèn)的構(gòu)造器。但是如果已經(jīng)定義了一個(gè)構(gòu)造器(無(wú)論是否有參數(shù)),編譯器就不會(huì)幫你自動(dòng)創(chuàng)建默認(rèn)構(gòu)造器。
四、this關(guān)鍵字
1.在構(gòu)造器中調(diào)用構(gòu)造器
可能為一個(gè)類寫(xiě)了多個(gè)構(gòu)造器,有時(shí)可能會(huì)想在一個(gè)構(gòu)造器中調(diào)用另一個(gè)構(gòu)造器,以免重復(fù)代碼,可以用this關(guān)鍵字做到。通常寫(xiě)this關(guān)鍵字的時(shí)候,都是指“這個(gè)對(duì)象”或者“當(dāng)前對(duì)象”,而且它本身表示對(duì)當(dāng)前對(duì)象的引用。
public class Flower {
int petalCount = 0;
String s = "initial value";
Flower(int petals){
petalCount = petals;
System.out.println("int arg only,petalCount = "+petalCount);
}
Flower(String ss){
System.out.println("String arg only,s = "+s);
s = ss;
}
Flower(String s,int petals) {
this(petals);
//this(s);此處編譯器會(huì)報(bào)錯(cuò)
this.s = s;
System.out.println("String & int arg");
}
Flower() {
this("hi",47);
System.out.println("no args");
}
public static void main(String args[]){
Flower x = new Flower();
}
}
運(yùn)行結(jié)果:int arg only,petalCount = 47
String & int arg
no args
在有兩個(gè)參數(shù)的構(gòu)造方法中,試圖調(diào)用兩次構(gòu)造方法,但是編譯器報(bào)錯(cuò)。這表明,盡管可以用this調(diào)用一個(gè)構(gòu)造器,但卻不能調(diào)用兩個(gè),此外,必須將構(gòu)造器置于最初始處,否則編譯器會(huì)報(bào)錯(cuò)。
五、清理:終結(jié)處理和垃圾回收
java有垃圾回收器負(fù)責(zé)回收無(wú)用對(duì)象占據(jù)的內(nèi)存資源,但也有特殊情況:假定你的對(duì)象(并非使用new關(guān)鍵字)獲得了一塊“特殊”的內(nèi)存區(qū)域,由于垃圾回收器只知道釋放那些經(jīng)由new分配的內(nèi)存,所以它不知道該如何釋放該對(duì)象的這塊“特殊”內(nèi)存。為了應(yīng)對(duì)這種情況,java允許在類中定義一個(gè)名為finalize()的方法。它的工作原理“假定”是這樣的:一旦垃圾回收器準(zhǔn)備好釋放對(duì)象占用的存儲(chǔ)空間,將首先調(diào)用其finalize()方法,并且在下一次垃圾回收動(dòng)作發(fā)生時(shí),才會(huì)真正回收對(duì)象占用的內(nèi)存。要記住以下三點(diǎn):
(1)對(duì)象可能不被垃圾回收
(2)垃圾回收不等于“析構(gòu)”
(3)垃圾回收只與內(nèi)存有關(guān)
1.垃圾回收器如何工作
在java虛擬機(jī)中,堆的實(shí)現(xiàn)像是一個(gè)傳送帶,每分配一個(gè)新對(duì)象,它就往前移動(dòng)一格。這意味著對(duì)象存儲(chǔ)空間分配的速度非常快,java的“堆指針"只是簡(jiǎn)單地移動(dòng)到尚未分配的區(qū)域。但實(shí)際情況未必像傳送帶那樣,因此,高效率的垃圾回收依賴于垃圾回收器的介入。當(dāng)它工作時(shí),將一面回收空間,一面使堆中的對(duì)象緊湊排列,這樣,”堆指針“就可以很容易地移動(dòng)到更靠近傳送帶的開(kāi)始處。通過(guò)垃圾回收器對(duì)對(duì)象的重新排列,實(shí)現(xiàn)了一種高速的,有無(wú)限空間可以分配的堆模型。
垃圾回收機(jī)制了解:
(1)引用記數(shù):簡(jiǎn)單,但速度很慢。每個(gè)對(duì)象都含有一個(gè)引用計(jì)數(shù)器,當(dāng)有引用連接至對(duì)象時(shí),引用記數(shù)加1,當(dāng)引用離開(kāi)作用域或被置于null時(shí),引用記數(shù)減1。這個(gè)方法有個(gè)缺陷,如果對(duì)象之間循環(huán)引用,可能會(huì)出現(xiàn)”對(duì)象應(yīng)該被回收,但引用記數(shù)卻不為0“的情況。對(duì)于垃圾回收器而言,定位這樣的交互自引用的對(duì)象組所需工作量極大。引用記數(shù)常用來(lái)說(shuō)明垃圾收集的工作方式,但似乎從未被應(yīng)用于任何一種虛擬機(jī)。
(2)自適應(yīng):java虛擬機(jī)采用自適應(yīng)的垃圾回收技術(shù),停止-復(fù)制:先暫停程序,將所有存活的對(duì)象復(fù)制到另一個(gè)堆中,沒(méi)有被復(fù)制的即為垃圾;標(biāo)記-清掃:遍歷所有引用,進(jìn)而找出所有存活的對(duì)象,當(dāng)沒(méi)有引用時(shí),變給對(duì)象標(biāo)記,這個(gè)過(guò)程中不會(huì)有任何清理操作。在java虛擬機(jī)運(yùn)行過(guò)程中,根據(jù)堆空間的對(duì)象情況,在以上兩種狀態(tài)切換,以達(dá)到垃圾回收。
六、成員初始化
java盡力保證,所有的變量在使用前都能得到恰當(dāng)?shù)某跏蓟?#xff0c;對(duì)于方法的局部變量,java以編譯時(shí)錯(cuò)誤的形式來(lái)貫徹這種保證。void f(){
int i;
i++;
}
以上代碼編譯期會(huì)報(bào)錯(cuò)變量沒(méi)有初始化。但是對(duì)于類的數(shù)據(jù)成員,情況有所不同,類的每個(gè)基本數(shù)據(jù)成員保證都會(huì)有一個(gè)初始值。即使代碼沒(méi)有給出,編譯器也會(huì)自動(dòng)賦初值。
七、構(gòu)造器初始化
1.初始化順序
在類的內(nèi)部,變量定義的先后順序決定了初始化的順序。即使變量定義散布于方法定義之間,它們?nèi)匀粫?huì)在任何方法(包括構(gòu)造器)被調(diào)用之前得到初始化。class Window{
Window(int marker) {
System.out.println("window("+marker+")");
}
}
class House{
Window w1 = new Window(1);
House(){
System.out.println("House()");
w3 = new Window(33);
}
Window w2 = new Window(2);
void f(){
System.out.println("f()");
}
Window w3 = new Window(3);
}
public class OrderOfInitialization {
public static void main(String[] args){
House h = new House();
h.f();
}
}
運(yùn)行結(jié)果:window(1)
window(2)
window(3)
House()
window(33)
f()
在House類中,故意把幾個(gè)window對(duì)象散布在各處,以證明它們?nèi)紩?huì)在調(diào)用構(gòu)造器或其他方法之前得到初始化。
2.靜態(tài)數(shù)據(jù)的初始化
無(wú)論創(chuàng)建多少個(gè)對(duì)象,靜態(tài)數(shù)據(jù)都只占一份存儲(chǔ)區(qū)域。static關(guān)鍵字不能應(yīng)用于局部變量,因此它只能作用于域。 初始化的順序是先靜態(tài)對(duì)象(如果之前并未被初始化),而后是非靜態(tài)對(duì)象。
對(duì)象的創(chuàng)建過(guò)程,假設(shè)有個(gè)名為Dog的類:
(1)當(dāng)首次創(chuàng)建類型為Dog的對(duì)象時(shí),java解釋器查找類路徑,定位Dog.class文件
(2)載入Dog.class,有關(guān)靜態(tài)初始化的所有動(dòng)作都會(huì)被執(zhí)行。因此,靜態(tài)初始化只在Class對(duì)象首次加載的時(shí)候進(jìn)行一次。
(3)當(dāng)用new Dog()創(chuàng)建對(duì)象時(shí),首先將在堆上為Dog對(duì)象分配足夠的存儲(chǔ)空間。
(4)這塊存儲(chǔ)空間會(huì)被清零,這就自動(dòng)地將Dog對(duì)象中的所有基本類型數(shù)據(jù)都設(shè)置成了默認(rèn)值,而引用則被置為null。
(5)執(zhí)行所有出現(xiàn)于字段定義處的初始化動(dòng)作。
(6)執(zhí)行構(gòu)造器。
八、數(shù)組初始化
數(shù)組只是相同類型的,用一個(gè)標(biāo)識(shí)符名稱封裝到一起的一個(gè)對(duì)象序列或者基本類型數(shù)據(jù)序列。
可變參數(shù):String[] args的寫(xiě)法可以寫(xiě)為String...args。有了可變參數(shù),就不用顯示地編寫(xiě)數(shù)組語(yǔ)法了,當(dāng)指定參數(shù)時(shí),編譯器會(huì)去填充數(shù)組,但是如果傳遞的本來(lái)就是數(shù)組,編譯器就不會(huì)再執(zhí)行任何轉(zhuǎn)換。因此,如果你有一組事物,可以把它們當(dāng)作列表傳遞,而如果你已經(jīng)有了一個(gè)數(shù)組,該方法可以把它們當(dāng)作可變參數(shù)列表來(lái)接受。將0個(gè)參數(shù)傳遞給可變參數(shù)列表依舊是可行的。
九、枚舉類型
java SE5中添加了一個(gè)看似很小的特性,即enum關(guān)鍵字,它使得我們?cè)谛枰航M并使用枚舉類型集時(shí),可以很方便地處理。enum Simple {
NOT,MILD,MEDIUM,HOT
}
public class SimpleEnumUse{
public static void main(String[] args){
Simple howHot = Simple.MEDIUM;
System.out.println(howHot);
}
}
運(yùn)行結(jié)果:MEDIUM
enum有一個(gè)特別實(shí)用的特性,即它可以在switch語(yǔ)句內(nèi)使用。
總結(jié)
以上是生活随笔為你收集整理的java编程思想 初始化_《java编程思想》_第五章_初始化与清理的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。
- 上一篇: android模拟win98中文版,Wi
- 下一篇: VB 中文乱码问题,以下方案可以试试