Java实验——实验4B
|字数总计:3.2k|阅读时长:14分钟|阅读量:
Exam1
- 编写一个程序,在程序中定义一个抽象类Shape,再定义两个抽象方法Area和printArea,定义两个Shape类的子类Rectangle和Circle类,在子类中实现父类的抽象方法。
code
Shape.java
1 2 3 4 5 6 7 8
| package project4B.abstractTest;
public abstract class Shape{ double area; public abstract void Area(); public abstract void printArea(); }
|
Rectangle.java
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20
| package project4B.abstractTest;
public class Rectangle extends Shape{ @Override public void Area() { area = height*width; }
@Override public void printArea() { System.out.println(String.format("%.3f",area)); }
float height,width;
public Rectangle(float height, float width) { this.height = height; this.width = width; } }
|
Circle.java
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21
| package project4B.abstractTest;
public class Circle extends Shape{ @Override public void Area() { area = Math.PI*r*r; }
@Override public void printArea() { System.out.println(String.format("%.3f",area)); }
float r;
public Circle(float r) { this.r = r; } }
|
Application.java
1 2 3 4 5 6 7 8 9 10 11 12
| package project4B.abstractTest;
public class Application { public static void main(String[] args) { Rectangle rectangle = new Rectangle(1.2f, 4.2f); rectangle.Area(); rectangle.printArea(); Circle circle = new Circle(3); circle.Area(); circle.printArea(); } }
|
运行结果

Exam2
2、编写下面程序写出运行结果,谈谈成员变量的继承与隐藏,方法的覆盖与重载。
code
Test.java
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74
| package project4B;
class A{ int sum,num1,num2; public A(){ num1 = 10; num2 = 20; sum = 0; }
void sum1(){ sum = num1+num2; System.out.println("sum ="+num1+"+"+num2+"="+sum); }
void sum2(int n){ num1 = n; sum = num1+num2; System.out.println("sum ="+num1+"+"+num2+"="+sum); }
}
class B extends A{ int num2;
public B() { this.num2 = 200; } void sum2(){ sum = num1+num2; System.out.println("sum ="+num1+"+"+num2+"="+sum);
}
void sum2(int n){ num1 = n; sum = num1+num2; System.out.println("sum ="+num1+"+"+num2+"="+sum); }
void sum3(int n){ super.sum2(n); System.out.println("sum ="+num1+"+"+num2+"="+sum); }
void testVar(){ System.out.println("this.num1==super.num1:\t"+(this.num1==super.num1)); System.out.println("this.num2==super.num2:\t"+(this.num2==super.num2)); }
}
public class Test { public static void main(String[] args) { B b = new B(); b.sum1(); b.sum2(); b.sum2(50); b.sum3(50); b.testVar(); } }
|
运行结果

总结:
- 子类会继承父类的成员变量,但当子类中定义了与父类相同的成员变量时,父类中相应的成员变量会被隐藏,并没有被覆盖,当需要调用被隐藏的变量时仍然可以调用。没有被隐藏的成员变量则为子类与父类共享的变量。
- 方法覆盖和方法重载的区别:方法覆盖是存在于继承当中的,当子类中显示定义了和父类完全相同的方法时,则会将父类对应的方法覆盖,并重写。(重写常用于子类继承父类后,对父类方法的具体实现不满意,但是仍然想用该方法的方法名和实参等,则对该方法的具体实现进行重写)。而方法重载是存在于同一个类中的,且要求形参不同,重载的方法时并行存在的。
Exam3
- 理解下面3个类的定义,分析它们之间的关系,写出运行结果。
code
Inheritance.java
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37
| package project4B;
class SuperClass{ int x; SuperClass(){ x = 3; System.out.println("in SuperClass:x="+x); } void doSomething(){ System.out.println("in SuperClass.doSomething()"); } }
class SubClass extends SuperClass{ int x; SubClass(){ super(); x = 5; System.out.println("in SubClass:x="+x); } void doSomething(){ super.doSomething(); System.out.println("in SubClass.doSomething()"); System.out.println("super.x="+super.x+"\nsub.x="+x); } }
public class Inheritance { public static void main(String[] args) { SubClass subClass = new SubClass(); subClass.doSomething(); } }
|
三个类的关系:
SuperClass属于正常的类,在此程序中作为SubClass的父类。
SubClass继承SuperClass,隐藏了SuperClass的属性x并重写了doSomething()方法。
Inheritance为公共类,在此程序中负责包含主进程。
运行结果

