admin 管理员组

文章数量: 887021


2024年1月17日发(作者:快速排序的全部代码)

一、实验目的

1. 深入理解类的继承的基本概念及实现。

2. 了解Object及对Object类的主要方法equals进行重写。

3. 掌握super关键字的作用。

4. 掌握抽象类与接口的基本概念及实际应用

5. 掌握对象多态性的作用。

6. 掌握接口的基本概念及实际应用。

7. 掌握接口回调的概念及运行机制。

二、实验内容及步骤

1、重写Object类的equals方法

任务一:使用继承自Object类的equals方法进行Person对象的比较操作。

(1)源代码如下:

class Person{

private String name;

private int age;

public Person(String name,int age){

= name;

= age;

}

//getter与setter方法略。

public String toString(){

return "姓名:"++";年龄:"+;

}

}

public class PersonDemo{

public static void main(String args[]){

Person person1 = new Person(“李兴华”,30);

Person person2 = new Person(“李兴华”,30);

n((person2)?"是同一个人。":"不是同一个人。");

}

}

(2)编译并运行应用程序。

运行结果:

(3)实验报告

将运行结果写在实验报告中。

思考:应用程序中person1对象调用的equals方法是从哪个类继承的,请查看源代码,说明此equals方法的作用,即比较的内容。

答:person1对象调用的equals方法是从Object类继承的。

此equals方法的目的是通过boolean判断两对象内存地址是否相同。

任务二:修改上述源代码Person类,使PersonDemo应用程序执行结果为“同一个人”。

提示:equals方法的原型是:public boolean equals(Object obj){}

源代码:

public boolean equals(Object obj){

if(obj==null||!(obj instanceof Person)) {

return false;

}

if(((Person) obj).name==&&((Person) obj).age==) {

return true;

}

return false;

}

运行结果:

2、对象的上转型对象

任务一:对象的上转型对象接收任意子类类型的对象

(1)使用Object接收一切的引用类型对象。

源代码:

class A{

public String getInfo(){

return “Hello World!!!”;

}

}

public class ADemo{

public static void main(String args[]){

Object obj = new A();

n(o());

n(ng());

A a = (A)obj;

n(o());

n(ng());

}

}

(2)编译并运行程序。

运行结果:

(3)实验报告

将运行结果写在实验报告中。

如果程序编译为通过,或运行时有错误提示,请说明原因,并将错误改正。

答:错误:The method getInfo() is undefined for the type Object 方法getInfo()没有被定义,需要add cast to Obj,改为n(((A) obj).getInfo());即可。

任务二:上转型实现多态性

(1) 实例学习

源代码:

package renwu3;

class A {

public void fun1(){

n("A-->public void fun1(){}");

}

public void fun2() {

1();

}

};

不使用上转型对象实现多态性源代码如下:

package renwu3;

class B extends A {

public void fun1() {

n("B-->public void fun1(){}");

}

public void fun3() {

n("B-->public void fun3(){}");

}

};

package renwu3;

class C extends A{

public void fun1() {

n("C-->public void fun1(){}");

}

public void fun5() {

n("C-->public void fun3(){}");

}

};

package renwu3;

public class PolDemo4 {

}

public static void main(String[] args) {

// TODO Auto-generated method stub

fun(new B());//传递B类实例

fun(new C());//传递C类实例

}

public static void fun(B b) {

1();//统一调用覆写父类的fun1()方法

}

public static void fun(C c) {

1();

}

运行结果:

以上程序虽然实现了基本的要求,但是可以发现:如果按照以上的方式完成程序,则当产生一个A类的子类时,fun()方法就要重载一次,这样如果功能扩充,则必须要修改类本身,那么如果使用对象多态性完成呢?

 使用上转型对象实现多态性:

源代码:

package renwu1;

class A {

public void fun1(){

n("a-->public void fun1(){}");

}

public void fun2() {

1();

}

};

package renwu1;

class B extends A {

public void fun1() {

n("B-->public void fun1(){}");

}

public void fun3() {

n("B-->public void fun3(){}");

}

};

package renwu1;

class C extends A {

public void fun1() {

n("C-->public void fun1(){}");

}

public void fun5() {

n("C-->public void fun3(){}");

}

}

package renwu1;

public class PolDemo05 {

public static void main(String[] args) {

// TODO Auto-generated method stub

fun(new B());//传递B类实例,产生向上转型

fun(new C());//传递C类实例,产生向上转型

}

public static void fun(A a) { //接收父类对象

1();

}

}

运行结果:

(2)阅读上述两个源代码,深刻理解使用上转型对象实现多态性机制。

答:上转型:是子类对象由父类引用。想要上转型的前提必须是由继承关系的两个类,在调用方法的时候,上转型对象只能调用父类中有的方法,如果调用子类方法则会报错。

3、抽象类与上转型对象练习

任务一:通过对上述实验内容的实践与学习,根据要求填写代码。

(1)要求:

