您好,登錄后才能下訂單哦!
本篇內容主要講解“Java中重復運用classes的方法是什么”,感興趣的朋友不妨來看看。本文介紹的方法操作簡單快捷,實用性強。下面就讓小編來帶大家學習“Java中重復運用classes的方法是什么”吧!
一.繼承(inheritance)
1. 在derived class中overriding某個函數時,只能覆寫base class中的接口,即base class中的public或protected或friendly函數。如果試圖overriding一個private函數,雖然編譯通過,但實際上你只是在derived class中添加了一個函數。如
class Cleanser{
private void prt(){//(b)
System.out.println("Cleanser.prt()");
}
}
public class ExplicitStatic extends Cleanser{
public void prt(){
System.out.println("ExplicitStatic.prt()");
}
public static void main(String[] args){
Cleanser x = new ExplicitStatic();
x.prt();//(a)
}
}
因為Cleanser中的prt()是private,所以不能在其derived class中被覆寫。ExplicitStatic中的prt()只是ExplicitStatic中的一個函數,所以當試圖在(a)處通過多態來調用prt()時,會發生錯誤。如果把(b)處的private去掉,則結果為
ExplicitStatic.prt()
2. Super的使用
1)通過關鍵字super可以調用當前class的superclass(父類)。
例6.1.1.1
class Base{
Base(){System.out.println("Base()");}
public void scrub() { System.out.println(" Base.scrub()"); }
}
class Cleanser extends Base{
private String s = new String("Cleanser");
public void append(String a) { s+=a; }
public void dilute() { append(" dilute()"); }
public void apply() { append(" apply()"); }
public void scrub() { append(" scrub()"); }
public void print() { System.out.println(s); }
Cleanser(){
System.out.println("Cleanser(): " + s);
}
public static void testStatic(){
System.out.println("testStatic()");
}
public static void main(String[] args){
Cleanser x = new Cleanser();
x.dilute(); x.apply(); x.scrub(); x.print();
}
}
public class ExplicitStatic extends Cleanser{
ExplicitStatic(){
System.out.println("ExplicitStatic()");
}
public void scrub(){
append(" Detergen.scrub()");
super.testStatic();
super.scrub();//調用的是Cleanser.scrub()
}
public void foam() { append(" foam()"); }
public static void main(String[] args){
ExplicitStatic x = new ExplicitStatic();
x.dilute(); x.apply(); x.scrub(); x.foam();
x.print(); System.out.println("Test base class:");
Cleanser.main(args);
testStatic();
}
}
運行結果:
Base()
Cleanser(): Cleanser
ExplicitStatic()
testStatic()
Cleanser dilute() apply() Detergen.scrub() scrub() foam()
Test base class:
Base()
Cleanser(): Cleanser
Cleanser dilute() apply() scrub()
testStatic()
2)通過super來調用superclass中的成員時,調用的是最近成員。
例6.1.1.2
class Base{
protected String baseS = "Base";//(a)
//private String baseS = "Base";
Base(){System.out.println("Base()");}
}
class Cleanser extends Base{
protected String baseS = "Cleanser";//(b)
public String s = new String("Cleanser");
Cleanser(){
System.out.println("Cleanser(): " + s);
}
Cleanser(String a){
System.out.println("Cleanser(" + a + "): s = " + s );
}
}
public class ExplicitStatic extends Cleanser{
String s2 = s;
String baseS = super.baseS; //(c)
ExplicitStatic(){
super("ExplicitStatic");
System.out.println("ExplicitStatic():s2 = " + s2 + ", baseS = " + baseS + "super.baseS = " + super.baseS);
baseS = "ExplicitStatic";
System.out.println("baseS = " + baseS + " , super.baseS = " + super.baseS);
}
public static void main(String[] args){
ExplicitStatic x = new ExplicitStatic();
}
}
結果1:
Base()
Cleanser(ExplicitStatic): s = Cleanser
ExplicitStatic():s2 = Cleanser, baseS = Cleanser,super.baseS = Cleanser
baseS = ExplicitStatic , super.baseS = Cleanser
在上面例子中,在三個class中都存在String bases實例。在ExplicitStatic中如果直接調用baseS,則實際調用的是當前類ExplicitStatic中的baseS(即(c)處的成員);如果通過super.bases來調用baseS,則調用的是離當前類ExplicitStatic最近的baseS成員,即Cleanser class中的baseS實例(即(b)處),產生的結果如結果1所示。如果把(b)處語句注釋掉,則將調用Base class中的baseS,結果如結果2所示。
結果2:
Base()
Cleanser(ExplicitStatic): s = Cleanser
ExplicitStatic():s2 = Cleanser, baseS = Base,super.baseS = Base
baseS = ExplicitStatic , super.baseS = Base
3. Base class的初始化
2.1 當你產生derived class對象時,其中會包含base class子對象(subobject)。這個子對象就和你另外產生的base class對象一模一樣。
2.2 通過super()可調用base class的構造函數,但必須放在構造函數的第一行,并且只能在構造函數中運用。
2.3 初始化順序為:
1) 加載代碼(.class文件)
2) 初始化class的靜態成員,初始化順序了“從里到外”,即從base class開始。
3) 在derived class的構造函數中調用base class的構造函數。
如果在derived class的構造函數中沒有通過super()顯式調用調用base class的構造函數,編譯器會調用bass class的default構造函數并自動生成相應的調用語句,從而產生一個base class實例。如果在derived class的構造函數中通過super()顯示調用了父類的構造函數,則調用所指定的構造函數。調用構造函數的調用順序是“從里到外”。
4) 調用derived class的構造函數。
**:當base class沒有default構造函數時,必須在derived class的構造函數中通過super顯示調用base class的構造函數。
例:下面代碼的初始化過程為:
1) 裝載ExplicitStatic的代碼(裝載ExplicitStatic.class文件)。
2) 發現ExplicitStatic有關鍵字extends,裝載ExplicitStatic的base class的代碼(裝載Cleanser.class文件)。
3) 發現Cleanser有關鍵字extends,裝載Cleanser的base class的代碼(裝載Base.class文件)。
4) 初始化Base class中的靜態成員。
5) 初始化Cleanser class中的靜態成員。
6) 初始化ExplicitStatic class中的靜態成員。
如果把(c)處的代碼注釋掉,那么初始化工作到此就結束了。
7) 為ExplicitStatic對象分配存儲空間,并把存儲空間初始化為0。
8) 在ExplicitStatic class的構造中調用super("ExplicitStatic")(在ExplicitStatic class的構造函數中顯式調用父類的構造函數),試圖產生一個Cleanser class實例。
9) 為Cleanser對象分配存儲空間,并把存儲空間初始化為0。
10) 由于Cleanser class又是繼承自Base class,會在Cleanser class的構造函數中通過super()(由于沒有顯式調用父類的構造函數,所以自動調用父類的default構造函數)調用父類的構造函數,試圖產生一個Cleanser class實例。
11) 產生一個Base class實例。先初始化成員變量,再調用構造函數。
12) 回到Cleanser class,產生一個實例。首先初始化Cleanser class中的成員數據,再執行構造函數Cleanser(String a)中的其余部分。
13) 回到ExplicitStatic class,產生一個實例。首先初始化ExplicitStatic class中的成員數據,再執行構造函數ExplicitStatic ()中的其余部分(System.out.println(“ExplicitStatic()”))。
class Base{
static int s1 = prt("s1 initialized.", 11);
int i1 = prt("i1 initialized.", 12);
Base(){
System.out.println("Base()");
System.out.println("s1 = " + s1 + " ,i1 = " + i1);
draw();//(d)
}
void draw(){
System.out.println("base.draw:s1 = " + s1 + " ,i1 = " + i1);
}
static int prt(String s, int num) {
System.out.println(s);
return num;
}
}
class Cleanser extends Base{
static int s2 = prt("s2 initialized.", 21);
int i2 = prt("i2 initialized.", 22);
Cleanser(){
System.out.println("Cleanser()");
System.out.println("s2 = " + s2 + " ,i2 = " + i2);
}
Cleanser(String a){
//super();(b)
System.out.println("Cleanser(" + a + ")");
System.out.println("s2 = " + s2 + " ,i2 = " + i2);
}
void draw(){
System.out.println("Cleanser.draw:s2 = " + s2 + " ,i2 = " + i2);
}
}
public class ExplicitStatic extends Cleanser{
static int s3 = prt("s3 initialized.", 31);
int i3 = prt("i3 initialized", 31);
ExplicitStatic(){
super("ExplicitStatic");//(a)
System.out.println("ExplicitStatic()");
System.out.println("s3 = " + s3 + " ,i3 = " + i3);
}
public static void main(String[] args){
ExplicitStatic x = new ExplicitStatic();//(c)
}
}
結果:
s1 initialized.
s2 initialized.
s3 initialized.
//如果把(c)處的代碼注釋掉,輸出結果到此為止,不會輸出下面結果
i1 initialized.
Base()
s1 = 11 ,i1 = 12
Cleanser.draw:s2 = 21 ,i2 = 0//(d)處結果
i2 initialized.
Cleanser(ExplicitStatic)//(a)處結果
s2 = 21 ,i2 = 22
i3 initialized
ExplicitStatic()
s3 = 31 ,i3 = 31
由于在Base()中調用draw()時,Cleanser中的i2還未進行初始化,而在為Cleanser對象分配存儲空間時,把存儲空間初始化為0,所以此時i2為0。
2.4 代碼及結果中的(a)說明了是先產生當前class的base class的實例,否則在derived class中無法調用base class的成員。在調用Cleanser class的構造函數Cleanser(String a)時,在Cleanser(String a)中沒有用super顯式調用Base class的構造函數,所以系統會自動生成調用Base class的default構造函數的語句,如(b)。
4. 組合與繼承之間的快擇
. 1)繼承表示的是一種“is-a(是一個)”的關系,如貨車是汽車中的一種;組合表示的是一種“has-a(有一個)”的關系,如汽車有四個輪子。
2)是否需要將新的class向上轉型為base class。
5. 在繼承中的訪問權限
protect變量能被子孫類所調用。如Base class中的baseS能被Cleanser class和ExplicitStatic class調用。
class Base{
protected String baseS = "Base";
//private String baseS = "Base";
Base(){System.out.println("Base()");}
}
class Cleanser extends Base{
protected String baseS = "Cleanser";
public String s = new String("Cleanser");
Cleanser(){
System.out.println("Cleanser(): " + s);
}
Cleanser(String a){
System.out.println("Cleanser(" + a + "): s = " + s );
}
}
public class ExplicitStatic extends Cleanser{
String s2 = s;
String baseS = super.baseS;
ExplicitStatic(){
super("ExplicitStatic");
System.out.println("ExplicitStatic():s2 = " + s2 + ", baseS = " + baseS + "super.baseS = " + super.baseS);
baseS = "ExplicitStatic";
System.out.println("baseS = " + baseS + " , super.baseS = " + super.baseS);
}
public static void main(String[] args){
ExplicitStatic x = new ExplicitStatic();
}
}
結果:
Base()
Cleanser(ExplicitStatic): s = Cleanser
ExplicitStatic():s2 = Cleanser, baseS = Cleanser, super.baseS = Cleanser
baseS = ExplicitStatic , super.baseS = Cleanser
二.關鍵字final
1.Final data
1.1 final data
1)當基本型別被定義為final,表示它的數據值不能被改變。如
final int i = 9;
i++;//編譯錯誤,不能改變I的值
2) 當object reference被定義為final時,不能改變的只是reference而不是對象本身。如
class Value{
int i = 1;
}
public class ExplicitStatic extends Cleanser{
public static void main(String[] args){
final Value v = new Value();//v.i = 1
v.i++;//v.i = 2
//v = new Value();
}
}
由于v為final,所以不能通過new Value()使v重新指向一個對象;但是v所指向的對象的值是可以改變的(v.i++)。
1.2 blank finals
我們可以將數據成員聲明為final但不給予初值,這就是blank finals。但blank finals必須且只能在構造函數中進行初始化。
public class ExplicitStatic {
final int ib;
final int i = 1;
ExplicitStatic()
{
ib = 2;//(a)
//i = 3; (b)
System.out.println("i = " + i + ", ib = " + ib);
}
public static void main(String[] args){
ExplicitStatic ex = new ExplicitStatic();
}
}
ib為blank finals,所以可以在構造函數中進行初始化。如果把(a)處的代碼注釋掉,則ib沒有初值,編譯出錯。而i在定義處已進行了初始化,則不能改變i的值,(b)處的代碼編譯錯誤。
**:非blank finals成員即使在構造函數中也不能更改其值
2.Final methods
1)被聲明為final的函數不能被覆寫
2)class中所有private函數自然而然會是final。
1. Final classes
1)當一個class被聲明為final時,表示它不能被繼承,但class的數據成員不是final,可以被改變。如
class SmallBrain{}
XML:namespace prefix = o ns = "urn:schemas-microsoft-com:Office:office" />
final class Dinosaur{
int i = 7;
int j = i;
SmallBrain x = new SmallBrain();
void f(){};
}
//不能繼承final函數
//class Further extends Dinosaur{}
public class ExplicitStatic{
public static void main(String[] args){
Dinosaur n = new Dinosaur();
n.f();
n.i = 40;//final class中的non-final數據成員可以被改變
n.j++;
}
}
2)final class中的所有函數也都自然是final,因為沒有人能夠加以覆寫。
到此,相信大家對“Java中重復運用classes的方法是什么”有了更深的了解,不妨來實際操作一番吧!這里是億速云網站,更多相關內容可以進入相關頻道進行查詢,關注我們,繼續學習!
免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。