程序运行过程分析:
- 主进程第一条代码new了一个SubClass类型的对象,调用SubClass的无参构造。SubClass()首先调用父类无参构造SuperClass(),则super.x = 3,在控制台输出“in SuperClass:x=3”,this.x = 5,在控制台输出“in SubClass:x=5”。
- 第二条代码调用了subClass的doSomething()方法。首先调用父类的doSomething()方法,控制台输出“in SuperClass.doSomething()”,控制台紧接着输出“in SubClass.doSomething()”和“super.x=3”和“sub.x=5”。
Exam4
- 接口和继承的综合应用
首先定义一个接口(IShapeArea),其中包含返回面积的方法(getArea)。然后定义一个矩形类(Rectangle)和一个圆类(Circle),并派生出一个正方形类(Square),即正方形类的父类为矩形类,三者都要求实现接口IShapeArea,自行扩充成员变量和方法(比如周长和面积)。
在主方法 main 中建一数组,数组中放入一些上述类型的对象,并计算它们的周长和面积之和。
code
IShapeArea.java
1 2 3 4 5 6 7
| package project4B.interfaceTest;
public interface IShapeArea {
double getArea(); float getPerimeter(); }
|
Rectangle.java
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27
| package project4B.interfaceTest;
public class Rectangle implements IShapeArea{ float length,width,perimeter; double area; public Rectangle(){
}
public Rectangle(float length, float width) { this.length = length; this.width = width; this.perimeter = getPerimeter(); this.area = getArea(); }
@Override public float getPerimeter() { return 2*(width+length); }
@Override public double getArea() { return length*width; }
}
|
Circle.java
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22
| package project4B.interfaceTest;
public class Circle implements IShapeArea{ float r,perimeter; double area;
public Circle(float r) { this.r = r; this.perimeter = getPerimeter(); this.area = getArea(); }
@Override public float getPerimeter() { return (float)(2*Math.PI*r); }
@Override public double getArea() { return Math.PI*r*r; } }
|
Square.java
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20
| package project4B.interfaceTest;
public class Square extends Rectangle implements IShapeArea{
public Square(float length) { this.length = length; this.perimeter = getPerimeter(); this.area = getArea(); }
@Override public float getPerimeter() { return 4*length; }
@Override public double getArea() { return length*length; } }
|
Test.java
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30
| package project4B.interfaceTest;
public class Test { public static void main(String[] args) { Rectangle[] rectangles = new Rectangle[3]; Circle[] circles = new Circle[3]; Square[] squares = new Square[3];
for(int i = 0;i < 3;i++){ rectangles[i] = new Rectangle((float)(100*Math.random()),(float)(100*Math.random())); circles[i] = new Circle((float)(100*Math.random())); squares[i] = new Square((float)(100*Math.random())); }
for(int i = 0; i < 3;i++) System.out.println("rectangles["+i+"]的长为"+String.format("%.3f",rectangles[i].length)+",宽为"+String.format("%.3f",rectangles[i].width)+",周长为"+String.format("%.3f",rectangles[i].perimeter)+",面积为"+String.format("%.3f",rectangles[i].area));
System.out.println("================================================"); for (int i = 0;i < 3;i++) System.out.println("circle["+i+"]的半径为"+String.format("%.3f",circles[i].r)+",周长为"+String.format("%.3f",circles[i].perimeter)+",面积为"+String.format("%.3f",circles[i].area));
System.out.println("================================================"); for(int i = 0;i < 3;i++) System.out.println("square["+i+"]的边长为"+String.format("%.3f",squares[i].length)+",周长为"+String.format("%.3f",squares[i].perimeter)+",面积为"+String.format("%.3f",squares[i].area)); } }
|
运行结果

