java的super和this關鍵字用法總結
阿新 • • 發佈:2019-01-09
------super關鍵字------
super用途:在子類中訪問超類“被隱藏的成員變數(無論是否靜態)和靜態方法”以及“被重寫的例項方法”。這裡的超類必須是“直接超類”,即子類之上最近的超類。
super的用法:
①在子類構造方法中呼叫超類的構造方法,用“super(ParamList)”的方式呼叫,ParamList根據超類構造方法而定,可以為空。另外super(ParamList)必須是子類構造方法的第一句。
②當超類的成員變數因與子類的成員變數同名而被隱藏時(成員變數隱藏與是否靜態無關),可用"super.memberVariableName"來訪問超類的成員變數。
注意:有些人說當超類的成員變數與子類某方法的區域性變數或引數同名時,也屬於被隱藏。那麼一旦離開該方法隱藏還成立嗎,顯然這種說法是錯誤的。隱藏概念只限於成員變數範圍,方法體內的區域性變數與成員變數同名屬於下面的this要討論的內容。
假設有超類parent,其中有成員變數A,子類child,其中有方法method(type A)存在:
1)如果子類沒有隱藏超類成員變數A,在method(type A)中,無論使用this.A還是super.A都是一樣的,都會訪問超類成 員變數A;(this.A就是繼承下來的,換句話說,對於自然繼承下來(沒有隱藏/重寫) 的成員變數甚至是方法,super.memberName=this.membername)
2)如果子類有成員變數A隱藏了超類成員變數A,在method(type A)中,super.A=parent.A,this.A=child.A,兩者有區別。
③當超類的靜態方法/例項方法被子類隱藏/重寫時,可使用"super.methodName(ParamList)"來訪問超類方法。對於靜態方法而言,這沒什麼奇怪,對於例項方法而言,這種用法使得超類被重寫的方法在子類中可見。
最後需要注意,super關鍵字不能在靜態方法中使用!
------this關鍵字------
this的用途:引用物件本身。
當一個物件建立後,Java虛擬機器就會給這個物件分配一個引用自身的指標,這個指標的名字就是this。因此,this只能在類中的非靜態方法中使用,靜態方法和靜態的程式碼塊中絕對不能出現this。並且this只和特定的物件關聯,而不和類關聯,同一個類的不同物件有不同的this。
this用法:
①在構造方法中,用this(ParamList)呼叫自己的另一個構造方法,this(ParamList)必須放在第一句位置!此用法只限於在構造方法中使用。
②某方法的引數或區域性變數與某個成員變數同名時,在該方法中要訪問該成員變數需要用“this.memberVariableName”的形式。
③某方法中需要引用其所屬類的當前物件時,直接用this來引用當前物件。
示例程式碼:
super用途:在子類中訪問超類“被隱藏的成員變數(無論是否靜態)和靜態方法”以及“被重寫的例項方法”。這裡的超類必須是“直接超類”,即子類之上最近的超類。
super的用法:
①在子類構造方法中呼叫超類的構造方法,用“super(ParamList)”的方式呼叫,ParamList根據超類構造方法而定,可以為空。另外super(ParamList)必須是子類構造方法的第一句。
②當超類的成員變數因與子類的成員變數同名而被隱藏時(成員變數隱藏與是否靜態無關),可用"super.memberVariableName"來訪問超類的成員變數。
注意:有些人說當超類的成員變數與子類某方法的區域性變數或引數同名時,也屬於被隱藏。那麼一旦離開該方法隱藏還成立嗎,顯然這種說法是錯誤的。隱藏概念只限於成員變數範圍,方法體內的區域性變數與成員變數同名屬於下面的this要討論的內容。
假設有超類parent,其中有成員變數A,子類child,其中有方法method(type A)存在:
1)如果子類沒有隱藏超類成員變數A,在method(type A)中,無論使用this.A還是super.A都是一樣的,都會訪問超類成 員變數A;(this.A就是繼承下來的,換句話說,對於自然繼承下來(沒有隱藏/重寫)
2)如果子類有成員變數A隱藏了超類成員變數A,在method(type A)中,super.A=parent.A,this.A=child.A,兩者有區別。
③當超類的靜態方法/例項方法被子類隱藏/重寫時,可使用"super.methodName(ParamList)"來訪問超類方法。對於靜態方法而言,這沒什麼奇怪,對於例項方法而言,這種用法使得超類被重寫的方法在子類中可見。
最後需要注意,super關鍵字不能在靜態方法中使用!
------this關鍵字------
this的用途:引用物件本身。
當一個物件建立後,Java虛擬機器就會給這個物件分配一個引用自身的指標,這個指標的名字就是this。因此,this只能在類中的非靜態方法中使用,靜態方法和靜態的程式碼塊中絕對不能出現this。並且this只和特定的物件關聯,而不和類關聯,同一個類的不同物件有不同的this。
this用法:
①在構造方法中,用this(ParamList)呼叫自己的另一個構造方法,this(ParamList)必須放在第一句位置!此用法只限於在構造方法中使用。
②某方法的引數或區域性變數與某個成員變數同名時,在該方法中要訪問該成員變數需要用“this.memberVariableName”的形式。
③某方法中需要引用其所屬類的當前物件時,直接用this來引用當前物件。
示例程式碼:
import java.lang.reflect.Field;
import java.lang.reflect.Modifier;
class A {
int x;
static double y;
char z;
A(char z) {
this.z = z; // this訪問成員變數,以區分同名引數
}
A(double newy, char newz) {
double y = newy; // this訪問成員變數,以區分同名區域性變數
char z = newz;
this.y = y; // 因y是靜態成員變數,最好使用className.staticMemberVarName即A.y訪問
this.z = z;
}
A(int a, double b, char c) {
this(b, c);// 使用this(paramList)呼叫另一個構造方法必須放在第一句位置
this.x = a;// 此處無法再使用this(x);理由同上
}
void OutPut() {
if (this.equals(this))// this作為物件引用使用,當然此條件永遠=true
System.out.println("我是類" + GetClassName() + "的方法"
+ GetInvokeMethodName());
}
String GetClassName() {
return this.getClass().getName();
}
String GetInvokeMethodName() {
String TempName = new Exception().getStackTrace()[1].getMethodName();
return TempName;
}
static void showStaticFieldValue(Object obj) throws Exception { //
Field fields[] = obj.getClass().getDeclaredFields();
String fieldName, fieldModifier, fieldType;
Object val;
for (int i = 0; i < fields.length; i++) {
Field field = fields[i];
if (field.toString().indexOf("static") != -1) {
// System.out.println(field.toString());
fieldName = field.getName();
fieldType = field.getType().getName();
fieldModifier = Modifier.toString(field.getModifiers());
field.setAccessible(true);
val = field.get(obj);
System.out.println(fieldModifier + " " + fieldType + " "
+ fieldName + " = " + val);
}
}
}
void getStaticFieldValue() {
try {
showStaticFieldValue(this);
} catch (Exception e) {
}
}
}
class B extends A {
static double x;// 隱藏超類A的成員變數x
int y = (int) this.x + 1;// 隱藏超類A的成員變數y,有人說this必須在方法體中使用,無情的擊破其謠言。
// 繼承了超類A的成員變數z,仍為char z;
B(char c) {
super(c);/*
* super(c)呼叫超類建構函式的目的在於初始化自然繼承的超類成員,若子類完全隱藏了超類的成員變數, 則可以不用super
* super(ParamList)訪問超類建構函式 疑問: 1.類B隱藏且改變了類A的成員變數,
* super(b)是否僅僅改變了B中包含的A物件的值, 而B中的static double x的值仍然為預設值?(待驗證)
* 2.java的構造方法屬於例項方法還是靜態方法?
*/
x = super.y + 1.0;// super訪問超類被隱藏的成員變數double y,也可以寫成A.y
y = super.x;// super訪問超類被隱藏的成員變數int x
}
String GetClassName() {// 重寫超類A的GetClassName()
return "類類類BBB";
}
String GetInvokeMethodName() {// 重寫超類A的GetInvokeMethodName()
return "方法名稱方法名稱方法名稱";
}
void OutPut() { // 重寫超類的OutPut例項方法.
System.out.println("super呼叫超類被重寫的兩個方法輸出:類名="
+ super.GetClassName() + ",方法名=" + super.GetInvokeMethodName());// super呼叫超類的例項方法
System.out.println("用類B的重寫方法輸出:類名=:" + GetClassName() + ","
+ ",方法名="+GetInvokeMethodName());// 呼叫自己的方法
}
static void showStaticFieldValue(Object obj) throws Exception { // 隱藏超類的靜態方法
System.out.println("static Field doulbe x=" + x);
}
void getStaticFieldValue() {
try {
System.out.println("super呼叫超類A的方法輸出靜態成員變數");
super.showStaticFieldValue(this); // super呼叫超類被隱藏的靜態方法
System.out.println("類B自己的方法輸出靜態成員變數");
showStaticFieldValue(this);// 類B自己的方法
} catch (Exception e) {
}
}
}
class Example3_15 {
public static void main(String[] args) {
A myA = new A(8, 6.0, 'k');
B myB = new B('哦');
myA.getStaticFieldValue();
myA.OutPut();
System.out.println("====================");
myB.getStaticFieldValue();
myB.OutPut();
}
}