Java实验03 面向对象(下)

实验三 面向对象(下)
实验3-1 类的继承
一、实验描述
1、 考核知识点
名称:类的继承
2、 练习目标
 了解类继承的意义和作用
 掌握如何实现类的继承
3、 需求分析
在程序中,继承描述的是事物之间的所属关系,通过继承可以使多种事物之间形成一种关系体系。
为了让初学者熟悉类的继承,本实验将演示类的继承并编写测试类验证子类是否拥有父类的可继承成员。
4、 设计思路(实现原理)
1)设计两个类Student和Teacher
2)抽取两个类共同的内容(如:吃饭、睡觉)封装到一个类Person中,各自特有的部分保留在各自类中。
3)让学生类继承Person类,老师类也继承Person。
4)编写测试类Example01,测试Student类和Teacher是否继承了Person类的成员。

二、实验实现
1、抽取父类Person,实现继承关系,代码如下:

class Person{
    String name;
    int age;
    public void eat(){
        System.out.println(name + "在吃饭");
    }
    public void sleep(){
        System.out.println(name + "在睡觉");
    }
}

2、定义测试类Example01,代码如下:

package Example01;

class Person{
    String name;
    int age;
    public void eat(){
        System.out.println(name + "在吃饭");
    }
    public void sleep(){
        System.out.println(name + "在睡觉");
    }
}

class Student extends Person{
    public Student(String name,int age){
        this.name = name;
        this.age = age;
    }
    public void speak(){
        System.out.println("我叫"+this.name+"我今年"+age+"岁了,我是一个学生。");
    }
}

class Teachar extends Person{
    public Teachar(String name,int age){
        this.name = name;
        this.age = age;
    }
    public void speak(){
        System.out.println("我叫"+this.name+"我今年"+age+"岁了,我是一个老师。");
    }
}

public class Example01 {
    public static void main(String[] args) {
        Student s = new Student("小明",18);
        Teachar t = new Teachar("大明",25);
        s.speak();
        s.eat();
        s.sleep();
        t.speak();
        t.eat();
        t.sleep();
    }
}

运行结果如图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{
    public void call(){
        System.out.println("输入:1.打电话");
        Scanner in = new Scanner(System.in);
        int flag = in.nextInt();
        if(flag == 1){
            System.out.println("正在打电话");
        }
    }
}

class NewPhone extends Phone{
    public void call(){
        System.out.println("输入:1.打电话,2.开启语言功能,3.关闭语言功能");
        Scanner in = new Scanner(System.in);
        int flag = in.nextInt();
        if(flag == 1){
            System.out.println("正在打电话!");
        }
        else if(flag == 2){
            System.out.println("开启语言功能成功!");
        }
        else if(flag == 3){
            System.out.println("关闭语言功能成功!");
        }
    }
}

2、定义测试类Example02,代码如下:

package Example02;

import java.util.Scanner;

class Phone{
    public void call(){
        System.out.println("输入:1.打电话");
        Scanner in = new Scanner(System.in);
        int flag = in.nextInt();
        if(flag == 1){
            System.out.println("正在打电话");
        }
    }
}

class NewPhone extends Phone{
    public void call(){
        System.out.println("输入:1.打电话,2.开启语言功能,3.关闭语言功能");
        Scanner in = new Scanner(System.in);
        int flag = in.nextInt();
        if(flag == 1){
            System.out.println("正在打电话!");
        }
        else if(flag == 2){
            System.out.println("开启语言功能成功!");
        }
        else if(flag == 3){
            System.out.println("关闭语言功能成功!");
        }
    }
}

