實驗三 面向對象(下)
實驗3-1 類的繼承
一、實驗描述
1、 考核知識點
名稱:類的繼承
2、 練習目標
- 了解類繼承的意義和作用
- 掌握如何實現類的繼承
3、 需求分析
在程序中,繼承描述的是事物之間的所屬關系,通過繼承可以使多種事物之間形成一種關系體系。
為了讓初學者熟悉類的繼承,本實驗將演示類的繼承並編寫測試類驗證子類是否擁有父類的可繼承成員。
4、 設計思路(實現原理)
1)設計兩個類Student和Teacher
2)抽取兩個類共同的內容(如:吃飯、睡覺)封裝到一個類Person中,各自特有的部分保留在各自類中。
3)讓學生類繼承Person類,老師類也繼承Person。
4)編寫測試類Example01,測試Student類和Teacher是否繼承了Person類的成員。
二、實驗實現
1、抽取父類Person,實現繼承關系,代碼如下:
class Person{
int times;
void speak(){
System.out.println("我每天吃"+times+"次飯");
}
}
class Teacher extends Person{
String teacher="老師";
void speakt(){
System.out.println("我是"+teacher);
}
}
class Student extends Person{
String student="學生";
void speaks(){
System.out.println("我是"+student);
}
}
2、定義測試類Example01,代碼如下:
public class Example301 {
public static void main(String[] args) {
Student stu=new Student();
Teacher t=new Teacher();
stu.times=3;
stu.speaks();
stu.speak();
t.times=2;
t.speakt();
t.speak();
}
}
運行結果如圖3-1所示。
圖3-1 運行結果
三、實驗總結
1、在Java中,多個類可以繼承一個父類,但是一個類不能直接繼承多個類,一個類只能有一個直接父類。
2、父類是由子類不斷抽取而來的,不斷地抽取就形成了體系結構,這個結構稱為繼承體系結構。
3、子類在繼承父類的時候,會自動擁有父類所有的成員。
4、繼承的好處是划分了類的層次性,實現了代碼重用、擴展了程序功能。
實驗3-2 方法的重寫
一、實驗描述
1、 考核知識點
名稱:方法的重寫
2、 練習目標
- 了解方法重寫的意義和作用
- 掌握如何進行方法重寫
3、 需求分析
在繼承關系中,子類會自動繼承父類中定義的方法,但有時在子類中需要對繼承的方法進行一些
修改,即對父類的方法進行重寫。為了讓初學者掌握方法的重寫,本實驗將編寫一個類NewPhone,該類繼承Phone類並對Phone類的call()方法進行重寫。
4、 設計思路(實現原理)
1)定義一個類Phone,編寫方法call(),表示打電話功能
2)定義一個Phone的子類NewPhone,重寫父類call()方法,讓它除了打電話功能外還具有開啟語言和關閉語言功能。
3)編寫一個測試類Example02,分別調用重寫前和重寫后的call()方法
二、實驗實現
1、定義Phone及其子類NewPhone,子類對父類中的call()方法重寫,代碼如下:
class Phone{
void call(){
System.out.println("可以打電話");
}
}
class NewPhone extends Phone{
void call(){
super.call();
System.out.println("開啟語音");
System.out.println("關閉語音");
}
}
2、定義測試類Example02,代碼如下:
public class Example402 {
/**
* @param args
*/
public static void main(String[] args) {
// TODO Auto-generated method stub
System.out.println("重寫之前:");
Phone phone=new Phone();
phone.call();
System.out.println("重寫之后:");
NewPhone n=new NewPhone();
n.call();
}
}
運行結果如圖3-2所示
圖3-2 運行結果
三、實驗總結
1、子類中需要對繼承自父類的方法進行一些修改,這時就用到方法重寫。
2、在子類中重寫的方法需要和父類被重寫的方法具有相同的方法名、參數列表以及返回值類型。
3、子類方法的訪問修飾權限不能小於父類的。
4、重寫的主要優點是能夠定義子類特有的特征。
實驗3-3 super訪問父類成員變量
一、實驗描述
1、 考核知識點
名稱:super關鍵字
2、 練習目標
- 掌握使用super關鍵字訪問父類成員變量
3、 需求分析
子類可以繼承父類的非私有成員變量,如果在子類中修改了繼承自父類的成員變量的值,再想要訪問父類的該成員變量時,可以通過super.成員變量來實現。為了讓初學者熟悉super關鍵字的用法,本實驗將分別設計Fu類及其子類Zi,並在Zi類的方法中使用super關鍵字訪問Fu類的成員變量。
4、 設計思路(實現原理)
1)編寫一個Fu類,在類中定義無參構造和一個初始值為20的num成員變量。
2)Zi類繼承Fu類,在子類中對num值進行了修改,同時在子類中定義無參構造和一個無返回值的method()方法,method()方法中使用super關鍵字調用了Fu類的num成員變量。
3)定義測試類Example03。
二、實驗實現
1、編寫Fu類及其子類Zi,在Zi類中使用super關鍵字調用Fu類成員變量,代碼如下
class Fu{
int num=20;
public Fu(){
}
}
class Zi extends Fu{
int num=10;
public Zi(){
}
public void method(){
System.out.println(super.num);
}
}
2、定義測試類Example03,代碼如下:
public class Example403 {
/**
* @param args
*/
public static void main(String[] args) {
// TODO Auto-generated method stub
Zi z=new Zi();
z.method();
}運行結果如圖3-3所示。
圖3-3 運行結果
三、實驗總結
1、使用super關鍵字調用父類的成員方法。具體格式如下:
super.成員變量
2、被調用的父類成員變量,必須是非private的。
實驗3-4 super訪問父類成員方法
一、實驗描述
1、 考核知識點
名稱:super關鍵字
2、 練習目標
- 掌握使用super關鍵字訪問父類成員方法
3、 需求分析
子類重寫父類的方法后,子類對象將無法訪問父類被重寫的方法,為了解決這個問題,在Java中專門提供了一個super關鍵字用於訪問父類的成員。為了讓初學者熟悉super關鍵字的用法,本實驗將分別設計Fu類及其子類Zi,在Zi類的方法中使用super關鍵字訪問Fu類的成員方法。
4、 設計思路(實現原理)
1)編寫一個Fu類,在類中定義無參構造和一個無返回值的show()方法。
2)Zi類繼承Fu類,子類中定義無參構造和一個無返回值的method()方法,method()方法中使用super關鍵字調用了Fu類的show()方法。
3)定義測試類Example04。
二、實驗實現
1、編寫Fu類及其子類Zi,在Zi類中使用super關鍵字調用Fu類成員方法,代碼如下:
class Fu{
public Fu(){
}
public void show(){
System.out.println("父類的方法被調用");
}
}
class Zi extends Fu{
public Zi(){
}
public void method(){
super.show();
}
}
2、定義測試類Example04,代碼如下:
public class Example404 {
/**
* @param args
*/
public static void main(String[] args) {
// TODO Auto-generated method stub
Zi z=new Zi();
z.method();
}
}
運行結果如圖3-4所示。
圖3-4 運行結果
三、實驗總結
1、使用super關鍵字調用父類的成員方法。具體格式如下:
super.成員方法([參數1,參數2…])
2、被調用的父類成員方法,必須是非private的。
實驗3-5 super訪問父類構造方法
一、實驗描述
1、 考核知識點
名稱:super關鍵字
2、 練習目標
- 掌握如何在子類構造方法中使用super關鍵字訪問父類構造方法
3、 需求分析
在子類的構造方法中一定會調用父類的某個構造方法,如果想指定調用類父類中的哪個構造方法,可以使用super關鍵字來實現。為了讓初學者掌握super關鍵字的用法,本實驗將分別設計Fu類及其子類Zi,在Zi類的構造方法中使用super關鍵字訪問Fu類的構造方法。
4、 設計思路(實現原理)
1)編寫一個Fu類,在類中定義無參構造。
2)Zi類繼承Fu類,子類中也定義無參構造方法,在構造方法中使用super關鍵字調用Fu類的構造方法。
3)定義測試類Example05。
二、實驗實現
1、編寫Fu類及其子類Zi,在Zi類構造中使用super關鍵字調用Fu類構造方法,代碼如下:
class Fu{
public Fu(){
System.out.println("父類構造方法被訪問");
}
}
class Zi extends Fu{
public Zi(){
super();
}
}
2、定義測試類Example05,代碼如下:
public class Example405{
/**
* @param args
*/
public static void main(String[] args) {
// TODO Auto-generated method stub
Zi z=new Zi();
}
運行結果如圖3-5所示。
圖3-5 運行結果
三、實驗總結
1、通過super調用父類構造方法的代碼必須位於子類構造方法的第一行,並且只能出現一次。
2、在子類的構造方法中通過super指定調用父類的哪個構造方法,如果沒有指定,在實例化子類對象時,會自動調用父類無參的構造方法。
3、被調用的父類構造方法,必須是非private的。
實驗3-6 final修飾類
一、實驗描述
1、 考核知識點
名稱:final關鍵字
2、 練習目標
- 了解final關鍵字修飾類的特點
- 掌握final關鍵字修飾類的用法
3、 需求分析
Java中的類被final關鍵字修飾后,該類將不可以被繼承,也就是不能夠派生子類。為了讓初學者熟悉final關鍵字修飾類的用法,本實驗將分別設計兩個類,一個是使用final關鍵字修飾的Fu類,另一個是繼承Fu類的Zi類,驗證final關鍵字修飾的類是否能被繼承。
4、 設計思路(實現原理)
1)編寫一個final關鍵字修飾的Fu類,類體可以為空
2)編寫Zi類,Zi類繼承於Fu類,類體可以為空
3)定義測試類Example06。
二、實驗實現
1、編寫final修飾的Fu類,Zi類繼承Fu類,代碼如下:
final class Fu{
}
class Zi extends Fu{
}
2、定義測試類Example06,代碼如下:
public class Example406{
/**
* @param args
*/
public static void main(String[] args) {
// TODO Auto-generated method stub
Zi z=new Zi();
}
}
運行結果如圖3-6所示。
圖3-6 運行結果
三、實驗總結
在Java中,被final關鍵字修飾的類為最終類,不能被其它類繼承。
實驗3-7 final修飾方法
一、實驗描述
1、 考核知識點
名稱:final關鍵字
2、 練習目標
- 掌握使用final關鍵字修飾方法
3、 需求分析
子類可以繼承父類的成員方法,並在必要時對方法進行重寫,增加了方法的擴展的同時也打破了方法的封裝,如果我們希望父類中的某些方法不能被重寫,這時就可以使用final關鍵字來修飾。為了讓初學者掌握使用final關鍵字修飾方法,本實驗將分別設計兩個類,一個是Fu類,其中定義了final修飾的show()方法,另一個是繼承Fu類的Zi類,在Zi類中對show()方法進行重寫。
4、 設計思路(實現原理)
1)編寫一個Fu類,類中定義final修飾的show()方法。
2)編寫Zi類,Zi類繼承於Fu類,在Zi類中對show()方法進行重寫
3)定義測試類Example07,創建Zi類對象,並調用Zi類show()方法。
二、實驗實現
1、編寫Fu類及其子類Zi類,在Zi類中對show()方法重寫,代碼如下:
class Fu{
public final void show(){
System.out.println("父類方法被訪問");
}
}
class Zi extends Fu{
public void show(){
}
2、定義測試類Example07,代碼如下:
public class Example407 {
/**
* @param args
*/
public static void main(String[] args) {
// TODO Auto-generated method stub
Zi z=new Zi();
z.show();
}
運行結果如圖3-7所示。
圖3-7 運行結果
三、實驗總結
當一個類的方法被final關鍵字修飾后,這個類的子類將不能重寫該方法。
實驗3-8 final修飾局部變量
一、實驗描述
1、 考核知識點
名稱:final關鍵字
2、 練習目標
- 掌握使用final關鍵字修飾局部變量
3、 需求分析
Java中被final修飾的變量為常量,它只能被賦值一次,也就是說final修飾的變量一旦被賦值,其值不能改變。為了讓初學者掌握使用final關鍵字修飾局部變量,本實驗將在類的方法中定義一個final修飾的局部變量,並試着對該變量重新賦值。
4、 設計思路(實現原理)
1)編寫一個Example08類,類中定義類一個final修飾的局部變量age,為其賦初始值為18。
2)為age重新賦值為20。
二、實驗實現
1、編寫類Example08,代碼如下
public class Example408{
/**
* @param args
*/
public static void main(String[] args) {
// TODO Auto-generated method stub
final int age=20;
int age=18;
System.out.println(age);
}
}
編譯錯誤,如圖3-8所示。
圖3-8 錯誤提示
三、實驗總結
final修飾的變量表示常量,一經定義就不能重新賦值。
實驗3-9 final修飾成員變量
一、實驗描述
1、 考核知識點
名稱:final關鍵字
2、 練習目標
- 掌握使用final關鍵字修飾成員變量
3、 需求分析
在Java中,final修飾的變量表示常量,一經定義就不能重新賦值。為了讓初學者熟悉final修飾變量的情況,本實驗將使用final關鍵字修飾成員變量,觀察其是否能夠再次賦值。
4、 設計思路(實現原理)
1)編寫一個Fu類,父類中定義一個變量X,並用final關鍵字修飾變量。
2)編寫Zi類,Zi類繼承於Fu類,在子類中對常量再賦新值。
3)定義測試類Example09,觀察運行結果。
二、實驗實現
1、編寫Fu類及其子類Zi類,在Zi類中對X再賦值,代碼如下:
class Fu{
final int X=50;
}
class Zi extends Fu{
int X=20;
}
2、定義測試類Example09,代碼如下:
public class Example409 {
/**
* @param args
*/
public static void main(String[] args) {
// TODO Auto-generated method stub
Zi zi=new Zi();
System.out.println(X);
}
}
編譯錯誤,結果如圖3-9所示。
圖3-9 錯誤提示
三、實驗總結
在本實驗中Zi類中對變量X再次賦值,運行結果報錯。這是因為Java中被final修飾的變量為常量,它只能被賦值一次,也就是說final修飾的變量一旦被賦值,其值不能改變。如果再次對該變量進行賦值,則程序會在編譯時報錯。
實驗3-10 接口的實現
一、實驗描述
1、 考核知識點
名 稱:接口
2、 練習目標
- 掌握如何實現接口
3、 需求分析
由於接口中的方法都是抽象方法,因此不能通過實例化對象的方式來調用接口中的方法。此時需要定義一個類,並使用implements關鍵字實現接口中所有的方法。為了上初學者掌握如何實現接口,本實驗將設計一個類,使用關鍵字implements實現Inter接口中的方法。
4、 設計思路(實現原理)
1)設計名為Inter的接口,接口中定義一個初始值為20的num常量和method()抽象方法。
2)編寫Inter接口的實現類InterImpl,使用implements關鍵字實現接口中的方法。
3)編寫測試類Example10,測試類中對接口的實現類進行實例化,並調用接口中的方法。
二、實驗實現
1、編寫接口Inter,InterImpl類使用implements實現了接口,代碼如下:
interface Inter{
int num=20;
abstract void method();
}
class InterImpl implements Inter{
public void method() {
System.out.println("定義的num是"+num);
}
2、定義測試類Example10,代碼如下:
public class shiyan410 {
/**
* @param args
*/
public static void main(String[] args) {
// TODO Auto-generated method stub
InterImpl I=new InterImpl();
I.method();
}
}
運行結果如圖3-10所示。
圖3-10 運行結果
三、實驗總結
1、接口使用interface關鍵字來定義。
2、接口沒有構造方法,接口中的變量缺省都是使用public static final修飾的,即全局常量,接口中的方法都是public abstract修飾的,即抽象方法。
3、定義一個類,並使用implements關鍵字實現接口中的方法,一個類可以實現多個接口。
4、由於接口中的方法都是抽象方法,因此不能直接通過實例化對象的方式來調用接口中的方法,需要在類實現接口后借助類來間接實例化。
實驗3-11 接口的繼承
一、實驗描述
1、 考核知識點
名 稱:接口的繼承與多實現
2、 練習目標
- 掌握接口繼承的方式及其特點
3、 需求分析
在程序中,可以定義一個接口使用extends關鍵字去繼承另一個接口。為了加深初學者對結果的理解,本實驗將演示接口與接口、類與接口的繼承和實現關系。
4、 設計思路(實現原理)
1)設計接口Phone代表傳統手機,在接口中定義receiveMessages()和call()抽象方法。
2)設計接口SmartPhone代表智能手機,在接口中定義faceTime()方法,並使用extends關鍵字繼承Phone接口,使其具有Phone接口的所有功能。
3)設計類MIPhone表示小米手機,類中定義useMIUI()方法,並實現SmartPhone接口的所有方法。
4)編寫測試類Example11,測試類中對MIPhone進行實例化,並訪問小米手機具有的各種功能。
二、實驗實現
1、編寫接口Phone和SmartPhone、類MIPhone。代碼如下:
public interface Phone {
String namePhone="傳統手機";
void call();
}
public interface SmartPhone extends Phone {
String nameSmartPhone="智能手機";
void faceTime();
}
class MIPhone implements SmartPhone{
String nameMI="小米手機";
public void call(){
System.out.println("能打電話");
}
void receiveMessage(){
System.out.println("收發信息");
}
public void faceTime(){
System.out.println("能視頻");
}
public void useMIUI() {
}
{
call();
receiveMessage();
faceTime();
}
}
運行結果如圖3-11所示。
圖3-11 運行結果
三、實驗總結
接口與接口之間的繼承關系,可以是單繼承,也可以是多繼承;一個接口可以通過extends關鍵字繼承多個接口,接口之間用逗號隔開。
實驗3-12 Object類
一、實驗描述
1、 考核知識點
名 稱:Object類
2、 練習目標
- 了解什么是Object類
- 掌握Object類中常用方法的使用
3、 需求分析
在JDK中提供了一個Object類,它是所有類的父類,即每個類都直接或間接繼承自該類。Object類自身的equals()方法比較的是內存地址值,相當於“==”,但是在實際開發中我們很少比較兩個對象的地址值,這時候常常就需要根據自身需求來重寫equals()方法。為了方便初學者學習Object類,本實驗將演示如何重寫equals()方法。
4、 設計思路(實現原理)
1)設計Student類,定義sid變量表示學號,重寫equals()方法,判斷進行比較的兩個學生對象學號是否相同,相同即為同一個學生,否則不是。
2)編寫測試類Example12,創建兩個Student的對象Lily和Lucy,並分別調用setter方法為學號賦值,最后通過打印語句,輸出這兩個對象通過“==”和重寫后的equals()方法比較后的結果。
二、實驗實現
1、編寫Student類,重寫equals()方法。代碼如下:
class Student{
long sid;
public boolean equals(Object a,Object b){
if(a==b)
return true;
else return false;
}
}
2、定義測試類Example12,為學號賦值,並打印使用“==”和重寫equals()方法的比較結果,代碼如下:
public class Example412 {
/**
* @param args
*/
public static void main(String[] args) {
// TODO Auto-generated method stub
Student Lily=new Student();
Student Lucy=new Student();
Lily.sid= 1667111141;
Lucy.sid=1663104630;
System.out.println(Lily.equals(Lily, Lucy));
}
}
運行結果如圖3-12所示。
圖3-12 運行結果
三、實驗總結
1、Object類是Java中所有類的父類,每個類都直接或間接繼承自該類。
2、Object類中的equals()方法比較的是內存地址值,和“==”比較結果一致。底層代碼如下:
public boolean equals(Object obj) {
return (this == obj);
}
實際開發中很少比較內存地址值,所以我們常常會根據自身需求重寫equals()方法。
實驗3-13 多態的作用
一、實驗描述
1、 考核知識點
名 稱:多態
2、 練習目標
- 了解多態的概念、多態的好處和弊端
- 掌握如何實現多態
3、 需求分析
在Java中為了實現多態,允許使用一個父類類型的變量來引用一個子類類型的對象,根據被引用子類對象特征的不同,得到不同的運行結果。多態提高代碼了的擴展性和可維護性。為了幫助初學者掌握如何實現多態,本實驗將實現一個多態程序來演示如何實現多態。
4、 設計思路(實現原理)
1)編寫Animal接口,接口中定義sleep()方法。
2)Cat類實現Animal接口的方法,並定義另一個方法catchMouse()
3)編寫測試類Example13,使Cat對象指向父類Animal的引用 ,並通過該引用調用sleep()方法。
二、實驗實現
1、編寫Animal接口及其實現類Cat。代碼如下:
interface Animal{
public void sleep();
}
class Cat implements Animal{
public void sleep(){
System.out.println("在睡覺");
}
public void catchMouse(){
System.out.println("捉耗子");
}
}
2、定義測試類Example13,Cat對象指向Animal引用,並使用父類Animal引用調用sleep()方法。代碼如下:
public class Example413 {
public static void main(String[] args) {
Animal cat=new Cat();
cat.sleep();
}
}
運行結果如圖3-13所示。
圖3-13 運行結果
三、實驗總結
1、多態是指對象在不同時刻表現出來的不同狀態,在Java中,允許使用一個父類類型的變量來引用一個子類類型的對象。
2、多態的前提:
(1) 要有繼承關系。
(2) 要有方法重寫。
(3) 要有父類引用指向子類對象。
3、多態的好處是提高代碼的擴展性和可維護性。
4、多態的弊端是父類或者接口只能調用自己具備的成員,不能訪問子類特有的成員。
實驗3-14 對象的類型轉換
一、實驗描述
1、 考核知識點
名 稱:對象的類型轉換
2、 練習目標
- 掌握如何實現對象的類型轉換
3、 需求分析
在多態的學習中,涉及到將子類對象當做父類類型使用的情況,這時進行強制類型轉換可能會出現出錯。為了讓初學者熟悉對象的類型轉換,本實驗將演示一個子類與父類之間類型轉換過程中出現的錯誤。
編寫一個接口Animal,接口中定義sleep()方法,編寫兩個類Cat和Pig分別實現接口,再編寫一個測試類Example14實現對象的類型轉換。
4、 設計思路(實現原理)
1)編寫Animal接口,接口中定義sleep()方法。
2)Cat類和Pig類分別實現Animal接口的方法
3)編寫測試類Example14對對象的類型進行轉換,使Cat向上轉型為Animal類型,然后再讓Animal類型轉換為Pig類型。
二、實驗實現
1、編寫Animal接口及其實現類Cat。代碼如下:
interface Animal{
public void sleep();
}
class Pig implements Animal{
public void sleep(){
System.out.println("豬在睡覺");
}
}
class Cat implements Animal{
public void sleep(){
System.out.println("貓在睡覺");
}
}
2、定義測試類Example14,Cat對象指向Animal引用,並使用父類Animal引用調用sleep()方法。代碼如下:
public class Example413 {
public static void main(String[] args) {
Animal cat=new Cat();
cat.sleep();
Pig pig=(Pig) new Animal();
pig.sleep();
}
}
運行結果如圖3-14所示。
圖3-14 錯誤提示
三、實驗總結
1、向下類型轉換時,需要注意被轉換對象的真實類型是否和需要轉換的對象類型相同,否則容易報類型轉換異常(java.lang.ClassCastException)。
2、Java提供了一個關鍵字instanceof,它可以判斷一個對象是否為某個類(或接口)的實例或者子類實例,語法格式如下:
對象(或者對象引用變量) instanceof 類(或接口)
3、進行向上類型轉換,子類對象當做父類類型使用時,不能通過父類變量去調用子類中某些方法,否則會拋出編譯異常。
實驗3-15 匿名內部類
一、實驗描述
1、 考核知識點
名 稱:匿名內部類
2、 練習目標
- 了解什么是匿名內部類
- 掌握如何使用匿名內部類
3、 需求分析
在學習接口時,如果方法的參數被定義為一個接口類型,那么就需要定義一個類來實現接口。除此之外,還可以使用匿名內部類來實現接口。為了讓初學者能更好地理解什么是匿名內部類,本實驗將演示如何實現一個匿名內部類。
4、 設計思路(實現原理)
1)設計一個Inter接口,接口中定義show()和method()方法。
2)設計一個Outer類,在類的function()方法中使用匿名內部類實現Inter接口並實例化,並調用show()和method()方法。
3)最后編寫一個測試類Example15,創建Outer的對象並調用function()方法。
二、實驗實現
1、編寫Inter接口及Outer類,使用匿名內部類實現接口並創建對象。代碼如下:
interface Inter{
public void show();
public void method();
}
2、定義測試類Example15。代碼如下:
public class Example41 {
/**
* @param args
*/
public static void main(String[] args) {
class Outer implements Inter{
public void show() {
System.out.println("show方法");
}
public void method() {
System.out.println("method方法");
}
}
function(new Outer());
}
static public void function(Inter i){
i.show();
i.method();
}
}
運行結果如圖3-15所示。
圖3-15 運行結果
三、實驗總結
1、匿名內部類的格式,具體如下:
new 父類(參數列表) 或 父接口(){
//匿名內部類實現部分
}
2、匿名內部類是實現接口的一種簡便寫法,在程序中不一定非要使用匿名內部類。
3、什么時候使用匿名內部類:通常在使用方法是接口類型參數,並該接口中的方法不超過三個時,可以將匿名內部類作為參數傳遞。
4、內部類:
(1) 將一個類B定義在另一個類A的里面,那么B類就稱為內部類(嵌套類),內部類定義在成員位置上。
(2) 內部類可以直接訪問外部類中的成員,包括私有成員,而外部類要訪問內部類中的成員必須要建立內部類的對象。
實驗3-16 try...catch語句
一、實驗描述
1、 考核知識點
名 稱:try...catch和finally
2、 練習目標
- 掌握如何使用try...catch語句進行異常處理
3、 需求分析
Java中提供了一種對異常進行處理的方式——異常捕獲,異常捕獲通常使用try…catch語句。為了讓初學者熟悉try…catch語句,本實驗將演示如何使用try...catch語句處理遍歷時可能出現的數組角標越界異常。
4、 設計思路(實現原理)
1) 編寫測試類Example16,
2) 在類Example16中定義名為arr的int類型一維數組,遍歷數組輸出每次遍歷出的值,結束輸出“over”。
2)使用try...catch語句處理遍歷時可能出現的數組角標越界異常,如果出現異常輸出“角標越界”。
二、實驗實現
package shiyan416;
public class Example416 {
/**
* @param args
*/
public static void main(String[] args) {
// TODO Auto-generated method stub
try{
int[]arr=new int[4];
arr[0]=0;
arr[1]=1;
arr[2]=2;
arr[3]=4;
arr[4]=5;
int i;
for(i=0;i<5;i++)
System.out.println(arr[i]);
System.out.println("over!");
}catch(Exception e){
System.out.println(e.getMessage()+"角標越界");
}
}
}
運行結果如圖3-16所示。
圖3-16 運行結果
三、實驗總結
1、try代碼塊中編寫可能發生異常的Java語句,catch代碼塊中編寫針對異常進行處理的代碼。在try代碼塊中,發生異常語句后面的代碼是不會被執行的。
2、可能發生多個異常時,可以使用多個try...catch或者用一個try多個catch。
3、 Throwable:是異常體系的超類.
|--Error 重大的錯誤,這個問題發生后,一般我們處理不了,一般不處理,而是要程序進行修正 。(內存溢出)
|--Exception 可以處理的問題,這個問題需要我們編寫針對性的代碼進行處理。(異常處理)
實驗3-17 finally語句
一、實驗描述
1、 考核知識點
名 稱:try...catch和finally
2、 練習目標
- 掌握如何使用finally語句
3、 需求分析
在程序中,有時候我們希望有些語句無論程序是否發生異常都要執行,這時就可以在try…catch語句后,加一個finally代碼塊。為了讓初學者熟悉finally代碼塊,本實驗將演示如何使用finally語句來保證不論是否異常都輸出一句話。
4、 設計思路(實現原理)
1) 編寫Example17類
2) 在main方法中使用try…catch…finally…語句,其中try語句塊中編寫可能發生異常的語句10/0,如果不異常輸出“程序繼續”,如果異常在catch語句塊中會輸出“出異常類”
3) 在finally語句塊中輸出“釋放資源”,保證保證不論是否異常一定輸出此語句
二、實驗實現
package shiyan416;
public class Example416 {
/**
* @param args
* @return
*/
public static void main(String[] args) {
// TODO Auto-generated method stub
try{
int result= Divide(10,0);
System.out.println(result);
}catch(Exception e){
System.out.println("拋出的異常是"+e.getMessage());
return;
}
finally{
System.out.println("進入finally");
}
System.out.println("程序繼續執行....");
}
private static int Divide(int x, int y) {
// TODO Auto-generated method stub
int result;
result=x/y;
return result;
}
}
運行結果如圖3-17所示。
圖3-17 錯誤提示
三、實驗總結
無論是否發生異常,finally代碼塊是一定會執行的。但是需要注意的是,finally中的代碼塊在一種情況下不會執行,那就是在執行到finally語句之前執行了System.exit(0)語句。
實驗3-18 throws關鍵字
一、實驗描述
1、 考核知識點
名 稱:throws關鍵字
2、 練習目標
- 掌握如何使用throws關鍵字
3、 需求分析
Java中允許在方法的后面使用throws關鍵字對外聲明該方法有可能發生的異常,這樣調用者在調用方法時,就明確地知道該方法有異常,並且必須在程序中對異常進行處理,否則編譯無法通過。為了讓初學者熟悉throws關鍵字,本實驗將演示如何使用throws關鍵字。
4、 設計思路(實現原理)
1) 編寫一個類Example18
2) 在該類中定義方法div()用於進行除法運算,運算前對被除數進行判斷,如果等於0,使用throws拋出異常對象,否則進行正常的除法運算。
3) 由於throw拋出了非運行時異常,為了保證編譯通過,我們需要在方法名后面使用throws聲明拋出異常類。
2)在main方法中調用div()方法,並通過try…catch…語句處理拋出的異常。
二、實驗實現
package shiyan416;
import javax.xml.ws.handler.MessageContext;
public class Example416 {
/**
* @param args
* @return
*/
public static void main(String[] args) {
// TODO Auto-generated method stub
try{
int result= Divide(10,0);
System.out.println(result);
}catch(Exception e){
e.printStackTrace();
}
}
private static int Divide(int x, int y)throws Exception{
// TODO Auto-generated method stub
if(y==0)
{
System.out.println("除數為0");
}
int result;
result=x/y;
return result;
}
}
運行結果如圖3-18所示。
圖3-18 運行結果
三、實驗總結
1、throws關鍵字聲明拋出異常的語法格式如下:
修飾符 返回值類型 方法名([參數1,參數2.....])throws ExceptionType1[,ExceptionType2.....]{
}
2、throws關鍵字需要寫在方法聲明的后面,throws后面需要聲明方法中發生異常的類型,通常將這種做法稱為方法聲明拋出一個異常。
實驗3-19 自定義異常
一、實驗描述
1、 考核知識點
名 稱:自定義異常
2、 練習目標
- 掌握如何自定義異常
3、 需求分析
Java中定義的異常有限,如果想描述程序中特有的異常情況,就需要自定義異常。為了讓初學者熟悉自定義異常,本實驗將自定義一個名為MyException的異常類來演示如何自定義異常。
4、 設計思路(實現原理)
1)自定義名為MyException的異常類,繼承自Exception類。
2)在Example19類中進行除法運算,判斷當除數為零時,拋出自定義的異常類
3)在main()方法中處理異常。
二、實驗實現
1、編寫自定義異常類,代碼如下:
class Divide extends Exception{
public Divide(){
super();
}
public Divide(String message){
super(message);
}
}
2、拋出異常和處理異常,代碼如下:
public class Example419 {
public static void main(String[] args) {
// TODO Auto-generated method stub
try{
int result=divide(10,0);
System.out.println(result);
}catch(Divide e){
System.out.println(e.getMessage());
}
}
public static int divide(int x,int y)throws Divide{
if(y==0){
throw new Divide("被除數是0");
}
int result =x/y;
return result;
}
}
運行結果如圖3-19所示。
圖3-19 運行結果
三、實驗總結
1、在Java中允許用戶自定義異常,但自定義的異常類必須繼承自Exception或其子類。
2、throw關鍵字用於在方法中聲明拋出異常的實例對象,其語法格式如下:
throw Exception異常對象
3、main()方法中,定義了一個try…catch語句用於捕獲divide()方法拋出的異常。在調用divide()方法時由於傳入的被除數不能為零,程序會拋出一個自定義異常MyException,該異常被捕獲后最終被catch代碼塊處理,並打印出異常信息。
實驗3-20 import引入指定類
一、實驗描述
1、 考核知識點
名 稱:import語句
2、 練習目標
- 掌握如何使用import引入指定類
3、 需求分析
不同包下的類互相調用時,一般會使用import關鍵字引入包。為了方便初學者的學習,本實驗將演示如何使用import引入指定類。
4、 設計思路(實現原理)
1) 在D:\samplePackage\chapter04 文件夾下新建Student.java文件
2) 打開文件編寫Student類,類中定義int類型的變量sid,String類型的變量name和double類型的變量score,分別表示學生id,學生姓名和分數。
2)Student類定義構造器及一個evaluation()方法,該方法用於評定學生是否為三好學生,得分大於90分為三好學生,否則為普通學生。Student類編譯后位於cn.itcast.domain包下。
3)在D:\samplePackage\chapter04 文件夾下新建Example20.java文件,打開文件編寫Example20類,在main方法中使用有參構造創建Student類的對象並調用evaluation()方法
4)Example20類編譯后位於cn.itcast.example包下,在類中使用import cn.itcast.domain.Student;引入Student類。
二、實驗實現
1、編寫Student類,該類位於cn.itcast.domain包下,代碼如下所示:
package shiyan420;
public class Student {
int sid;
String name;
double score;
public Student(int s,String n,double sc){
sid=s;
name=n;
score=sc;
}
public void evalustion(){
if(score>90){
System.out.println("學號為"+sid+"的"+name+"是三好學生");
}
else System.out.println("學號為"+sid+"的"+name+"不是三好學生");
}
}
2、編寫Example20類,該類位於cn.itcast.example包下,代碼如下所示:
package shiyan414;
import shiyan420.Student;
public class Example420 {
/**
* @param args
*/
public static void main(String[] args) {
// TODO Auto-generated method stub
Student student=new Student(141,"范敏",98);
student.evalustion();
}
}
運行結果如圖3-20所示。
圖3-20 運行結果
三、實驗總結
1、當處於不同包下的類互相調用時,需要使用被調用類的完整類名,即包名加上類名。為了簡化代碼,Java中提供了import關鍵字,用於引入某個指定包下的類。
2、import通常出現在package語句之后,類定義之前。
3、當需要引入同一包下的多個類時,可以使用“import包名.*;”的方式,引入包下所有的類。