有一家公司,有不同类型的员工,包括按年领取薪水,按月领取薪水,按周领取薪水,计算该公司一年需支付的薪水总额

 有一个abstract类,类名为Employee;

 该类有一个abstract方法:

public abstract double earnings( );;

 Employee的子类有YearWorker、MontthWorker和WeekWorker。

YearWorker对象按年领取薪水,MonthWorker按月领取薪水,WeekWorker按周领取薪水。

 子类必须实现父类的earnings()方法,返回各自领取薪水数。

 有一个Company类,该类用employee数组作为成员,employee数组的

单元可以是YearWorker对象的上转型对象、MonthWorker对象的上转型对象或WeekWorker对象的上转型对象。

 程序能输出Company对象一年需要支付的薪水总额。

(2)代码模板

源代码:

package renwu2;

public class Company {

Employee[] employee;

double salaries=0;

Company(Employee[] employee){

ee=employee;

}

public double salariesPay(){

salaries=0;

for(int i=0;i<;i++){

salaries=salaries+employee[i].earnings();

}

return salaries;

}

}

package renwu2;

abstract class Employee {

public abstract double earnings( );

}

package renwu2;

public class WeekWorker extends Employee{

public double earnings(){

return 52*1000;

}

}

package renwu2;

public class MonthWorker extends Employee{

public double earnings(){

return 12*5000;

}

}

package renwu2;

public class YearWorker extends Employee {

public double earnings(){

return 120000;

}

}

package renwu2;

public class HardWork {

public static void main(String[] args){

Employee[] employee=new Employee[20]; //公司有20名职员

for(int i=0;i<;i++){

if(i%3==0)

employee[i]=new WeekWorker();

else if(i%3==1)

employee[i]=new MonthWorker();

else if(i%3==2)

}

}

employee[i]=new YearWorker();

}

Company company=new Company(employee);

n("公司年工资总额:"+esPay()+"元");

运行结果:

(3)实验报告

将代码1-4写在实验报告中。

在Employee类的子类中合适位置使用super,再运行程序。根据查看的结果,验证在子类中是否可以调用抽象类父类的构造方法,即抽象类是否有构造方法?

答:子类可以调用抽象类父类的构造方法。

4、接口案例学习

任务一:学习下面实例,定义一个抽象的汽车类car,再将汽油车设计为接口。该程序代码如下:

import ; //汽车抽象类

public abstract class Car

{

//公用数据字段声明区

public Color color; //车辆颜色

public int gearNum; //排档数

public String tiretype; //轮胎型号

public float engine; //引擎排气量

//公用抽象方法声明区

public abstract void shiftgear(); //换档

public abstract void brake(); //煞车

public abstract void aircon(); //开冷气

public abstract void headlight(); //开大灯

}

public interface Gasoline //汽油车接口

{

public static final String FUEL="gasoline(汽油)";//定义一个最终字段

public void refuel(); //声明一个方法

}

源代码:

package renwu3;

public class Gcar extends Car {

static int gearNum=5;//声明gearNum为类栏

public Gcar() {

tiretype="BridgeStone185ST";//轮胎型号

engine=1598.5f;//排气量

}

public static void main(String args[]) {

Gcar gcar=new Gcar();//产生实例

ent();

ear();

();

}

public void equipment() {//轿车的配置

n("轿车颜色:"+color);

n("轿车排挡数:"+gearNum);

n("轿车轮胎型号:"+tiretype);

n("轿车排气量:"+engine);

}

public void shiftgear() {

n("轿车换挡方式:自排"+gearNum+"文件");

}//换挡

public void brake() {

n("水压式刹车系统");

}//刹车

public void aircon() {};//开冷气

public void headlight() {};//开大灯

}

任务二:(1)根据以上代码,定义你自己的车,该车继承自汽车类car并实现汽油车接口。

自己的车属性为:档位为5个档,轮胎型号是BridgeStone185ST,排气量为1598.5。

自己的车的新增的方法有:equipment():输出轿车颜色、轿车排档数、轿车轮胎型号、轿车排气量和轿车燃料。

源代码:

package renwu3;

import ; //汽车抽象类

public class MyCar extends Gcar{

private Color color;

public MyCar() {

color=;//设置汽车颜色

}

public static void main(String args[]) {

MyCar mycar=new MyCar();

ent();

ear();

();

}

public void equipment() {

n("我的车排挡数:"+m);

n("我的车颜色:"+);

n("我的车轮胎型号:"+pe);

n("我的车引擎排气量:"+);

}

public void shiftgear() {//换挡-覆盖的新方式

n("我的车换挡方式:自排"+m+"档");

}

@Override

public void brake() {

// TODO Auto-generated method stub

}

@Override

public void aircon() {

// TODO Auto-generated method stub

}

@Override

public void headlight() {

// TODO Auto-generated method stub

}

}

(2)实验报告

将任务二的代码写在实验报告中。

编写应用程序测试实现类。

运行结果:

