Java筆記:類和物件
Java類和物件
類是在程式設計中經過編寫的,擁有成員變數和一些方法的一種資料型別,可以由自己通過聯絡現實中的事物進行編寫,關鍵字是class,一個Java原始檔只能含有一個public類,且該類名稱與檔名相同。類是對現實中具體事物的一種表示,並且需藉由類建立物件,稱為類的例項化,一個物件就是一個類的例項化,由一個類可以建立多個物件,這些同屬一個類的物件便擁有定義類時類中定義含有的成員變數和方法。可粗略地把Java中類看做含有可以操作其成員變數的結構體。
類的儲存
每個類可以包含成員變數和方法,成員變數儲存由類定義的物件的一些引數,方法表示物件所能完成的一些行為。類屬於引用資料型別,同其他引用資料型別一樣,在棧中存放其引用地址,指向儲存在堆中的實際值,包括非靜態成員變數。以後文中的testClass為例,想要建立一個該類的物件,需要執行:testClass theObject = new testClass(); 語句,前半段是將theObject變為引用變數,後半段開闢空間,並根據引數呼叫相應的構造方法。單獨的testClass只能宣告引用而不能開闢空間並定義物件。 由類定義物件時,在堆中為其開闢空間,包括物件頭、Class物件指標、例項成員變數和記憶體填充。物件頭佔8個位元組、指標佔4個位元組、例項成員變數中,基本資料型別按照其本身所佔位元組數進行計算,引用資料型別佔4個位元組,最後一個物件所佔的所有位元組數需為8的倍數,用記憶體填充補齊。物件頭指向Class物件,再借由Class物件找到方法區中的方法表,方法表中存放著每個類的方法和靜態成員變數,方法表和靜態成員變數在方法區中只有一個儲存的位置,也就對於每個類只有一份。
物件的初始化
物件的初始化,即將由類定義的物件的例項成員變數值初始化、賦初值。方式有以下幾種: 1、 呼叫類中定義的構造方法:構造方法的名稱需與類的名稱相同,構造方法允許方法過載,對構造方法來說,即為方法的引數列表不同,因而無參的構造方法只能有一個,無參的構造方法可以通過this關鍵字呼叫有參的構造方法,this(),括號中根據填入引數不同,呼叫相應的有參構造方法。除在構造方法之外,不能在其他方法中通過this呼叫構造方法。在構造方法中,this只能使用一次且必須在構造方法的最前端,或許可以如下理解:若由this引用的構造方法放在了後面,則該構造方法中位於this之前的初始化語句就沒有用了。 2、 通過普通方法對成員變數賦值:即便是將成員變數設定為訪問許可權需求最高的private,該成員變數仍有類內訪問許可權,類中方法可以對成員變數進行引用和修改。 3、 呼叫靜態塊對靜態成員變數賦值:靜態塊和靜態方法只能修改靜態成員變數,在其他方法中也可修改靜態成員變數。 4、 通過例項塊對成員變數賦值:可以修改靜態成員變數和非靜態成員變數。
一個類的初始化順序
一個類可能會含有靜態成員變數、靜態塊、例項成員變數、例項塊、構造方法和普通方法。 在類的例項化定義物件時他們的初始化也有順序,普通方法不經引用無法實現,用下面的程式碼觀察初始化順序。
public class testClass {
int i;
static test2 t = new test2();
test0 t0 = new test0();
static{
System.out.println("靜態塊");
}
{
System.out.println("例項塊");
}
testClass(){
System.out .println("構造方法");
}
}
class test2{
test2(){
System.out.println("靜態成員變數");
}
}
class test0{
test0(){
System.out.println("普通成員變數");
}
}
在其他位置中通過呼叫testClass的無參構造方法,通過列印的順序可以得出各個部分的初始化順序:靜態成員變數、靜態塊、普通成員變數、例項塊、構造方法。這也解釋了為什麼不能在靜態塊中對普通成員變數進行操作,在初始化靜態塊時,普通成員變數還沒有被初始化,因而不能呼叫。
幾個關鍵字
this關鍵字
this代表由類定義的一個物件自身,因此能用this.來呼叫自身的所有成員變數和方法。
static關鍵字
Static,靜態,用static可以修飾變數和方法使其成為靜態變數和靜態方法,靜態方法歸類所有而不歸物件所有,每個類只有一份。
final關鍵字
final關鍵字的作用有:1、修飾變數;2、修飾方法;3、修飾類
1、修飾變數:Final修飾的變數將變為不能更改值的常量;
class Cat{
final int age;
public Cat(int age){
this.age = age;
}
}
此處將Cat類中的age成員變數定義為final,在構造時賦初值。在其他地方寫入下面的語句:
Cat cat1 = new Cat(5);
System.out.println(cat1.age++);//!
第二句發生錯誤,由final修飾的變數一經賦值後,便不能為其分配新的值。
2、用final修飾方法
用final修飾的方法也被鎖定而不能更改,子類繼承父類時,父類中的final方法可被子類繼承,不能被子類重寫,而在父類中final方法可以被過載,可被過載為final方法或非final方法。此處提到方法的過載:即在同一類中兩個方法使用同一方法名,根據返回值和引數列表區分該呼叫哪個方法。沿用上面的Cat類,getAge方法兩次重寫,在類中不論是否由final修飾都可被重寫。
final void getAge(){
System.out.println(this.age);
}
void getAge(String name){
System.out.println(this.age);
}
final void getAge(int years){
System.out.println("this cat will be " + (this.age+years) + " after " + years + " years" );
}
3、用final修飾類
當用final修飾類時,該類無法被繼承,即沒有子類。
單例模式
即每個類只有一個物件,實現單例。
1、 重點在於將構造方法設為類的私有,不允許在類外定義新物件,而將在類中的物件、返回靜態物件的方法設為歸類所有的static型別,每個類只有一份,從而使歸物件所有的該類成員變數只被引用了一次。後續再執行new操作也只是為第一次生成的物件加一個引用變數。
class singleExample{
private static singleExample theExample = new singleExample();
private int i;
private singleExample(){
i = 0;
}
public static singleExample returnTheExample(){
return theExample;
}
public void setI(int num){
this.i = num;
}
public int getI(){
return this.i;
}
}
放在其他地方的引用該類:
singleExample theExample = singleExample.returnTheExample();
theExample.setI(5);
singleExample theExample2 = singleExample.returnTheExample();
System.out.println(theExample2.getI());
在設定theExample的成員變數i為5後,重新new一個theExample2物件,並列印theExample的i,輸出為5,此時的theExample2只是該類中靜態物件的新引用。
2、 構建單例模式,可以在定義成員變數的時候進行物件的定義,也可在呼叫該方法時進行物件的定義,在呼叫方法時需加以判斷,若引用為空,則new物件,若非空,仍返回原物件theExample,由於theExample為靜態,因此不被改變:
3、 class singleExample2{
private static singleExample2 theExample;
private int i;
private singleExample2(){
i = 0;
}
public static singleExample2 returnTheExample(){
if(theExample == null){
theExample = new singleExample2();
}
return theExample;
}
public void setI(int num){
this.i = num;
}
public int getI(){
return this.i;
}
}
訪問修飾符
訪問修飾符可用來修飾類、成員變數、方法,使其能在不同大小的區域被呼叫
default:寫default或什麼也不寫,擁有包訪問許可權,同一包內可訪問呼叫。 Private:僅在同一類中可被呼叫,但不能修飾外部類。 Public:在任何地方都可呼叫,但需在java檔案開頭加入包名才可引用public類。 Protected:同包中可呼叫,但多用於繼承時修飾父類成員變數或方法,使其可以在子類中使用。不能修飾外部類。
為體現封裝性,一般將類的成員變數設定為private,並通過自定義幾個public方法向內或向外傳值達到呼叫成員變數或更改成員變數值的操作。
方法過載
在同一類中,多個方法可以同名且引數列表不同,稱為方法過載。可以為想進行的操作傳遞不同的引數型別。但多個方法方法名相同、返回值型別不同、引數列表相同是不允許的。例如:
class cat{
public cat(){}
public void eat(){
System.out.println("cat eat");
}
public int eat(int i){
return i;
}
}