1. 程式人生 > 其它 >Java -- 面向物件(三)

Java -- 面向物件(三)

技術標籤:javajava

Java – 面向物件(三)

本篇的重點是介紹多型的使用,上篇中介紹的繼承,子類和父類,其實將父類物件應用於子類的特徵就是多型。雖然不好理解,建議關於多型的定義理解,看一下參考書,因為他是抽象的內容,而且多型的綜合性非常強,一條語句可能就包含很多的知識點;建議多練習,新手的話多嘗試逐字逐句分析程式碼的含義,使其抽象的內容做到有自己的理解方式;

十二、final

1、概念
1.	是java中提供的一個關鍵字
2.	finanl是最終的意思
3.	final可以修飾類,方法,成員變數

初衷是因為:java出現了繼承後,子類可以更改父類的功能,當父類功能不許子類改變時可以利用final關鍵字修飾父類。

2、特點

1.被final修飾的類,不能被繼承
2.被final修飾的類,不能被重寫
3.被final修飾的變數是個常量,值不能被修改

3、測試案例

package cn.tedu.finaldemo;

public class Test_Final {
	//測試final關鍵字
	public static void main(String[] args) {
		//建立子類物件測試
		Son son = new Son();
//		son.SUM = 5;//在不加final時可以修改,加上final之後不可以修改
		
		//警告提示:The static field Son.SUM should be accessed in a static way
// System.out.println(son.SUM);//沒有加static通過物件呼叫, System.out.println(Son.SUM);//加上靜態static之後,通過類名呼叫 } } //建立父類 //1、被final修飾的類是最終類,不能被繼承 //final class Father {//The type Son cannot subclass the final class Father class Father { //2、被final修飾的方法是最終方法,不能被重寫 // final public void eat() {//The type Son cannot subclass the final class Father
public void eat() { System.out.println("爸爸在吃肉"); } } //建立子類 class Son extends Father{ //是子類的特有功能,只能建立子類物件才能呼叫 //3、final修飾的變數是常量,常量的值不能被修改 //4、變數前加了final是說變數變成了一個常量。加了static為了方便通過類名來直接呼叫 // int sum = 10; static final int SUM = 10; @Override public void eat() { System.out.println("兒子在喝湯"); } }

控制檯顯示:10

十三、多型

1、概念
	多型指同一個實體同時具有多種形態,他是面向物件程式設計(OOP)的一個重要特性;
	主要是指用一個物件,在不同時刻代表的物件不一樣,指的是物件的多種形態;
	好處是可以把不同的子類物件都當成父類來看,可以遮蔽不同子類物件之間的差異,寫入出通用的程式碼,做出通用的程式設計,統一呼叫標準;
	
	例如:水,在不同時刻可以有多種形態,包括水蒸氣,冰,水

Java怎麼體現多型呢?狗有兩種形態:狗和小動物

class Animal{}
class Dog extends Animal{}
Dog d = new Dog();//狗是狗
Animal a = new Dog();//狗是小動物,建立了狗的物件,賦值給動物物件,這就是多型

2、特點

1.多型前提是繼承
2.要是方法的重寫
3.父類引用指向子類物件:如:Animal a = new Dog(); – 小到大,向上轉型;
4.多型中,編譯看左邊,執行看右邊

3、入門案例

package cn.tedu.muiti;

//這個類用來測試多型
public class Test_Muiti {
	public static void main(String[] args) {
		//3、建立父類測試物件
		Animal animal = new Animal();
		animal.eat();
		
		//4、建立子類測試物件
		Dog dog = new Dog();
		dog.eat();//重寫前,使用的是父類的;重寫後,使用的是子類的;
		
		//5、建立多型測試物件
		//口訣1:父類引用 指向 子類物件   -- 多型/向上轉型
		Animal animal2 = new Dog();
		//口訣2:編譯看左邊,執行看右邊
		//編譯看左邊:想要儲存成功,只能呼叫左邊(父類)的功能  ---- 統一呼叫標準!!標準就是父類!!
		//執行看右邊:執行結果看子類的功能
		animal2.eat();
	}
}
//1、多型的前提:繼承 + 重寫
class Animal{
	public void eat() {
		// TODO Auto-generated method stub
		System.out.println("...");
	}
}
class Dog extends Animal{
	//2、重寫:子類的方法宣告和父類一模一樣
	@Override  //標誌著這是在重寫父類的方法
	public void eat() {
		System.out.println("真香。。");
	}
}

控制檯顯示:
在這裡插入圖片描述

編譯看左邊:想要儲存成功,只能呼叫左邊(父類)的功能;
執行看右邊:執行結果看子類的功能

4.多型的好處

(1)多型的使用

多型可以讓我們不用關心某個物件到底是什麼具體型別,就可以使用該物件的某些方法;

提高了程式的擴充套件性和可維護性

(2)多型的使用特點