(2) 注意:在实现接口时,要实现所有接口中定义的所有方法,方法的实现可以具有具体的实现内容,也可以是抽象的方法,即只有方法名或参数,没有变量、没有具体操作语句,只有一对大括号{}的空方法。

5、接口的回调

任务一:有一家商店销售电视、计算机和手机,计算该商店的年销售总额

(1) 要求:

 有一个ComputeTotalSales接口,该接口中有一个方法:

public double totalSalesByYear();

 有三个实现该接口的类:Television,Computer和Mobile。这三个类通过实现接口

computeTotalSales给出自己的年销售额。

 有一个Shop类,该类用computeTotalSales数组作为成员,computeTotalSales数

组的单元可以存放Television对象的引用或Mobile对象的引用。

 编写应用程序输出Shop对象的年销售额。

(2)代码模板

源代码:

interface ComputeTotalSales

{

public double totalSalesByYear( );

}

class Television implements ComputeTotalSales

{

public double totalSalesByYear() {// 实现totalSalesByYear( )方法

return 60000;}

class Compute implements ComputeTotalSales

{

public double totalSalesByYear() { // 实现totalSalesByYear( )方法

{

public double totalSalesByYear() {// 实现totalSalesByYear( )方法

{

ComputeTotalSales[ ] goods;

double totalSales=0;

Shop(ComputeTotalSales[ ] goods)

{

=goods;

}

public double giveTotalSales( )

{

totalSales=0;

for (int i=0; i<; i++) {// 计算totalSales

totalSales = totalSales + goods[i].totalSalesByYear();

} return totalSales;

}

}

public class HappySale

{

public static void main(String args[ ])

{

ComputeTotalSales[ ] goods=new ComputeTotalSales[3];

for(int i=0;i<;i++)

{

if(i%3==0)

goods[i]=new Television( );

else if(i%3==1)

goods[i]=new Computer( );

else if(i%3==2)

goods[i]=new Mobile( );

}

Shop shop=new Shop(goods);

return 50000;}

class Shop

return 10000;}

class Mobile implements ComputeTotalSales

n("商店年销售额:"+talSales( ) );

}

}

运行结果:

*任务二:利用接口回调和反射独立编程。

(1)内容及要求

 假定现有两种工具:Car 和Plane,其中Car 的平均速度运算公式为:a*b/c;Plane的平均速度运算公式为:a+b+c,三个参数的具体值在程序运行时用户录入。

 编写ComputeTime类,通过该类计算用户指定的交通工具运行1000公里所需的时间。参数的具体值在程序运行时用户录入。

 其运行过程如下,从命令行输入ComputeTime的四个参数,第一个是交通工具的类型,第二、三、四个参数分别时整数A、B、C,举例如下:

计算Plane的时间:"java ComputeTime Plane 20 30 40"。

计算Car的时间:"java ComputeTime Car 23 34 45"。

 编程要求:

在未来如果增加第3种交通工具的时候,只需要编写新的交通工具的程序。如第3种交通工具为Ship,则只需要编写,运行时输入:"java ComputeTime Ship 22 33

44"。

充分利用接口及接口回调的技术。

 提示:实例化一个对象的另外一种办法:e(str).newInstance();

例如需要实例化一个Plane对象:Plane plane =

(Plane)e("Plane").newInstance()

(2)实验报告

源代码:

package renwu5;

import ;

import .*;

public class ComputeTime {

public static void main(String args[]) {

n("交通工具:"+args[0]);

n("参数a:"+args[1]);

n("参数b:"+args[2]);

n("参数c:"+args[3]);

double a=ouble(args[1]);

double b=ouble(args[2]);

double c=ouble(args[3]);

double v,t;

try {

Common

d=(Common)e("e."+args[0]).newInstance();

v=er(a,b,c);

t=1000/v;

n("平均速度:"+v+"km/h");

n("运行时间:"+t+"小时");

}

catch(Exception e) {

n("class not found");

}

}

}

package renwu5;

import ;

import .*;

public class Plane implements Common{

public double runTimer(double a,double b,double c) {

return(a+b+c);

}

}

package renwu5;

import ;

public class Car implements Common{

public double runTimer(double a,double b,double c) {

return(a*b/c);

}

}

package ;

public interface Common {

double runTimer(double a,double b,double c);

}

三、实验结果及分析

与定义类的class不同,接口定义时需要使用interface关键字。

定义接口所在的仍为.java文件,虽然声明时使用的为interface关键字的编译后仍然会产生.class文件。这点可以将接口看做是一种只包含了功能声明的特殊类。接口中的方法全是抽象方法,直接new接口来调用方法没有意义,Java也不允许这样干。类与接口的关系为实现关系,即类实现接口。实现的动作类似继承,只是关键字不同,实现使用implements。其他类(实现类)实现接口后,就相当于声明:”我应该具备这个接口中的功能”。实现类仍然需要重写方法以实现具体的功能。


本文标签: 对象 接口 实现 方法 转型