定義:封裝就是將客戶端不應(yīng)看到的信息包裹起來。使內(nèi)部執(zhí)行對(duì)外部來看不一種不透明的、是一個(gè)黑箱,客戶端不需要內(nèi)部資源就能達(dá)到他的目的。
1.事物的內(nèi)部實(shí)現(xiàn)細(xì)節(jié)隱藏起來
2.對(duì)外提供一致的公共的接口――間接訪問隱藏?cái)?shù)據(jù)
3.可維護(hù)性
二、 繼承 (inherit) JAVA繼承特點(diǎn)
繼承:父類的成員能否繼承到子類?
對(duì)類成員訪問的限制及子類繼承情況: (從嚴(yán) 到寬 )
private 私有,本類內(nèi)部 不能繼承
(default) 本類+同包 同包子類可繼承
protected 本類+同包+子類 可以繼承
public 公開 任何地方都可以訪問 能繼承到子類
覆蓋
1、定義: 覆蓋了一個(gè)方法并且對(duì)其重寫,以求達(dá)到不同的作用。
2、用法:
a、最熟悉的覆蓋就是對(duì)接口方法的實(shí)現(xiàn)
b、在繼承中也可能會(huì)在子類覆蓋父類中的方法
3、產(chǎn)生 “覆蓋”的條件:
1、方法名:相同
2、參數(shù)表:相同(個(gè)數(shù),類型)
3、訪問限制符:相同或者更寬
4、返回值類型:相同 或者 子類返回的類型是父類返回的類型的子類
5、不能拋出比subclass(父類)更多的異常
注意:當(dāng)我們?cè)谧宇愔袆?chuàng)建的靜態(tài)方法,它并不會(huì)覆蓋父類中相同名字的靜態(tài)方法。class Parent
{
public void nonStaticMethod()
{
System.out.println("Parent's Non-Static Method is Called");
}
public static void staticMethod()
{
System.out.println("parent's static method is called");
}
}
class Child extends Parent
{
public void nonStaticMethod()
{
System.out.println("child's non-static method is called");
}
public static void staticMethod()
{
System.out.println("child's static method is called");
}
}
public class Test
{
public static void main(String args[])
{
Parent p1 = new Parent();
Parent p2 = new Child();
Child c = new Child();
System.out.print("Parent.static: "); Parent.staticMethod();
System.out.print("p1.static: "); p1.staticMethod();
System.out.print("p2.static: "); p2.staticMethod();
System.out.print("p1.nonStatic: "); p1.nonStaticMethod();
System.out.print("p2.nonStatic: "); p2.nonStaticMethod();
System.out.print("Child.static: "); Child.staticMethod();
System.out.print("c.static: "); c.staticMethod();
System.out.print("c.nonStatic: "); c.nonStaticMethod();
}
}
程序的運(yùn)行結(jié)果為:
Parent.static: parent's static method is called
p1.static: parent's static method is called
p2.static: parent's static method is called
p1.nonStatic: Parent's Non-Static Method is Called
p2.nonStatic: child's non-static method is called
Child.static: child's static method is called
c.static: child's static method is called
c.nonStatic: child's non-static method is called
值得注意的是p2實(shí)際上是一個(gè)Child的類型的引用,然而在調(diào)用靜態(tài)方法的時(shí)候,它執(zhí)行的卻是父類的靜態(tài)方法,而不是Child的靜態(tài)方法,而調(diào)用 p2的非靜態(tài)方法的時(shí)候執(zhí)行的是Child的非靜態(tài)方法,為什么呢?原因是靜態(tài)方法是在編譯的時(shí)候把靜態(tài)方法和類的引用類型進(jìn)行匹配,而不是在運(yùn)行的時(shí)候和類引用進(jìn)行匹配。因此我們得出結(jié)論:當(dāng)我們?cè)谧宇愔袆?chuàng)建的靜態(tài)方法,它并不會(huì)覆蓋父類中相同名字的靜態(tài)方法。
構(gòu)造
(java編程思想定義為:構(gòu)造器初始化)
對(duì)象的構(gòu)造過程:
首先為對(duì)象分配內(nèi)存空間,包括其所有父類的可見或不可見的變量的空間,并初始化這些變量為默認(rèn)值,如int類型為0,boolean類型為false,對(duì)象類型為null。。。。
然后用下述5個(gè)步驟來初始化這個(gè)新對(duì)象:
1)分配參數(shù)給指定的構(gòu)造方法;
2)如果這個(gè)指定的構(gòu)造方法的第一個(gè)語句是用this指針顯式地調(diào)用本類的其它構(gòu)造方法,則遞歸執(zhí)行這5個(gè) 步驟;如果執(zhí)行過程正常則跳到步驟5;
3)如果構(gòu)造方法的第一個(gè)語句沒有顯式調(diào)用本類的其它構(gòu)造方法,并且本類不是Object類(Object是所有其它類的祖先),則調(diào)用顯式(用super指針)或隱式地指定的父類的構(gòu)造方法,遞歸執(zhí)行這5個(gè)步驟;如果執(zhí)行過程正常則跳到步驟5;
4)按照變量在類內(nèi)的定義順序來初始化本類的變量,如果執(zhí)行過程正常則跳到步驟5;
5)執(zhí)行這個(gè)構(gòu)造方法中余下的語句,如果執(zhí)行過程正常則過程結(jié)束。
對(duì)分析本文的實(shí)例最重要的,用一句話說,就是“父類的構(gòu)造方法調(diào)用發(fā)生在子類的變量初始化之前”??梢杂孟旅娴睦觼碜C明:
列1
class Animal
{
Animal()
{
System.out.println("Animal");
}
}
class Cat extends Animal
{
Cat()
{
System.out.println("Cat");
}
}
class Store
{
Store()
{
System.out.println("Store");
}
}
public class Petstore extends Store
{
Cat cat = new Cat();
Petstore()
{
System.out.println("Petstore");
}
public static void main(String[] args)
{
new Petstore();
}
}
運(yùn)行這段代碼,它的執(zhí)行結(jié)果如下:
Store
Animal
Cat
Petstore
從結(jié)果中可以看出,在創(chuàng)建一個(gè)Petstore類的實(shí)例時(shí),首先調(diào)用了它的父類Store的構(gòu)造方法;然后試圖創(chuàng)建并初始化變量cat;在創(chuàng)建cat時(shí),首先調(diào)用了Cat類的父類Animal的構(gòu)造方法;其后才是Cat的構(gòu)造方法主體,最后才是Petstore類的構(gòu)造方法的主體。
列2
class Animal
{
Animal()
{
System.out.println("Animal");
}
}
class Cat extends Animal
{
Cat()
{
System.out.println("Cat");
}
}
class Cat2 extends Animal
{
Cat2()
{
System.out.println("Cat2");
}
}
class Store
{
Cat2 cat=new Cat2();
Store()
{
System.out.println("Store");
}
}
public class Petstore extends Store
{
Cat cat = new Cat();
Petstore()
{
System.out.println("Petstore");
}
public static void main(String[] args)
{
new Petstore();
}
}
運(yùn)行這段代碼,它的執(zhí)行結(jié)果如下:
Animal
Cat2
Store
Animal
Cat
Petstore
這例1和例2,使我更了解了類的構(gòu)造過程:
類在new實(shí)例的時(shí)候
a。第一步構(gòu)造類的成員變量
這里需要注意的:
a)即使變量定義散布于方法定義之間,它們?nèi)耘f會(huì)在任何方法(包括構(gòu)造函數(shù))被調(diào)用之前得到初始化
b)初始化的順序是先“靜態(tài)”對(duì)象(初始化過后,靜態(tài)對(duì)象不會(huì)再被初始化),而后是“非靜態(tài)”對(duì)象。
第二步調(diào)用構(gòu)造方法。
b。如果有父類,那么就是先構(gòu)造父類的成員變量,然后再調(diào)用父類的構(gòu)造方法,然后再a。
this用法
java中的this隨處可見,用法也多,現(xiàn)在整理有幾點(diǎn):
1. this是指當(dāng)前對(duì)象自己。
當(dāng)在一個(gè)類中要明確指出使用對(duì)象自己的的變量或函數(shù)時(shí)就應(yīng)該加上this引用。如下面這個(gè)例子中:
public class Hello
{
String s = "Hello";
public Hello(String s)
{
System.out.println("s = " + s);
System.out.println("1 -> this.s = " + this.s);
this.s = s;
System.out.println("2 -> this.s = " + this.s);
}
public static void main(String[] args)
{
Hello x=new Hello("HelloWorld!");
}
}
運(yùn)行結(jié)果:
s = HelloWorld!
1 -> this.s = Hello
2 -> this.s = HelloWorld!
在這個(gè)例子中,構(gòu)造函數(shù)Hello中,參數(shù)s與類Hello的變量s同名,這時(shí)如果直接對(duì)s進(jìn)行操作則是對(duì)參數(shù)s進(jìn)行操作。
若要對(duì)類Hello的成員變量s進(jìn)行操作就應(yīng)該用this進(jìn)行引用
class A
{
public A()
{
new B(this).print();
}
public void print()
{
System.out.println("Hello from A!");
}
}
class B
{
A a;
public B(A a)
{
this.a = a;
}
public void print()
{
a.print();
System.out.println("Hello from B!");
}
}
public class C
{
public static void main(String[] args)
{
A x=new A();
}
}
運(yùn)行結(jié)果:
Hello from A!
Hello from B!
在這個(gè)例子中,對(duì)象A的構(gòu)造函數(shù)中,用new B(this)把對(duì)象A自己作為參數(shù)傳遞給了對(duì)象B的構(gòu)造函數(shù)。
2。在構(gòu)造函數(shù)中,通過this可以調(diào)用同一class中別的構(gòu)造函數(shù),如
class Flower
{
Flower (int pig)
{
System.out.println("pig:"+ pig );
}
Flower(String ss)
{
ss="string";
System.out.println("ss:"+ ss);
}
Flower(int pig, String ss)
{
this(pig);
System.out.println("pigpig"+ pig);
}
}
public class Zx
{
public static void main(String[] args)
{
Flower a=new Flower(7,"java");
}
}
運(yùn)行結(jié)果:
pig:7;
pigpig:7;
值得注意的是:
1:在構(gòu)造調(diào)用另一個(gè)構(gòu)造函數(shù),調(diào)用動(dòng)作必須置于最起始的位置。
2:不能在構(gòu)造函數(shù)以外的任何函數(shù)內(nèi)調(diào)用構(gòu)造函數(shù)。
static
1. 調(diào)用靜態(tài)方法時(shí),不需要產(chǎn)生對(duì)象.因?yàn)殪o態(tài)方法屬于類本身,而不屬于對(duì)象. 調(diào)用時(shí): 類名.靜態(tài)方法名() 就可以
2.
class Point
{
int x;
static int y; //定義了1個(gè)靜態(tài)變量
static void output()
{
System.out.println("out");
}
public static void main(String[] args)
{
Point.output(); //調(diào)用靜態(tài)方法
Point pt1=new point();
Point pt2=new point();
pt1.y=5;
pt2.y=6;
System.out.println(pt1.y);
System.out.println(pt2.y);
}
}
結(jié)果
pt1 6
pt2 6
靜態(tài)常量和靜態(tài)方法,都只屬于某個(gè)類,加載的時(shí)候 已經(jīng)有內(nèi)存空間了.所有對(duì)象都共享同1個(gè)靜態(tài)變量,同1個(gè)靜態(tài)方法..引用直接通過類名引用.
但非靜態(tài)方法,可以調(diào)用靜態(tài)方法和靜態(tài)變量;但反過來,靜態(tài)方法不能調(diào)用非靜態(tài)變量和非靜態(tài)方法.(即 x)
final
final類不能被繼承,因此final類的成員方法沒有機(jī)會(huì)被覆蓋,默認(rèn)都是final的。在設(shè)計(jì)類時(shí)候,如果這個(gè)類不需要有子類,類的實(shí)現(xiàn)細(xì)節(jié)不允許改變,并且確信這個(gè)類不會(huì)載被擴(kuò)展,那么就設(shè)計(jì)為final類。
1.定義及編程技巧
final類不能被繼承,沒有子類,final類中的方法默認(rèn)是final的。
final方法不能被子類的方法覆蓋,但可以被繼承。
final成員變量表示常量,只能被賦值一次,賦值后值不再改變。
final不能用于修飾構(gòu)造方法。
注意:父類的private成員方法是不能被子類方法覆蓋的,因此private類型的方法默認(rèn)是final類型的
2、final方法
如果一個(gè)類不允許其子類覆蓋某個(gè)方法,則可以把這個(gè)方法聲明為final方法。
使用final方法的原因有二:
第一、把方法鎖定,防止任何繼承類修改它的意義和實(shí)現(xiàn)。
第二、高效。編譯器在遇到調(diào)用final方法時(shí)候會(huì)轉(zhuǎn)入內(nèi)嵌機(jī)制,大大提高執(zhí)行效率。
技巧:final static 類型成員變量。static使得變量只存在一個(gè)拷貝。final使得它不能改變。
3.關(guān)于final成員賦值的討論:
a.final 成員能且只能被初始化一次
b.final成員必須在聲明時(shí)或者在構(gòu)造方法中被初始化,而不能在其它的地方被初始化。
eg1
public class Aox
{
int height;
Aox(int h)
{
height=h;
}
void bb()
{
System.out.println(height);
} public static void main(String[] args)
{
Aox boxobj = new Aox(25);
boxobj.bb();
boxobj=new Aox(32);
boxobj.bb();
}
}
運(yùn)行結(jié)果:
25
32
eg2
public class Aox
{
int height;
Aox(int h)
{
height=h;
}
void bb()
{
System.out.println(height);
} public static void main(String[] args)
{
Aox boxobj = new Aox(25);
boxobj.bb();
// boxobj=new Aox(32); 出錯(cuò)!
boxobj.bb();
}
}
super
1.super(參數(shù)):調(diào)用基類中的某一個(gè)構(gòu)造函數(shù)(應(yīng)該為構(gòu)造函數(shù)中的第一條語句)
2.super: 它引用當(dāng)前對(duì)象的直接父類中的成員(用來訪問直接父類中被隱藏的父類中成員數(shù)據(jù)或函數(shù),基類與派生類中有相同成員定義時(shí))
如:super.變量名
super.成員函數(shù)據(jù)名(實(shí)參)
包
1.從本質(zhì)上來說,包是將類組合在一起形成代碼模塊的一種機(jī)制,可以將包看成一個(gè)“文件夾”,而包里的各類,則是“文件”。
用途:避免命名沖突;可以在更廣的范圍保護(hù)類,數(shù)據(jù)和方法。
2.創(chuàng)建包
package a; //a是包名
3.導(dǎo)入包
1) import package a.* //a是包名。字符"*"則導(dǎo)入了包里的所有類和接口。
2) import package a.b //a是包名,b是類名。該操作導(dǎo)入了a包里的b類,而不會(huì)導(dǎo)入其它類。
4.使用其它包的類,而沒有用import導(dǎo)入該包,操作如下:
a.b x= new a.b(); //a是包名,b是a包里的類,x是剛創(chuàng)建的該類的實(shí)例名。