	成員變數:使用的是父類的;
	成員方法:由於存在重寫現象所以使用的是子類的;
	靜態成員:隨著物件而存在,誰呼叫的就返回誰的;	

(3)測試案例

package cn.tedu.muiti;

public class Test_UseMulti {
	public static void main(String[] args) {
		//建立多型物件測試
		Father f = new Son();
		
		//1、多型中的成員方法怎麼用??
		//編譯看左邊,用父類提供的方法宣告部分
		//執行看右邊,用子類提供的方法體 --- 多指方法 重寫 現象
		f.study();//天天向上
		
		//2、多型中的成員變數怎麼用? -- 父類的
		System.out.println(f.sum);
		
		//3、多型中的靜態資源怎麼用? -- 父類的
//		System.out.println(f.name);
		System.out.println(Father.name);
		
		//4、測試一下靜態方法能不能重寫?? -- 靜態資源不能重寫,誰呼叫就是誰的
		//因為靜態資源是跟著類存在的
		f.show();
		Father.show();
	}
}
//多型的前提:繼承 + 重寫
class Father{
	int sum = 20;
	static String name = "jack";
	public void study() {
		System.out.println("好好學習");
	}
	static public void show() {
		System.out.println("Fa show...");
	}
}
class Son extends Father{
	int sum = 10;
	static String name = "rose";
	@Override
	public void study() {
		System.out.println("天天向上");
	}
	
	static public void show() {
		System.out.println("son show...");
	}
}

控制檯顯示:

在這裡插入圖片描述
由於多型綜合了前面的封裝和繼承,所以需要多加練習更好的例理解
提供了一個練習案例;
文末會提供聯絡的具體程式碼和答案

/*
 * 自己測試練習:
 * 	--父類 --Teacher
 * 	--子類 --Student
 * 	--建立多型測試
 * 	--成員變數,成員方法,靜態資源
 */

十四、異常

1、概述

用來封裝錯誤資訊的物件
組成結構:型別,提示,行號;

2、異常的繼承結構

Throwable - 頂級父類
-- Error:系統錯誤,無法修復
-- Exception:可修復的錯誤
	--RunTimeException
		--ClassCastException
		--ClassNotFoundException

3、異常處理

程式中遇到異常,通常有兩種處理方式:捕獲或者向上丟擲
當呼叫了一個丟擲異常的方法是,呼叫位置可以不做處理繼續向上爆出也可以捕獲異常
不建議向上丟擲,儘量捕獲,不要選擇丟擲,要不然開發者就刺激了;

1.捕獲方式

try{ 
    需要捕獲的程式碼
}catch(異常型別  異常名){
    處理方案
}

2.丟擲方式
會在發生異常的方法上新增程式碼: throws異常型別,例如:

public static void main(String[] args)  throws Exception{
	
}

4、測試

package cn.tedu.exception;

import java.util.Scanner;

//這個類用來測試異常的暴露
public class Test_Exception {
	public static void main(String[] args) {
		//method();//暴露異常
//		method2();//捕獲異常 
		//儘量捕獲,不要選擇丟擲,要不然開發者就刺激了
		try {
			method3();
		} catch (Exception e) {
			// 開發階段,上線的時候會被註釋掉
			e.printStackTrace();//通常用來排除錯誤
			System.out.println("執行失敗");//專案上線時給出的提示
		}
	}