public class Example02 {
    public static void main(String[] args) {
        Phone p = new Phone();
        NewPhone n = new NewPhone();
        System.out.println("Phone类测试");
        p.call();
        System.out.println("NewPhon类测试");
        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{

    public Zi() {}
    int num = 10;
    public void method(){
        System.out.println(super.num);
    }
}

2、定义测试类Example03,代码如下:

package Example03;

class Fu{

    int num = 20;
    public Fu(){}
}

class Zi extends Fu{

    public Zi() {}
    int num = 10;
    public void method(){
        System.out.println("super.num = "+super.num);
    }
}

public class Example03 {
    public static void main(String[] args) {
        Fu f = new Fu();
        Zi z = new Zi();
        System.out.println("父类中的num = "+f.num);
        System.out.println("子类中的num = "+z.num);
        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("执行了Fu类show()方法");
    }
}

class Zi extends Fu {

    public Zi() {}
    public void method(){
        System.out.println("调用了super.show()方法");
        super.show();
    }
}

2、定义测试类Example04,代码如下:

package Example04;

class Fu{
    public Fu(){}
    public void show(){
        System.out.println("执行了Fu类show()方法");
    }
}

class Zi extends Fu {

    public Zi() {}
    public void method(){
        System.out.println("调用了super.show()方法");
        super.show();
    }
}

public class Example04 {
    public static void main(String[] args) {
        Fu f = new Fu();
        Zi z = new Zi();
        System.out.println("调用父类中的show()方法");
        f.show();
        System.out.println("调用子类中的method()方法");
        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("调用了Fu类的构造方法。。。");
    }
}

class Zi extends Fu {

    public Zi() {
        super();
        System.out.println("调用了Zi类的构造方法。。。");
    }
}

2、定义测试类Example05,代码如下:

package Example05;

class Fu{
    public Fu(){
        System.out.println("调用了Fu类的构造方法。。。");
    }
}

class Zi extends Fu {

    public Zi() {
        super();
        System.out.println("调用了Zi类的构造方法。。。");
    }
}

public class Example05 {
    public static void main(String[] args) {
        System.out.println("实例化Fu对象");
        Fu f = new Fu();
        System.out.println("实例化Zi对象");
        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{
    public Fu(){
        System.out.println("调用了Fu类的构造方法。。。");
    }
}

class Zi extends Fu {

    public Zi() {
        System.out.println("调用了Zi类的构造方法。。。");
    }
}

2、定义测试类Example06,代码如下:

package Example06;

final class Fu{
    public Fu(){
        System.out.println("调用了Fu类的构造方法。。。");
    }
}

class Zi extends Fu {

    public Zi() {
        System.out.println("调用了Zi类的构造方法。。。");
    }
}

public class Example06 {
    public static void main(String[] args) {
        System.out.println("实例化Fu对象");
        Fu f = new Fu();
        System.out.println("实例化Zi对象");
        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 Fu(){
        System.out.println("调用了Fu类的构造方法。。。");
    }
    public final void show(){
        System.out.println("执行了Fu类show()方法");
    }
}

class Zi extends Fu {
    public Zi() {
        System.out.println("调用了Zi类的构造方法。。。");
    }
    public void show(){
        System.out.println("执行了Zi类show()方法");
    }
}

2、定义测试类Example07,代码如下:

package Example07;

class Fu{
    public Fu(){
        System.out.println("调用了Fu类的构造方法。。。");
    }
    public final void show(){
        System.out.println("执行了Fu类show()方法");
    }
}

class Zi extends Fu {
    public Zi() {
        System.out.println("调用了Zi类的构造方法。。。");
    }
    public void show(){
        System.out.println("执行了Zi类show()方法");
    }
}

public class Example07 {
    public static void main(String[] args) {
        System.out.println("实例化Fu对象");
        Fu f = new Fu();
        System.out.println("实例化Zi对象");
        Zi z = new Zi();
        System.out.println("调用Zi类的show()方法");
        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,代码如下

package Example08;

public class Example08{
    final static int age = 18;
    public static void main(String[] args) {
        age = 20;
    }
}

编译错误,如图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{
    public final int x = 12;
}

class Zi extends Fu {
    public void show(){
        x = 11;
        System.out.println(x);
    }
}

2、定义测试类Example09,代码如下:

package Example09;

class Fu{
    public final int x = 12;
}

class Zi extends Fu {
    public void show(){
        x = 11;
        System.out.println(x);
    }
}

public class Example09 {
    public static void main(String[] args) {
        Fu f = new Fu();
        Zi z = new Zi();
        z.show();
    }
}

编译错误,结果如图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;
    void method();
}

class InterImpl implements Inter{

    public void method() {
        System.out.println("调用了在InterImpl类里实现的Inter接口里的method()方法");
    }
}

2、定义测试类Example10,代码如下:

package Example10;

interface Inter{
    int num = 20;
    void method();
}

class InterImpl implements Inter{

    public void method() {
        System.out.println("调用了在InterImpl类里实现的Inter接口里的method()方法");
    }
}

public class Example10 {
    public static void main(String[] args) {
        InterImpl i = new InterImpl();
        System.out.println("Inter里的num = " + i.num);
        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。代码如下:

package Example11;

interface Phone{
    void receiveMessages();
    void call();
}

interface SmartPhone extends Phone {
    void faceTime();
}

class MIPhone implements SmartPhone{
    public void useMIUI(){
        System.out.println("调用了useMIUI()方法。。。");
    }
    public void receiveMessages(){
        System.out.println("调用了receiveMessages()方法。。。");
    }
    public void call(){
        System.out.println("调用了call()方法。。。");
    }
    public void faceTime(){
        System.out.println("调用了faceTime()方法。。。");
    }
}

public class Example11 {
    public static void main(String[] args) {
        MIPhone m = new MIPhone();
        m.useMIUI();
        m.call();
        m.receiveMessages();
        m.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{
    private int sid;
    public void setter(int sid){
        this.sid = sid;
    }
    public boolean equals(Student s){
        if(this.sid == s.sid) return true;
        else return false;
    }
}

2、定义测试类Example12,为学号赋值,并打印使用“==”和重写equals()方法的比较结果,代码如下:

package Example12;

class Student{
    private int sid;
    public void setter(int sid){
        this.sid = sid;
    }
    public boolean equals(Student s){
        if(this.sid == s.sid) return true;
        else return false;
    }
}

public class Example12 {
    public static void main(String[] args) {
        Student Lily = new Student();
        Student Lucy = new Student();
        Lily.setter(123456);
        Lucy.setter(123456);
        System.out.println("Lily 和 Lucy 的学号均为 123456");
        System.out.println("Lily.equals(Lucy) = "+Lily.equals(Lucy));
        System.out.println("Lily == Lucy = "+(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{
    void sleep();
}

class Cat implements Animal{
    public void sleep(){
        System.out.println("调用了sleep()方法。。。");
    }
    public void catchMouse(){
        System.out.println("调用了catchMouse()方法。。。");
    }
}

2、定义测试类Example13,Cat对象指向Animal引用,并使用父类Animal引用调用sleep()方法。代码如下:

package Example13;

interface Animal{
    void sleep();
}

class Cat implements Animal{
    public void sleep(){
        System.out.println("调用了sleep()方法。。。");
    }
    public void catchMouse(){
        System.out.println("调用了catchMouse()方法。。。");
    }
}

public class Example13 {
    public static void main(String[] args) {
        Animal c = new Cat();
        c.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{
    void sleep();
}

class Cat implements Animal {
    public void sleep(){
        System.out.println("调用了Cat.sleep()方法。。。");
    }
}

class Pig implements Animal {
    public void sleep(){
        System.out.println("调用了Pig.sleep()方法。。。");
    }
}

2、定义测试类Example14,Cat对象指向Animal引用,并使用父类Animal引用调用sleep()方法。代码如下:

package Example14;

interface Animal{
    void sleep();
}

class Cat implements Animal {
    public void sleep(){
        System.out.println("调用了Cat.sleep()方法。。。");
    }
}

class Pig implements Animal {
    public void sleep(){
        System.out.println("调用了Pig.sleep()方法。。。");
    }
}

public class Example14 {
    public static void main(String[] args) {
        Animal a = new Cat();
        Pig p = a;
        p.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{
    void show();
    void method();
}

class Outer implements Inter{
    public void function(){
        Inter in = new Inter() {
            @Override
            public void show() {
                System.out.println("调用了Inter.show()方法。。。");
            }
            @Override
            public void method() {
                System.out.println("调用了Inter.method()方法。。。");
            }
        };
        in.show();
        in.method();
    }

    @Override
    public void show() {}
    @Override
    public void method() {}
}

2、定义测试类Example15。代码如下:

package Example15;

interface Inter{
    void show();
    void method();
}

class Outer implements Inter{
    public void function(){
        Inter in = new Inter() {
            @Override
            public void show() {
                System.out.println("调用了Inter.show()方法。。。");
            }
            @Override
            public void method() {
                System.out.println("调用了Inter.method()方法。。。");
            }
        };
        in.show();
        in.method();
    }

    @Override
    public void show() {}
    @Override
    public void method() {}
}

public class Example15 {
    public static void main(String[] args) {
        Outer ou = new Outer();
        ou.function();
    }
}

运行结果如图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 Example16;

public class Example16 {
    public static void main(String[] args) {
        int[] arr = {1,2,3,4,5,6,7,8,9,0};
        for (int i = 0; i < arr.length; i++) {
            System.out.print(arr[i]+" ");
        }
        System.out.println("over");
        try{
            for (int i = 0; i < arr.length + 1; i++) {
                System.out.print(arr[i]+" ");
            }
            System.out.println("over");
        }
        catch(Exception e){
            System.out.println("角标越界");
        }
    }
}

运行结果如图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 Example17;

public class Example17 {
    public static void main(String[] args) {
        try{
            int n = 10/0;
            System.out.println("程序继续");
        }
        catch(Exception e){
            System.out.println("出异常类");
        }
        finally {
            System.out.println("释放资源");
        }
    }
}

运行结果如图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 Example18;

public class Example18 {
    public static int div(int a,int b) throws Exception {
        Exception e = new Exception("除数为零");
        if(b == 0) throw e;
        return a/b;
    }

    public static void main(String[] args) {
        int x = 0;
        try{
            x = div(10,1);
            System.out.println(x);
        } catch (Exception e) {
           System.out.println("捕获的异常是:"+e.getMessage());
        }

        try{
            x = div(10,0);
            System.out.println(x);
        } catch (Exception e) {
            System.out.println("捕获的异常是:"+e.getMessage());
        }
    }
}

运行结果如图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 MyException extends Exception{
    public MyException(){
        super();
    }
    public  MyException(String message){
        super(message);
    }
}

2、抛出异常和处理异常,代码如下:

package Example19;

class MyException extends Exception{
    public MyException(){
        super();
    }
    public  MyException(String message){
        super(message);
    }
}

public class Example19 {
    public static int div(int a,int b) throws MyException{
        MyException e = new MyException("除数为零");
        if(b == 0) throw e;
        return a/b;
    }
    public static void main(String[] args) {
        try{
            int x = div(10,0);
            System.out.println(x);
        } catch (MyException e) {
            System.out.println("捕获的异常是:"+e.getMessage());
        }
    }
}

运行结果如图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 cn.itcast.domain;

public class Student{
    int sid;
    String name;
    double score;
    public Student(int sid,String name,double score){
        this.name = name;
        this.score = score;
        this.sid = sid;
    }
    public void evaluation(){
        if(this.score > 90) {
            System.out.println(this.name+"是三好学生");
        }
        else{
            System.out.println(this.name+"是普通学生");
        }
    }
}

2、编写Example20类,该类位于cn.itcast.example包下,代码如下所示:

package cn.itcast.example;
import cn.itcast.domain.Student;

public class Example20 {
    public static void main(String[] args) {
        Student s = new Student(123456,"李明",91);
        s.evaluation();
    }
}

运行结果如图3-20所示。

图3-20 运行结果
三、实验总结
1、当处于不同包下的类互相调用时,需要使用被调用类的完整类名,即包名加上类名。为了简化代码,Java中提供了import关键字,用于引入某个指定包下的类。
2、import通常出现在package语句之后,类定义之前。
3、当需要引入同一包下的多个类时,可以使用“import包名.*;”的方式,引入包下所有的类。

评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值