super的含義
super並沒有代表超類的一個引用的能力(但是,this可以作爲隱含的引用,所以可以System.out.println(this);),只是代表調用父類的方法或屬性而已。
反例:如果super是超類的引用,那麼就可以System.out.println(super);, 事實上不可以,所以super不是超類的引用
看下面的程序
//Test1.java
class A{
public void print(){
System.out.println(super.getClass());//System.out.println(super.getClass().getName());//輸出類的名字,用這個換一下呢,看看結果
System.out.println(this.getClass());
System.out.println(super.hashCode());
System.out.println(this.hashCode());
}
}
class B extends A{
public void print(){
System.out.println(super.getClass());//調用A類中的getclass()方法,A是Object的子類,A中的getClass()是Object中的,運行時期的實例是B類,所以輸出的依然是Class B
System.out.println(this.getClass()); //調用B類中的getclass()方法,此方法從A繼承的,A從Object繼承的,運行時期的實例是B類,所以輸出的是Class B
/*上面的super.getClass()和this.getClass()都是調用的Object中的getClass(),
而super.getClass()和this.getClass()都是通過實例化B類,調用print(),從而調
用這兩個方法,運行時期的類都是B,Object中的getClass()返回的是運行時期的類
名,所以輸出都是Class B
*/
/*事實上如果是通過一個ClassLoader裝載的話,調用super.getClass()是沒有什麼
意義的,不如直接調用 this.getClass() 【這個從網上搜的,自己沒有看過,不過
覺得有用】,有興趣的可以繼續查閱
*/
System.out.println(super.hashCode());
System.out.println(this.hashCode());
/*Object中的hashCode()返回的是實例對象的哈希碼值,此處實例對象是B類的,所
以輸出的都是B類實例的哈希碼
*/
}
}
public class Test1{
public static void main(String[] args){
A a=new A();
B b=new B();
a.print();
b.print();
}
}
/*
運行結果:
class A
class A
14576877
14576877
class B
class B
12677476
12677476
super一直就表示代表調用父類的方法或是屬性,getClass()從Object繼承的。如果 B繼承A, A繼承Object,如果b.getClass() 是B , 那麼,無論B是調用Object中的getClass() ,還是調用 B中的getClass() 結果都是一樣的,就是B 。因爲getClass()的意思就是運行期的類,就是說b一開始是什麼就是什麼。不受造型的影響。
*/
//Test2.java
class A{
}
class B extends A{
public void print(){
System.out.println(super.toString());
System.out.println(this.toString());
/*B繼承A,A繼承Object,所以super.toString()和this.toString()調用的都是Object中的toString(),
返回的是實例對象的字符串形式,實例對象是B類的,所以返回的都是B的
*/
}
}
public class Test2{
public static void main(String[] args){
B b=new B();
b.print();
}
}
/*
運行結果:
B@de6ced
B@de6ced
*/
//Test3.java
class A{
public String toString(){
return "A";
}
}
class B extends A{
public void print(){
System.out.println(super.toString());//調用父類A中的toString(),輸出A
System.out.println(this.toString()); //調用子類B中的toString(),輸出B
/*
因爲A類重寫了Object中的toString()
B類重寫了A類中toString(),所以和Test2.java的結果是不一樣的
*/
}
public String toString(){
return "B";
}
}
public class Test3{
public static void main(String[] args){
B b=new B();
b.print();
}
}
/*
運行結果:
A
B
*/
//Test.java
class A{
int data=1;
public String getName(){
return "A";
}
public int getData(){
return data;
}
public void printData(){
System.out.println(getData());
}
public void printName(){
System.out.println(getName());
}
}
class B extends A{
int data=2;
public String getName(){
return "B";
}
public int getData(){
return data;
}
public void printData(){
//super.printData(); //在本例中和下面的等價,不信自己試試呢
System.out.println(getData());
}
public void printName(){
System.out.println(getName());//在本例中和下面的等價,不信自己試試呢
//super.printName();
}
public void testSuper(){
System.out.println(super.data);//調用父類A中的data爲1
System.out.println(this.data); //調用子類B中的data爲2
System.out.println(super.getName());//調用父類A中的getName()方法,返回"A"
System.out.println(this.getName()); //調用子類B中的getName()方法,返回"B"
System.out.println(super.getData());//調用父類A中的getData()方法,父類A中的getData()方法返回的是父類A的data爲1
System.out.println(this.getData()); //調用子類B中的getData()方法,子類B中的getData()方法返回的是子類B的data爲2
super.printName();//打印B,因爲:調用父類A中的printName()方法,此方法又調用了getName(),是子類B的getName(),爲啥是B的?因爲實例是B類的,由多態性知調用的是B的
this.printName(); //打印B,因爲:調用子類B中的printName()方法,此方法又調用了B中的getName()
super.printData();//打印2,因爲:調用父類A中的printData()方法,此方法又調用了getData(),是子類B的getData(),爲啥是B的?因爲實例B的實例,由多態性知調用的是B的
this.printData();//打印2,因爲:調用子類B中的printData()方法,此方法又調用了B中的getData()
}
}
public class Test{
public static void main(String[] args){
A a=new A();
B b=new B();
A ab=new B();
System.out.println("屬性:");
System.out.println(a.data);
System.out.println(b.data);
System.out.println(ab.data);//屬性不具有多態性,所以輸出的是A類中的data
System.out.println("測試super:");
b.testSuper();
}
}
/*
運行結果:
屬性:
1
2
1
測試super:
1
2
A
B
1
2
B
B
2
2
小結:
在子類B中用super.method()調用父類的方法method(),運行時的實例依然是子類B
1、若父類A的method()中調用了f()這個方法【子類B重寫了這個方法】,那麼這個方法事實上是調用的子類B中的方法,因爲運行時的實例是子類B,方法具
有多態性,所以是調用子類B中的f()
2、若父類A的method()中調用了data這個屬性【子類中重寫了這個屬性】,那麼這個方法事實上調用的依然是父類A中的屬性,儘管運行時的實例是子類B,
但是屬性不具有多態性,所以調用的是父類A中的屬性data
*/
打印地址或不打印地址,object是系統類,一般都不打印地址,如果是自己定義的類,且又沒有重寫toString()方法,那麼打印是地址。如果不想打印出地址,那沒就重寫toString()方法