	//丟擲異常:在會出錯的方法上新增程式碼 throws 異常型別
	//直接丟擲Exception也是體現了多型,因為根本不關心具體的子類型別,會把子類當做父類來看,寫出通用程式碼
	public static void method3() throws Exception{
		//接收使用者輸入的兩個整數
		int a = new Scanner(System.in).nextInt();
		int b = new Scanner(System.in).nextInt();
		//做除法運算
		System.out.println(a/b);
	}

	//1、捕獲異常 try{有可能發生異常的程式碼}catch(異常型別 異常名){解決方案}
	private static void method2() {
		try {
			//接收使用者輸入的兩個整數
			int a = new Scanner(System.in).nextInt();
			int b = new Scanner(System.in).nextInt();
			//做除法運算
			System.out.println(a/b);			
		} catch (Exception e) {//2、當try裡的程式碼發生異常時,會給出捕獲方案
			//Exception就是多型的體現,好處是不關心具體的子類型別,會把子類當做父類來處理,寫出通用程式碼
			System.out.println("請輸入正整數");
		}
	}
	//暴露異常
	public static void method() {
		//接收使用者輸入的兩個整數
		int a = new Scanner(System.in).nextInt();
		int b = new Scanner(System.in).nextInt();
		//做除法運算
		System.out.println(a/b);
	}
}


訪問控制符(背過就可以)

用來控制一個類,或者類中的成員的訪問範圍。
在這裡插入圖片描述

多型自我測試的答案

package cn.tedu.muiti;

/*
 * 自己測試練習:
 * 	--父類 --Teacher
 * 	--子類 --Student
 * 	--建立多型測試
 * 	--成員變數,成員方法,靜態資源
 */

public class MyTest {
	public static void main(String[] args) {
		//建立多型物件測試
		Teacher t = new Student();
		
		System.out.println(t.age);//30 --父類
		Teacher.hei();//180老師 --父類
		System.out.println(t.name);//tea --父類
		
		t.study();//正在做題 --子類
		//只有重寫的方法才可以執行看右邊
		
		//如果,你非要用 子類的特有功能,多型物件不可能!!此時,只能建立子類物件。
//		t.name//報錯,因為t是多型物件,只能使用父類的功能,對於子類特有功能,多型物件無能為力
		//方法一:建立子類物件 -- 建議使用
		Student s = new Student();
		System.out.println(s.name);
		
		//方法二:向下轉型 -- 多型叫做向上轉型 -- 不建議使用
		Student s2 = (Student) t;//右側的t是父類 型別,給左側的子類型別 s2賦值時,--需要強轉
		System.out.println(s2.name);
	}
}
//Teacher類
class Teacher{
	//成員變數
	int age = 30;
	//靜態成員變數
	static String name = "tea";
	//方法
	public void study() {
		System.out.println("正在講課");
	}
	//靜態方法
	static public void hei() {
		System.out.println("180老師");
	}
}

//Student類
class Student extends Teacher{
	//成員變數
	int age = 18;
	//靜態成員變數
	static String name = "stu";
	//方法
	public void study() {
		System.out.println("正在做題");
	}
	//靜態方法
	static public void hei() {
		System.out.println("160學生");
	}
}



涉及到向上轉型和向下轉型!!!

向上轉型和向下轉型

	在JAVA中,繼承是一個重要的特徵,通過extends關鍵字,子類可以複用父類的功能,如果父類不能滿足當前子類的需求,則子類可以重寫父類中的方法來加以擴充套件;

	在應用中就存在著兩種轉型方式,分別是:向上轉型和向下轉型。

比如:父類Parent,子類Child

向上轉型:

  父類的引用指向子類物件Parent p=new Child();
   說明:向上轉型時,子類物件當成父類物件,只能呼叫父類的功能,如果子類重寫了父類的方法就根據這個引用指向呼叫子類重寫方法。

向下轉型(較少):
子類的引用的指向子類物件,過程中必須要採取到強制轉型

Parent  p = new Child();//向上轉型,此時,p是Parent型別;
Child c = (Child)p;//此時,把Parent型別的p轉成小型別Child
//其實,相當於建立了一個子類物件一樣,可以用父類的,也可以用自己的

說明:向下轉型時,是為了方便使用子類的特殊方法,也就是說當子類方法做了功能拓展,就可以直接使用子類功能。

向下轉型不建議使用,還不如直接建立子類物件

【下篇預告】

抽象類
介面