文章目录
1 Java实验五,继承
一.实验目的
- 实现Java中的类继承机制;
- 体会继承的好处:重用和封装。
二.实验内容及要求
编写能够满足如下条件的程序:
- 声明一个Person类,有name(String类型)、age(int类型)、sex(char类型)属性。通过构造方法进行赋值。一个show方法,返回String类型,内容如下:某某男(女)年龄
- 声明一个Student类,继承Person类,增加id(int,学号)属性,通过构造方法,利用super 调用父类构造方法来进行变量赋值。Override父类的show方法,返回String类型,内容如下:某某男(女)年龄学号
提示:利用super调用父类的show方法得到除学号部分的String,然后加上学号的信息。 - 声明一个Teacher类,继承Person,增加course(String,所教课程)属性,通过构造方法,利用super 调用父类构造方法来进行变量赋值。Overide父类的show方法,返回String类型,内容如下:某某男(女)年龄所教课程
提示:利用super 调用父类的show方法得到除所教课程部分的String,然后加上所教课程的信息。 - 声明PersonApp类,在其中的main 方法中分别声明 Person、Student、Teacher类型的变量,并通过构造方法初始化,然后显示各自的信息。
//Person.java
public class Person {
String name;
char sex;
int age;
// 构造函数,设置父类person对象信息
public Person(String name, char sex, int age) {
this.name = name;
this.sex = sex;
this.age = age;
}
//输出父类person对象信息
String show() {
return "姓名:" + name + ", 性别:"+ sex + ", 年龄:" + age;
}
}
//Student.java
public class Student extends Person{
int id;
// 构造函数,设置子类student对象信息
public Student(String name, char sex, int age, int id) {
//调用父类构造函数
super(name, sex, age);
this.id = id;
}
//输出子类student对象信息
String show() {
return super.show() + ", 学号:" + id;
}
}
//Teacher.java
public class Teacher extends Person{
String course;
// 构造函数,设置子类teacher对象信息
public Teacher(String name, char sex, int age, String course) {
//调用父类构造函数
super(name, sex, age);
this.course = course;
}
//输出子类teacher对象信息
String show() {
return super.show() + ", 所属课程:" + course;
}
}
//PersonApp.java
public class PersonApp {
public static void main(String[] args) {
//设置父类person信息并输出
Person person = new Person("person", '男', 20);
System.out.println(person.show());
//设置子类student信息并输出
Student student = new Student("student", '女', 18, 16010101);
System.out.println(student.show());
//设置子类teacher信息并输出
Teacher teacher = new Teacher("teacher", '女', 22, "English");
System.out.println(teacher.show());
}
}
2 Java实验六,接口
一.实验目的
- 实现Java中的接口;
- 掌握接口回调技术;
- 掌握面向接口编程思想。
二.实验内容及要求
体操比赛计算选手成绩的办法是去掉一个最高分和最低分后再计算平均分,而学校考察一个班级的某科目的考试情况时,是计算全班同学的平均成绩。编写能够满足如下条件的程序:
- 定义一个接口,包含计算平均值的抽象方法。
- 定义一个实现上述接口的用于计算体操比赛选手成绩的类。
- 定义一个实现上述接口的用于计算班级平均成绩的类。
- 在主类中通过接口回调分别计算并输出体操选手和班级的成绩。
//AverScore.java
public interface AverScore {
//接收一个分数数组,计算平均数并输出
void averageScore(double [] score);
}
//GymnasticsScore.java
import java.util.Arrays;
public class GymnasticsScore implements AverScore{
public void averageScore(double [] score) {
//调用Array类方法sort,将数组从小到大排序
Arrays.sort(score);
//去掉一个最高分,去掉一个最低分,并计算总分
double sum = 0;
for (int i = 1; i < score.length - 1; i++) {
sum += score[i];
}
System.out.printf("体操选手成绩为:%.2f\n", sum / (score.length - 2));
}
}
//ClassScore.java
public class ClassScore implements AverScore{
public void averageScore(double [] score) {
double sum = 0;
//计算总分
for (int i = 0; i < score.length; i++) {
sum += score[i];
}
System.out.printf("班级平均成绩为:%.2f\n", sum / score.length);
}
}
//PrintAverScore.java
public class PrintAverScore {
//第一个参数是实现接口的类的对象,第二个参数是存储分数的数组
void showScore(AverScore averScore, double [] score) {
//调用实现接口的类的方法,输出平均分
averScore.averageScore(score);
}
public static void main(String[] args) {
double classScore[] = {99, 70, 88.3, 93.6, 100};//班级学生分数
double gymnasticsScore[] = {88.3, 97, 77, 90, 96.5};//体操选手分数
PrintAverScore printAverScore = new PrintAverScore();
//输出班级学生平均分
printAverScore.showScore(new ClassScore(), classScore);
//输出体操选手平均分
printAverScore.showScore(new GymnasticsScore(), gymnasticsScore);
}
}
四.实验中的问题及心得
- 我更加理解了接口回调的概念:可以把实现某一接口的类创建的对象的引用赋值给该接口声明的接口变量,那么该接口变量就可以调用被类实现的接口方法,但接口无法调用类中的其他方法
- 若将接口变量作为函数的参数,则可以将任何实现该接口的类的实例的引用传递给该接口参数
- 若一非抽象类实现了某个接口,则该类必须重写接口中的所有方法,且方法的访问权限必须显式声明为public
- 接口在要求一些类有相同名称的方法时,不强迫这些类具有相同的父类
- 使用接口进行程序设计的核心思想是使用接口回调
3 Java实验七, 接口与多态
一.实验目的
- 理解接口与多态;
- 掌握接口回调技术;
- 掌握面向接口编程思想。
二.实验内容及要求
卡车要装载一批货物,货物由电视机、计算机和洗衣机组成,卡车需要计算出整批货物的重量。编写能够满足如下条件的程序:
- 定义一个接口,包含计算货物重量的抽象方法。
- 分别定义实现上述接口的用于计算电视机、计算机和洗衣机的类。
- 定义一个卡车类,在其中定义一个数组成员变量表示其装载的货物,并提供能计算所载整批货物重量的方法。
- 在主类中模拟卡车装载N件货物,每件货物的类别随机,输出其所载货物的总重量。
// Goods.java
public interface Goods {
double cal_weight();//计算货物重量的抽象方法
}
// TV.java
public class TV implements Goods{
double singleTVWeight;//单个电视机重量
double single_weight[] = {5.5, 3.1, 4.1, 6};//可选择的电视机重量
//构造方法,从single_weight[]中随机选中一个重量并设置
public TV(int randomInt) {
this.singleTVWeight = single_weight[randomInt];
}
//计算电视机重量的方法,返回电视机重量
public double cal_weight() {
return singleTVWeight;
}
}
// Computer.java
public class Computer implements Goods{
double singleComputerWeight;//单个电脑重量
double single_weight[] = {1.5, 1.9, 2.0, 2.4};//可选择的电脑重量
//构造方法,从single_weight[]中随机选中一个重量并设置
public Computer(int randomInt) {
this.singleComputerWeight = single_weight[randomInt];
}
//计算电脑重量的方法,返回电脑重量
public double cal_weight() {
return singleComputerWeight;
}
}
// WashingMachine.java
public class WashingMachine implements Goods{
double singleWMWeight;//单个洗衣机重量
double single_weight[] = {13.5, 11.9, 20, 12.4};//可选择的洗衣机重量
//构造方法,从single_weight[]中随机选中一个重量并设置
public WashingMachine(int randomInt) {
this.singleWMWeight = single_weight[randomInt];
}
//计算洗衣机重量的方法,返回洗衣机重量
public double cal_weight() {
return singleWMWeight;
}
}
// Truck.java
import java.util.Random;
public class Truck {
static Goods[] goods;//数组成员变量,表示其装载的货物
static void show_weight(Goods[] goods) {
double sum = 0;//货物总重,初始为0
for (Goods g: goods) {
sum += g.cal_weight();
}//计算货物总重
System.out.printf("卡车装载货物的总重量为:%.2fkg\n", sum);
}
public static void main(String[] args) {
Random random = new Random();//创建随机数生成器random
Truck.goods = new Goods[50];//设置N为50
//计算电脑、洗衣机、电视机总数
int countTV = 0, countWM = 0, countCom = 0;
//计算电脑、洗衣机、电视机总重
double TVWeight = 0, WMWeight = 0, ComWeight = 0;
for (int i = 0; i < Truck.goods.length; i++) {
int selection = random.nextInt(3);
int index = random.nextInt(4);
//若随机数为0,货物种类为“电脑”
if (selection == 0) {
//设置数组中第i个货物种类为“电脑”
Truck.goods[i] = new Computer(index);
countCom++;//电脑总数加1
ComWeight += Truck.goods[i].cal_weight();
}
//若随机数为1,货物种类为“洗衣机”
else if (selection == 1) {
//设置数组中第i个货物种类为“洗衣机”
Truck.goods[i] = new WashingMachine(index);
countWM++;//洗衣机总数加1
WMWeight += Truck.goods[i].cal_weight();
}
//若随机数为2,货物种类为“电视机”
else if (selection == 2) {
//设置数组中第i个货物种类为“电视机”
Truck.goods[i] = new TV(index);
countTV++;//电视机总数加1
TVWeight += Truck.goods[i].cal_weight();
}
}
System.out.printf("电脑总数:%d, 总重:%.2fkg\n", countCom, ComWeight);
System.out.printf("洗衣机总数:%d, 总重:%.2fkg\n", countWM, WMWeight);
System.out.printf("电视机总数:%d, 总重:%.2fkg\n", countTV, TVWeight);
System.out.println("卡车装载货物的总数为:" + Truck.goods.length);
Truck.show_weight(Truck.goods);
}
}
四.实验中的问题及心得
- 通过此次实验我对面向接口编程有了更深的了解:
- 面向接口编程要遵循开-闭原则,使程序对接口的修改“关闭”,否则一旦修改接口(比如增加一个abstract方法),则实现该接口的类都要修改;对增加实现接口的类开放,这样可以使程序的功能易于扩充
- java只允许单继承,每个子类只能有一个父类;而使用接口,每个类却可以实现多个接口
- 此次实验中,既使用了接口回调,也使用了对象数组,我对对象数组也有了更深的理解。比如:
A[] a;
a = new A[10];
a[i] = new A();
前两步只是定义了数组a有10个元素,每个元素都是A类的对象,这些对象目前都是空对象;第三步后,数组中每个元素才是真正的对象
4 Java实验八,异常
一.实验目的
- 掌握自定义异常类的编写;
- 掌握使用try-catch 语句来处理异常。
二.实验内容及要求
车站检查危险品的设备,如果发现危险品会发出警告。编程模拟设备发现危险品:
- 编写一个Exception的子类DangerException,该子类可以创建异常对象,该异常对象调用showMessage)方法输出“属于危险品”。
- 编写一个Goods类,其中包括行李名称和是否为危险品的属性及对应的设置和获取方法。
- 编写一个Machine类,其中的checkGoods方法当发现行李为危险品时将抛出DangerException异常。
- 在主类的main()方法中定义n件行李,随机产生其是否为危险品的属性,并使用try-catch 语句让Machine类的实例调用checkGoods方法进行异常处理。
//DangerException.java
public class DangerException extends Exception{
String message;//字符串变量,是否为危险品
//属性为危险品时,设置变量值为"属于危险品"
public DangerException() {
message = "属于危险品";
}
//返回显示信息
String showMessage(){
return message;
}
}
//Goods.java
public class Goods {
String luggageName;//行李名
boolean isDanger;//行李属性。true:危险;false:不危险
//设置行李名
void setLuggageName(String luggageName){
this.luggageName = luggageName;
}
//返回行李名
String getLuggageName(){
return luggageName;
}
//随机设置行李属性
void setisDanger(boolean b){
isDanger = b;
}
//返回行李属性
boolean getIsDanger(){
return isDanger;
}
}
//Machine.java
import java.util.Random;
public class Machine {
void checkGoods(Goods goods) throws DangerException{
if (goods.isDanger){//若行李性质为true,抛出异常
throw new DangerException();
}
}
public static void main(String[] args){
Random random = new Random();
Machine machine = new Machine();
//行李名可选择范围
String name[] = {"vegetable", "apple", "gun", "candy", "cheery", "drink"};
Goods goods[] = new Goods[10];
System.out.printf("%-26s|%-13s|%s\n", "行李", "是否危险", "异常信息");
System.out.println("------------------------------------");
for (int i = 0; i < goods.length; i++) {
int index = random.nextInt(6);
boolean b = random.nextBoolean();
goods[i] = new Goods();
goods[i].setLuggageName(name[index]);//随机设置行李名
goods[i].setisDanger(b);//随机设置行李属性
//输出行李信息
System.out.printf("%-2d. %-12s|%-12s|", i+1, goods[i].getLuggageName(), goods[i].getIsDanger());
if (!goods[i].getIsDanger()) {
System.out.println();
}
try{
machine.checkGoods(goods[i]);//若危险属性为true,抛出异常
} catch (DangerException e){
System.out.println(e.showMessage());//输出异常信息
}
}//for
}//main
}
四.实验中的问题及心得
- try-catch:将可能出现异常的操作(代码)放在try部分,一旦try部分抛出异常,或调用某个可能抛出异常对象的方法,且该方法抛出了异常对象,则try部分立刻结束执行,转向catch部分(try-catch可由多个catch组成,分别处理相应异常)
- Java中所有异常类都是Exception类的子类,属于继承的范畴,对异常类的使用有助于加深对继承的理解
- Java允许自定义异常类,自定义的异常类可以处理类中独特的异常,自定义的异常类需是Exception类的子类
- java使用throw关键字抛出一个Exception子类的实例表示异常发生
5 Java实验九,String类和StringBuffer类实现字符串拷贝,并比较二者效率
一.实验目的
- 掌握String类和StringBuffer类等常用类;
- 掌握各常用类的实际运用方法。
二.实验内容及要求
编写一个Java程序,实现以下功能:
- 编写两个方法strCopy1和strCopy2,分别用String 类和StringBuffer类实现字符串的拷贝操作。
- 在主类的main()方法中分别调用stuCopy1和strCopy2完成字符串的拷贝操作,并比较二者的执行效率。
public class StringCopy {
/**
* @param str:待复制字符串
* @return:复制后的字符串
* 实现过程:1.创建空对象s
* 2.将str(String类型)中的字符逐个复制到s
*/
static String strCopy1(String str){
String s = "";
for (int i = 0; i < str.length(); i++) {
s += str.charAt(i);
/**
* 输出String对象 s 所存储的引用
* System.out.println(i + ". " + Integer.toHexString(s.hashCode()));
*/
}
return s;
}
/**
* @param str:待复制字符串
* @return:复制后的字符串
* 实现过程:1.创建空对象sBuffer
* 2.将str(String类型)中的字符逐个复制到sBuffer
*/
static StringBuffer strCopy2(String str){
StringBuffer sBuffer = new StringBuffer();
for (int i = 0; i < str.length(); i++) {
sBuffer.append(str.charAt(i));
/**
* 输出StringBuffer对象 sBuffer 所存储的引用
* System.out.println(i + ". " + Integer.toHexString(sBuffer.hashCode()));
*/
}
return sBuffer;
}
public static void main(String[] args) {
String sTest = "A string that is used to test";//待复制字符串
long startTime = System.nanoTime();//获取函数执行前时间
String s1 = StringCopy.strCopy1(sTest);
long endTime = System.nanoTime();//获取函数执行后时间
long time1 = endTime - startTime;//获取函数strCopy1耗时
System.out.println("String@strCpy1 耗时:" + time1 + " 纳秒; " + s1);
startTime = System.nanoTime();//获取函数执行前时间
StringBuffer sb2 = StringCopy.strCopy2(sTest);
endTime = System.nanoTime();//获取函数执行后时间
long time2 = endTime - startTime;//获取函数strCopy2耗时
System.out.println("StringBuffer@strCopy2 耗时:" + time2 + " 纳秒; " + sb2);
}
}
将方法strCpy1 和 strCpy2 中的注释去掉,结果如下
由运行结果可知,String类对象s所存储的字符序列的引用值随着s的修改而变化,而StringBuffer类对象Sbuffer存储的引用值只有一个(创建时得到)从未改变。所以,String类对象代表的值是常量,而StringBuffer类对象所代表的值不是常量,可以在原基础上修改。
四.实验中的问题及心得
String 类是常量,它们的值在创建之后不能更改。StringBuffer类支持可变的字符串
- String在修改时不会改变对象自身
在每次对String类型进行改变的时候其实都等同于生成了一个新的String对象,然后将指针指向新的String对象,所以经常改变内容的字符串最好不要用String。 - StringBuffer在修改时会改变对象自身
每次结果都会对StringBuffer对象本身进行操作,而不是生成新的对象,再改变对象引用。所以在字符串对象经常改变的情况下推荐使用StringBuffer。因此,用StringBuffer实现的 strCpy2比用String实现的strCpy1效率高
6 Java实验十,打字小游戏
一.实验目的
- 掌握常用组件与布局;
- 掌握各种事件处理器的使用。
二.实验内容及要求
编写一个简单的Java打字游戏,实现以下功能:
- 在窗口中随机产生一个A~Z之间的英文字母。
- 当输入正确的字母时,游戏自动产生下一个随机字母;当输入错误时,窗口中的字母不变化,直到输入正确的字母。
- 当按下Enter键时,停止游戏,并在窗口中显示用户打字的正确率;当按下Space键时,游戏重新开始。
import java.awt.*;
import javax.swing.*;
import javax.swing.border.EmptyBorder;
import java.awt.event.*;
import java.util.Random;
public class TypingGame extends JFrame {
JPanel contentPane;
JTextField inputField;
int clickCount, rightCount, randomInt;
JLabel resultLabel, inputLabel, showLabel, showResult, showChar;
/**contentPane:容器
* inputField: 输入字母文本框
* clickCount: 点击字母总数
* rightCount: 输入字母正确数
* randomInt: 随机数字,用于随机生成字母
* resultLabel:“正确率:”
* inputLabel: “请输入:”
* showLabel: “显示字母:”
* showResult: 以百分数形式显示正确率
* showChar: 显示随机生成的字母*/
public static void main(String[] args) {
EventQueue.invokeLater(new Runnable() {
public void run() {
try {
TypingGame frame = new TypingGame();
frame.setVisible(true);
} catch (Exception e) {
e.printStackTrace();
}
}
});
}
/**作用:随机生成一个字母
* @return 随机生成的字母*/
Character showLetter() {
Random random = new Random();
char c = 'A';
randomInt = random.nextInt(26);
return (char)(c + randomInt);
}
public TypingGame() {
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
setBounds(100, 100, 450, 300);
contentPane = new JPanel();
contentPane.setBorder(new EmptyBorder(5, 5, 5, 5));
setContentPane(contentPane);
contentPane.setLayout(null);
resultLabel = new JLabel("正确率:");
resultLabel.setFont(new Font("宋体", Font.PLAIN, 22));
resultLabel.setBounds(112, 96, 88, 18);
contentPane.add(resultLabel);
inputLabel = new JLabel("请输入:");
inputLabel.setFont(new Font("宋体", Font.PLAIN, 22));
inputLabel.setBounds(112, 142, 88, 18);
contentPane.add(inputLabel);
showLabel = new JLabel("显示字母:");
showLabel.setFont(new Font("宋体", Font.PLAIN, 22));
showLabel.setBounds(90, 50, 122, 18);
contentPane.add(showLabel);
showResult = new JLabel(" ");
showResult.setForeground(Color.RED);//设置字体为红色
showResult.setFont(new Font("宋体", Font.PLAIN, 24));
showResult.setBounds(211, 92, 114, 29);
contentPane.add(showResult);
showChar = new JLabel(" ");
showChar.setForeground(Color.BLUE);//设置字体为蓝色
showChar.setFont(new Font("宋体", Font.PLAIN, 25));
showChar.setBounds(210, 40, 85, 38);
contentPane.add(showChar);
inputField = new JTextField();
inputField.setFont(new Font("宋体", Font.PLAIN, 22));
inputField.addKeyListener(new KeyAdapter() {
@Override
public void keyPressed(KeyEvent e) {
/*按下空格键时开始游戏*/
if (e.getKeyCode() == KeyEvent.VK_SPACE) {
rightCount = 0;
clickCount = 0;
char c = showLetter();
showChar.setText(" " + c);
} /*记录文本框输入的字母数,并将之前输入的字母清空*/
else if (e.getKeyCode() >= KeyEvent.VK_A &&
e.getKeyCode() <= KeyEvent.VK_Z) {
clickCount++;
inputField.setText(null);
} /*按下回车键停止游戏,并以百分数形式显示正确率*/
else if (e.getKeyCode() == KeyEvent.VK_ENTER ) {
if (clickCount == 0) {
showResult.setText("0.00%");
} else {
double d = 100.0 * rightCount / clickCount;
String result = String.format("%.2f", d);
showResult.setText(result + "%");
}
}
}
@Override
public void keyReleased(KeyEvent e) {
/**show:值为随机生成的字母
* input:值为输入的字母
*/
String show = showChar.getText().trim();
String input = inputField.getText().trim();
/*若输入字母正确,则正确数加1并产生下一个随机字母*/
if (show.equals(input)) {
rightCount++;
char c = showLetter();
showChar.setText(" " + c);
}
}
});
inputField.setBounds(209, 139, 86, 29);
contentPane.add(inputField);
inputField.setColumns(10);
}
}