1. 程式人生 > >繼承與多態 - 課後作業

繼承與多態 - 課後作業

相加 隱式 -1 多態 字串 方式 信息 .sh str

1 . 繼承條件下的構造方法調用

class Grandparent 
{
    public Grandparent()
 	{
        	System.out.println("GrandParent Created.");
 	}

    public Grandparent(String string) 
	{
        	System.out.println("GrandParent Created.String:" + string);	   
	}
}

class Parent extends Grandparent
{
    public Parent()
	 {
        	//super("Hello.Grandparent.");

        	System.out.println("Parent Created");
	
       // super("Hello.Grandparent.");

	  }
}

class Child extends Parent 
{
    public Child()
	 {
        System.out.println("Child Created");
	  }
}

public class TestInherits 
{
    public static void main(String args[])
	 {
       	Child c = new Child();
  }

}

  截圖:

技術分享技術分享

第一個是沒有用super,第二個用到了super,super()括號中有參數,所以就調用了有參數的基類構造方法。當把super的語句放到後面的時候,程序報錯,構造函數調用必須是構造函數中的第一個語句。

父類與子類之間構造方法的調用關系修改Parent構造方法的代碼,顯式調用GrandParent的另一個構造函數,這句調用代碼必須是第一句,不然會報錯。通過 super 調用基類構造方法,必須是子類構造方法中的第一個語句。

2 . 為什麽子類的構造方法在運行之前,必須調用父類的構造方法?能不能反過來?為什麽不能反過來?

構造函數是一種特殊的方法 。主要在創建對象時初始化對象,

即為對象成員變量賦初值,總與new運算符一起使用在創建對象的語句中 。一個類可以有多個構造函數 ,可根據其參數個數的不同或參數類型的不同來區分它們 即構造函數的重載。構造函數的功能主要用於在類的對象創建時定義初始化的狀態。

構造一個對象,先調用其構造方法,來初始化其成員函數和成員變量。

子類擁有父的成員變量和方法,如果不調用,則從父類繼承而來的成員變量和成員方法得不到正確的初始化。

不能反過來調用,因為父類不知道子類有什麽變量,而且子類也得不到初始化的父類變量,導致程序運行出錯!

3 . A@1c5f743的運行結果

package kehou5;
public class ExplorationJDKSource { /** * @param args */ public static void main(String[] args) { System.out.println(new A()); } } class A{}

運行截圖: 

 技術分享

原因:使用javap –c命令反匯編這個程序,發現main方法實際上調用的是:public void println(Object x),這一方法內部調用了String類的valueOf方法。

valueOf方法內部又調用Object.toString方法:

public String toString() {

return getClass().getName() +"@" +

Integer.toHexString(hashCode());

}

hashCode方法是本地方法,由JVM設計者實現:public native int hashCode();

4 . 註意最後一句,為什麽一個字串和一個對象“相加”,得到以下結果

技術分享

結果;

技術分享

原因:在“+”運算中,當任何一個對象與一個String對象,連接時,會隱式地調用其toString()方法,默認情況下,此方法返回“類名 @ + hashCode”。為了返回有意義的信息,子類可以重寫toString()方法。

5 . 自行編寫代碼測試以下特性:在子類中,若要調用父類中被覆蓋的方法,可以使用super關鍵字。

class Parent
{
    public void show()
    {
        System.out.println("111");
    }
}
class Child extends Parent
{
    public void show()
    {
        super.show();
        System.out.println("222");
    }
}
public class test {
    public static void main(String [] args)
    {
        Child c = new Child();
        c.show();
    }

截圖:

技術分享

結果分析:super方法在子類覆蓋方法類使用,只有這樣才能調用父類中被覆蓋的方法,並且super語句放在子類覆蓋方法第幾句都行

6 .

現在有三個類: class Mammal{} class Dog extends Mammal {} class Cat extends Mammal{}

針對每個類定義三個變量並進行初始化 Mammal m=null ; Dog d=new Dog(); Cat c=new Cat();

下列語句哪一個將引起編譯錯誤?為什麽?哪一個會引起運行時錯誤?為什麽?

m=d; d=m; d=(Dog)m; d=c; c=(Cat)m;

class Mammal{}
class Dog extends Mammal {}
class Cat extends Mammal{}

public class TestCast
{
	public static void main(String args[])
	{
		Mammal m;
		Dog d=new Dog();
		Cat c=new Cat();
		m=d;
		//d=m;
		d=(Dog)m;
		//d=c;
		//c=(Cat)m;

	}
}

d=m;d=c;

不正確 子類對象可以直接賦給基類變量。
基類對象要賦給子類對象變量,必須執行類型轉換,
其語法是:子類對象變量=(子類名)基類對象名;

c=(Cat)m

不正確 轉換混亂。如果類型轉換失敗Java會拋出以下這種異常:ClassCastException

7 . 運行以下測試代碼

public class ParentChildTest {
	public static void main(String[] args) {
		Parent parent=new Parent();
		parent.printValue();
		Child child=new Child();
		child.printValue();
		
		parent=child;
		parent.printValue();
		
		parent.myValue++;
		parent.printValue();
		
		((Child)parent).myValue++;
		parent.printValue();
		
	}
}

class Parent{
	public int myValue=100;
	public void printValue() {
		System.out.println("Parent.printValue(),myValue="+myValue);
	}
}
class Child extends Parent{
	public int myValue=200;
	public void printValue() {
		System.out.println("Child.printValue(),myValue="+myValue);
	}
}

  運行結果:

技術分享

原因:通過強制類型轉換子類的字符將父類的字符覆蓋了

計算機是不會出錯的,之所以得到這樣的運行結果也是有原因的,那麽從這些運行結果中,你能總結出Java的哪些語法特性?

當子類與父類擁有一樣的方法,並且讓一個父類變量引用一個子類對象時,到底調用哪個方法,由對象自己的“真實”類型所決定,這就是說:對象是子類型的,它就調用子類型的方法,是父類型的,它就調用父類型的方法。

如果子類與父類有相同的字段,則子類中的字段會代替或隱藏父類的字段,子類方法中訪問的是子類中的字段(而不是父類中的字段)。如果子類方法確實想訪問父類中被隱藏的同名字段,可以用super關鍵字來訪問它。

如果子類被當作父類使用,則通過子類訪問的字段是父類的。

8 . 這種編程方式有什麽不合理的地方嗎?

public class Zoo 
{
	public static void main(String args[])
	{
		Feeder f = new Feeder("小李");
		// 飼養員小李餵養一只獅子
		f.feedLion(new Lion());
		// 飼養員小李餵養十只猴子

		for (int i = 0; i < 10; i++)
 		{
			f.feedMonkey(new Monkey());
		}
		// 飼養員小李餵養5只鴿子
		for (int i = 0; i < 5; i++)
 		{
			f.feedPigeon(new Pigeon());
		}
	}

}

class Feeder 
{
	public String name;
	public Feeder(String name)
	{
		this.name = name;
	}
	public void feedLion(Lion l)
	{
		l.eat();
	}
	public void feedPigeon(Pigeon p)
	{
		p.eat();
	}
	public void feedMonkey(Monkey m)
	{
		m.eat();
	}
}
class Lion
{
	public void eat() 
	{
		System.out.println("我不吃肉誰敢吃肉!");
	}
}
class Monkey 
{
	public void eat() 
	{
		System.out.println("我什麽都吃,尤其喜歡香蕉。");
	}
}
class Pigeon 
{
	public void eat() 
	{
		System.out.println("我要減肥,所以每天只吃一點大米。");
	}
}

算法太復雜。

結果:

技術分享

繼承與多態 - 課後作業