程序分析:
程序通过实现接口IShapeArea得到类Rectangle、Circle和Square,Square实现接口的同时继承Rectangle。在实现接口和继承中,均完成重写接口的方法或父类的方法。
并定义一个主进程所在类Test,创建三个不同类的对象数组,利用Math.random()方法给三个对象数组的各个对象的属性赋值。最后利用String.format()方法进行格式化输出将数据的精度控制在三位小数。
Exam5
- 接口的练习为某研究所编写一个通用程序,用来计算每一种交通工具运行1000米所需的时间,已知每种交通工具的参数都是3个整数A、B、C的表达式。现有两种工具:Car和Plane,其中Car的速度运算公式为:A*B/C,Plane的速度运算公式为:A+B+C。需要编写4类:ComputeTime、Plane、Car和接口(ICommon),要求在未来如果增加第3种交通工具的时候,不必修改以前的任何程序,只需要编写新的交通工具的程序即可,其运行过程如下,从命令行输入ComputeTime的四个参数,第一个是交通工具的类型,第二、三、四个参数分别是整数A、B、C,我们在Dos下运行时输入如下:计算Plane的时间:”java ComputeTime Plane 20 30 40”计算Car的时间:“java ComputeTime Car 23 34 45”
code
ComputeTime.java
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125
| package project4B;
import javax.swing.*; import java.lang.reflect.Constructor; import java.lang.reflect.Field; import java.lang.reflect.InvocationTargetException; import java.lang.reflect.Method;
interface ICommon { float getSpeed(); }
class Plane implements ICommon {
float A,B,C; public Plane(float a, float b, float c) { A = a; B = b; C = c; }
public float getA() { return A; }
public void setA(float a) { A = a; }
public float getB() { return B; }
public void setB(float b) { B = b; }
public float getC() { return C; }
public void setC(float c) { C = c; }
@Override public float getSpeed() { return A+B+C; } }
class Car extends Plane {
public Car(float a, float b, float c) { super(a,b,c); }
@Override public float getA() { return super.getA(); }
@Override public void setA(float a) { super.setA(a); }
@Override public float getB() { return super.getB(); }
@Override public void setB(float b) { super.setB(b); }
@Override public float getC() { return super.getC(); }
@Override public void setC(float c) { super.setC(c); }
@Override public float getSpeed() { return A*B/C; } }
public class ComputeTime { @SuppressWarnings("unchecked") public static void main(String args[]) throws ClassNotFoundException, NoSuchMethodException, IllegalAccessException, InvocationTargetException, InstantiationException, NoSuchFieldException { String s = "project4B."+args[0]; float Atemp = Float.parseFloat(args[1]); float Btemp = Float.parseFloat(args[2]); float Ctemp = Float.parseFloat(args[3]); Class Trans = Class.forName(s); Constructor constructor = Trans.getDeclaredConstructor(float.class,float.class,float.class); ICommon trans = (ICommon) constructor.newInstance(Atemp,Btemp,Ctemp);
Method getA = Trans.getDeclaredMethod("getA"); Method getB = Trans.getDeclaredMethod("getB"); Method getC = Trans.getDeclaredMethod("getC"); Method getSpeed = Trans.getDeclaredMethod("getSpeed"); float A = (float)getA.invoke(trans); float B = (float)getB.invoke(trans); float C = (float)getC.invoke(trans); float speed = (float) getSpeed.invoke(trans);
System.out.println("A:"+A+"\tB:"+B+"\tC"+C); System.out.println("Speed of "+args[0]+" is "+speed); }
}
|
运行结果
Dos运行ComputeTime.java操作过程:
在文件当前目录下打开命令行终端
- 输入
javac ComputeTime.java
编译java文件成功生成class文件。
- 输入
cd..
退回到java文件所在根目录(Java_Code)下的第一子目录(project4B)
- 输入
java project4B.ComputeTime Plane 20 30 40
得到飞机速度结果。
- 输入
java project4B.ComputeTime Car 23 34 45
得到汽车速度的结果。
拓展
添加一个Bike类,不对其他类进行任何修改,实现Bike的数据处理,Bike的速度计算公式为A*C/B。
在上述ComPuteTime.java文件中添加如下代码:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40
| class Bike extends Plane{ public Bike(float a, float b, float c) { super(a, b, c); }
@Override public float getA() { return super.getA(); }
@Override public void setA(float a) { super.setA(a); }
@Override public float getB() { return super.getB(); }
@Override public void setB(float b) { super.setB(b); }
@Override public float getC() { return super.getC(); }
@Override public void setC(float c) { super.setC(c); }
@Override public float getSpeed() { return A*C/B; } }
|
保存程序并重新编译(操作步骤和上面相同,不再赘述)。
运行结果:

程序总结:
该程序主要思想是运用了Java的反射机制,对在Dos下输入的数据进行处理,对第一个输入的字符串进行className查询,并将查询到的class进行调用构造器和调用方法操作,从而达到对输入的字符串进行分类数据处理。
在Plane实现接口后,往后的交通工具都可以对其进行继承操作从而得到Plane对ICommon接口的实现,再重写speed的算法即可。
遇到问题:
开始时,我是在一个package中添加了ICommon.java, Plane.java, Car.java, ComputeTime.java。但是在编译过程中,ICommon因为没有import其他自定义的java文件,所以编译顺利通过生成ICommon.class文件。但是在编译Plane.java时,import了ICommon,提示错误“无法找到字符”。上网查了一个小时没找到处理方法,最后就将接口和所有类合并到ComputeTime.java中了。报错的原因是因为只有import库中有的文件才行吗?而自定义的文件没有放到库中所以报错?
实验总结:
Java有很多有趣的机制,例如反射、注解、异常等。非常值得学习且有趣的一种高级语言。