1.protected使用
protected處理的是繼承的概念,如果創(chuàng)建了一個(gè)新包,并從另一個(gè)包中繼承類,可以訪問的成員有public和protected。protected 也提供包訪問權(quán)限。
package com.zhangyue.learn;
import static net.mindview.util.Print.*;
public class Test1 {
protected int n;
public int m;
public static void main(String[] args) {
print("aaaaa");
}
}
package com.zhangyue.learn1;
import com.zhangyue.learn.Test1;
public class LearnProtect extends Test1{
public static void main(String[] args) {
LearnProtect l = new LearnProtect();
l.m = 1;
l.n = 2;
}
}
class Other{
void test(){
Test1 t = new Test1();
t.m = 2;
// t.n = 1;
}
}
2.訪問權(quán)限控制將權(quán)限的邊界化在了數(shù)據(jù)類型的內(nèi)部的原因
- 第一,設(shè)定客戶端程序員可以使用和不可以使用的界限,可以在結(jié)構(gòu)中建立自己的內(nèi)部機(jī)制,不必?fù)?dān)心客戶端程序員把它當(dāng)做是自己可以使用的接口的一部分。
- 第二,就是接口和具體實(shí)現(xiàn)進(jìn)行分離。如果一個(gè)結(jié)構(gòu)是用于程序中,而客戶端程序員除了可以向接口發(fā)送信息外什么也不可以做的話,就可以隨意更改所有不是public的東西而不會(huì)破壞客戶端代碼。
3. 復(fù)用類
即可以通過創(chuàng)建新類來(lái)復(fù)用代碼,而不必重頭開始編寫,可以使用別人已經(jīng)開發(fā)并且調(diào)試好的類,有兩種方法,組合語(yǔ)法和繼承語(yǔ)法。
- 組合語(yǔ)法:新有的類是由現(xiàn)有的類的對(duì)象組合而成的,復(fù)用了現(xiàn)有代碼的功能,而不是它的形式。
- 繼承語(yǔ)法:按照現(xiàn)有類的類型來(lái)創(chuàng)建新類。無(wú)需改變現(xiàn)有類的形式,采用現(xiàn)有類的形式并在其中添加新代碼。
5. 繼承
當(dāng)創(chuàng)建一個(gè)類時(shí),總是在繼承,除了明確指出繼承哪個(gè)類,都隱式地繼承Object類。
package com.zhangyue.learn;
class Cleanser{
private String s = "Cleanser";
public void append(String a){ s += a;}
public void dilute(){ append(" dilute()");}
public void apply(){ append(" apply()");}
public void scrub(){ append(" scrub()");}
public String toString(){return s;}
//可以為每個(gè)類創(chuàng)建一個(gè)main()方法,方便測(cè)試
public static void main(String[] args){
Cleanser c = new Cleanser();
c.dilute();c.apply();c.scrub();
System.out.println(c);
}
}
public class Detergent extends Cleanser{
public void scrub(){
append("Deprecated.scrub()");
super.scrub();//super 表示超類的意思,當(dāng)前類就是從超類繼承過來(lái)的
}
public void foam(){
append("foam()");
}
public static void main(String[] args) {
Detergent d = new Detergent();
d.apply();d.dilute();d.scrub();d.foam();
System.out.println(d);
System.out.println("Testing base class");
Cleanser.main(args);
}
}
6.基類初始化
- 構(gòu)造器不帶參數(shù)
package com.zhangyue.learn;
class Art{
public Art() {
System.out.println("Art()");
}
}
class Drawing extends Art{
public Drawing() {
System.out.println("Drawing()");
}
}
public class Cartoon extends Drawing{
public Cartoon() {
System.out.println("Cartoon()");
}
public static void main(String[] args) {
Cartoon c = new Cartoon();
}
}
/*output
Art()
Drawing()
Cartoon()
*/
構(gòu)造過程從基類向外擴(kuò)散,基類在導(dǎo)出類可以訪問它之前就完成了初始化。即使不為Cartoon創(chuàng)建構(gòu)造器,編譯器也會(huì)合成默認(rèn)的構(gòu)造器調(diào)用基類構(gòu)造器。
- 構(gòu)造器帶參數(shù)
package com.zhangyue.learn;
class Game{
public Game(int i) {
System.out.println("Game()");
}
}
class BoardGame extends Game{
public BoardGame(int i) {
super(i); //調(diào)用基類構(gòu)造器
System.out.println("BoardGame()");
}
}
public class Chess extends BoardGame{
public Chess() {
super(11);
System.out.println("Chess()");
}
public static void main(String[] args) {
Chess c = new Chess();
}
}
如果不在BoardGame里調(diào)用基類構(gòu)造器,編譯器會(huì)抱怨無(wú)法找到符合Game()形式的構(gòu)造器,而且,調(diào)用基類構(gòu)造器必須是在導(dǎo)出類構(gòu)造器中要做的第一件事。
7. 向上轉(zhuǎn)型
“為新的類提供方法”并不是繼承中最重要的一面,其最重要的是用來(lái)表現(xiàn)新類和基類的關(guān)系,即“新類是現(xiàn)有類的一種類型”。
package com.zhangyue.learn;
class Instruction{
public void paly(){}
public static void tune(Instruction i){
i.paly();
}
}
public class Wing extends Instruction{
public static void main(String[] args) {
Wing w = new Wing();
Instruction.tune(w);
}
}
將Wing引用轉(zhuǎn)換為Instruction引用的動(dòng)作就是向上轉(zhuǎn)型。是安全的。
8. 選擇組合與繼承
到底使用組合還是繼承,一個(gè)最清晰的判斷方法就是問問自己是否需要從新類向基類進(jìn)行向上轉(zhuǎn)型。
9.final關(guān)鍵字
說明
對(duì)于基本數(shù)據(jù)類型,final使數(shù)據(jù)恒定不變;對(duì)于對(duì)象引用,final是引用恒定不變。一旦引用指向某個(gè)對(duì)象,就不能再指向另一個(gè)對(duì)象,但對(duì)象本身是可以修改的,java沒提供使對(duì)象恒定不變的途徑。
典型的常量定義方式:
public static final VALUE_ONE;
public指可用于包之外,static強(qiáng)調(diào)只有一份 只在第一次創(chuàng)建對(duì)象時(shí)初始化一次,final則說明是常量。final方法
將方法鎖定,以防任何繼承類修改它的定義。在繼承中使方法行為保持不變并且不會(huì)被覆蓋。
*final類
將整個(gè)類定義為final時(shí),就表示不打算繼承該類,對(duì)該類的設(shè)計(jì)不需要做任何變動(dòng)。