第7章•封裝封裝封裝封裝–定義類別(Class)–關於方法以物件思考問題•有一個帳戶,帳戶中有存款餘額,您可以對帳戶進行存款與提款的動作,並可以查詢以取得存款餘額。–識別問題中的物件與屬性–識別物件上的方法以物件思考問題使用class定義類別•在Java中使用class關鍵字來定義類別publicclassAccount{privateStringaccountNumber;privatedoublebalance;publicAccount(){this(empty,0.0);}publicAccount(StringaccountNumber,doublebalance){this.accountNumber=accountNumber;this.balance=balance;}…定義類別定義建構方法使用class定義類別•在Java中使用class關鍵字來定義類別…publicStringgetAccountNumber(){returnaccountNumber;}publicdoublegetBalance(){returnbalance;}publicvoiddeposit(doublemoney){balance+=money;}publicdoublewithdraw(doublemoney){balance-=money;returnmoney;}}定義成員使用class定義類別•可根據類別來建構物件•要透過公開成員來操作物件或取得物件資訊的話,可以在物件名稱後加上「.」運算子來進行Accountaccount1=newAccount();Accountaccount2=newAccount(123-4567,100.0);account1.getBalance();account1.deposit(1000.0);使用class定義類別Accountaccount=newAccount();System.out.println(帳戶:+account.getAccountNumber());System.out.println(餘額:+account.getBalance());account=newAccount(123-4567,100.0);account.deposit(1000.0);System.out.println(帳戶:+account.getAccountNumber());System.out.println(餘額:+account.getBalance());類別成員(Classmember)•類別成員可用的存取權限修飾詞有“public”、“protected”、“private”三個•在宣告成員時不使用存取修飾詞,則預設以「套件」(package)為存取範圍類別成員(Classmember)•資料成員被宣告為“private”,表示它是「私用成員」(Privatemember),私用成員只能在類別中被使用•方法被宣告為public,表示這些方法可以藉由物件的參考名稱加上.直接呼叫存取修飾傳回值型態方法名稱(參數列){//實作return傳回值;}類別成員(Classmember)•方法區塊中可以宣告變數(Variable),參數在方法區塊執行結束後就會自動清除•方法中的相同變數名稱會暫時覆蓋資料成員的作用範圍•可以使用this關鍵字來特別指定類別成員(Classmember)classMethodDemo{privateintdata=10;publicvoidscopeDemo(){//void表示沒有傳回值intdata=100;}publicintgetData(){returndata;}publicvoidsetData(intdata){//void表示沒有傳回值data=data;//這樣寫是沒用的//寫下面這個才有用//this.data=data;}}類別成員(Classmember)•資訊的最小化–如果資料成員能不公開就不公開•透過公開方法存取私用成員的好處–如果存取私用成員的流程有所更動,只要在公開方法中修改就可以了publicdoublewithdraw(doublemoney){if(balance–money0){return0;}else{balance-=money;returnmoney;}}建構方法(Constructor)•建構方法是與類別名稱相同的公開方法成員,且沒有傳回值publicclassSafeArray{//..publicSafeArray(){//建構方法//....}publicSafeArray(參數列){//建構方法//....}}建構方法(Constructor)publicclassSafeArray{privateint[]arr;publicSafeArray(){this(10);//預設10個元素}publicSafeArray(intlength){arr=newint[length];}…}關於this方法成員在記憶體中會只有一份關於this•使用參考名稱來呼叫物件的方法成員時,程式會將物件的參考告知方法成員•在方法中所撰寫的每一個資料成員其實會隱含一個this參考名稱•this名稱參考至呼叫方法的物件publicdoublegetBalance(){returnthis.balance;}關於this•在方法中使用資料成員時,都會隱含的使用this名稱publicAccount(StringaccountNumber,doublebalance){this.accountNumber=accountNumber;this.balance=balance;}publicAccount(Stringnumber,doublemoney){accountNumber=number;//實際等於this.accountNumber=number;this.balance=money;//實際等於this.balance=money;}關於this•this還有一種可以帶引數的用法,主要是用於呼叫建構方法publicclassBall{privateStringname;publicBall(){this(“Noname”);//會使用Ball(“Noname”)來建構}publicBall(Stringname){this.name=name;....}}關於static•被宣告為“static”的資料成員,又稱「靜態資料成員」•靜態成員是屬於類別所擁有,而不是個別的物件•可以將靜態成員視為每個物件實例所共享的資料成員publicclassBall{publicstaticdoublePI=3.14159;//宣告static資料...}關於static•屬於類別所擁有,可以在不使用名稱參考下,直接使用類別名稱加上‘.’運算子來存取•同樣遵守“public”、“protected”與“private”的存取限制•設定為“public”成員的話就可以如下存取•下面的方式是不被鼓勵的System.out.println(PI=+Ball.PI);Ballball=newBall();System.out.println(PI=+ball.PI);關於static•可以宣告方法成員為static方法,又稱「靜態方法」publicclassBall{...publicstaticdoubletoRadian(doubleangle){return3.14159/180*angle;}}System.out.println(角度90等於徑度+Ball.toRadian(90));關於static•靜態方法中不會有this參考名稱•靜態方法中不允許使用非靜態成員•在靜態方法中不能呼叫非靜態方法non-staticvariabletestcannotbereferencedfromastaticcontextnon-staticmethodshowHello()cannotbereferencedfromastaticcontext關於static•可以使用“static”定義一個靜態區塊,並在當中撰寫類別載入時的初始化動作•在類別被載入時,預設會先執行靜態區塊中的程式碼,且只會執行一次publicclassBall{static{//一些初始化程式碼}....}重載(Overload)方法•為類似功能的方法提供統一名稱,可根據參數列的不同而自動呼叫對應的方法•String的valueOf()方法就提供了多個版本staticStringvalueOf(booleanb)staticStringvalueOf(charc)staticStringvalueOf(char[]data)staticStringvalueOf(char[]data,intoffset,intcount)staticStringvalueOf(doubled)staticStringvalueOf(floatf)staticStringvalueOf(inti)staticStringvalueOf(longl)staticStringvalueOf(Objectobj)重載(Overload)方法•參數個數也可以用來設計方法重載publicclassSomeClass{//以下重載了someMethod()方法publicvoidsomeMethod(){//...}publicvoidsomeMethod(inti){//...}publicvoidsomeMethod(floatf){//...}publicvoidsomeMethod(inti,floatf){//...}}重載(Overload)方法•返回值型態不可用作為方法重載的區別根據,以下是不正確的publicclassSomeClass{publicintsomeMethod(inti){//...return0;}publicdoublesomeMethod(inti){//...return0.0;}}重載(Overload)方法•注意到autoboxing、unboxing的問題publicstaticvoidmain(String[]args){someMethod(1);}publicstaticvoidsomeMethod(inti){System.out.println(int版本被呼叫);}publicstaticvoidsomeMethod(Integerinteger){System.out.println(Integer版本被呼叫);}重載(Overload)方法•注意到autoboxing、unboxing的問題–找尋在還沒有裝箱動作前可以符合引數個數與型態的方法–嘗試裝箱動作後可符合引數個數與型態的方法–嘗試設有「不定長度引數」並可以符合的方法–編譯器找不到合適的方法,回報編譯錯誤不定長度引數•J2SE5.0之後開始支援「不定長度引數」(Variable-lengthArgument)•實際上nums是一個陣列publicstaticintsum(int...nums){//使用...宣告參數intsum=0;for(intnum:nums){sum+=num;}returnsum;}不定長度引數•宣告的參數必須設定在參數列的最後一個,下面的方式是合法的•下面的方式是不合法的publicvoidsomeMethod(intarg1,intarg2,int...varargs){//....}publicvoidsomeMethod(int...varargs,intarg1,intarg2){//....}不定長度引數•沒辦法使用兩個以上的不定長度引數,下面的方式是不合法的•如果使用物件的不定長度引數,宣告的方法相同publicvoidsomeMethod(int...varargs1,int...varargs2){//....}p