目录
6-7 jmu-Java-06异常-多种类型异常的捕获 (10 分)
6-1 计算成绩 (15 分)
体操比赛计算选手成绩的办法是去掉一个最高分和最低分后再计算平均分,而学校考察一个班级的某科目的考试情况时,是计算全班同学的平均成绩。体操Gymnastics类和学校School类都实现了ComputerAverage接口,但是实现的方式不同。
接口方法定义:
ComputerAverage接口有 如下方法:
public double average(double x[]);
其中 x
是用户传入的参数。 函数须返回平均值。
裁判测试程序样例:
import java.util.Scanner;
public class Main {
public static void main(String[] args) {
double a[] ;
double b[];
Scanner sc=new Scanner(System.in);
String str1=sc.nextLine();
String[] str_a=str1.split(" ");
a=new double[str_a.length];
for(int i=0;i<str_a.length;i++)
a[i]=Double.parseDouble(str_a[i]);
String str2=sc.nextLine();
String[] str_b=str2.split(" ");
b=new double[str_b.length];
for(int i=0;i<str_b.length;i++)
b[i]=Double.parseDouble(str_b[i]);
CompurerAverage computer;
computer=new Gymnastics();
double result=computer.average(a); //computer调用average(double x[])方法,将数组a传递给参数x
//System.out.printf("%n");
System.out.printf("体操选手最后得分:%5.3f\n",result);
computer=new School();
result=computer.average(b); //computer调用average(double x[])方法,将数组b传递给参数x
System.out.printf("班级考试平均分数:%-5.2f",result);
}
}
/* 请在这里填写答案 */
//定义接口
//定义Gymnastics 类实现接口
//定义School类实现接口
输入样例:
9.89 9.88 9.99 9.12 9.69 9.76 8.97
89 56 78 90 100 77 56 45 36 79 98
输出样例:
体操选手最后得分:9.668
班级考试平均分数:73.09
我的答案:
//定义School类实现接口
interface ComputerAverage {
double average(double x[]);
}
class Gymnastics implements ComputerAverage {
@Override
public double average(double[] x) {
// TODO Auto-generated method stub
double total = 0;
double min,max;
min = x[0];
max = x[0];
for(int i = 0;i<x.length;i++) {
if(x[i] < min) {
min = x[i];
}
if(x[i] > max) {
max = x[i];
}
}
for(int j = 0;j<x.length;j++) {
total = total + x[j];
}
total = total - min - max;
return total/(x.length-2);
}
}
class School implements ComputerAverage {
@Override
public double average(double[] x) {
double total = 0;
for(int i = 0;i<x.length;i++) {
total = total + x[i];
}
return total/x.length;
}
}
6-2 货车的装载量 (15 分)
卡车要装载一批货物,货物由三种商品组成:电视、计算机、洗衣机。卡车需要计算出整批货物的重量。
要求有一个ComputerWeight接口,该接口中有一个方法:
public double computeWeight()
有三个实现该接口的类:Television、Computer和WashMachine. 这三个类通过实现接口给出自重。这3个类都有属性weight,并通过构造方法初始化,其中Television类的computeWeight()方法,返回weight值;Computer的computeWeight()方法,返回2倍weight值;WashMachine的computeWeight()方法,返回3倍weight值
有一个卡车Truck类,该类用ComputeWeight接口类型的数组作为成员(Truck类面向接口),那么该数组的元素就可以存放Television对象的引用、Computer对象的引用或WashMachine
对象的引用。程序能输出Truck对象所装载的货物的总重量。
接口方法定义:
ComputerWeight接口的方法:
public double computeWeight();
该方法 在不同实现类中实现不同,Television类的computeWeight()方法,返回weight值;Computer的computeWeight()方法,返回2倍weight值;WashMachine的computeWeight()方法,返回3倍weight值。
裁判测试程序样例:
import java.util.Scanner;
public class Main {
public static void main(String[] args) {
ComputerWeight[] goods=new ComputerWeight[650]; //650件货物
double[] a=new double[3];//存储Television,Computer,WashMachine对象weight属性初值
Scanner sc=new Scanner(System.in);
String str1=sc.nextLine();
String[] str_a=str1.split(" ");
for(int i=0;i<3;i++)
a[i]=Double.parseDouble(str_a[i]);
for(int i=0;i<goods.length;i++) { //简单分成三类
if(i%3==0)
goods[i]=new Television(a[0]);
else if(i%3==1)
goods[i]=new Computer(a[1]);
else if(i%3==2)
goods[i]=new WashMachine(a[2]);
}
Truck truck=new Truck(goods);
System.out.printf("货车装载的货物重量:%-8.5f kg\n",truck.getTotalWeights());
goods=new ComputerWeight[68]; //68件货物
for(int i=0;i<goods.length;i++) { //简单分成两类
if(i%2==0)
goods[i]=new Television(a[0]);
else
goods[i]=new WashMachine(a[2]);
}
truck.setGoods(goods);
System.out.printf("货车装载的货物重量:%-8.5f kg\n",truck.getTotalWeights());
}
}
/* 请在这里填写答案 */
//定义 接口ComputerWeight 代码写在下面
//定义类 Television 实现接口ComputerWeight 代码写在下面
//定义类Computer实现接口ComputerWeight 代码写在下面
//定义类WashMachine 实现接口ComputerWeight 代码写在下面
//类Truck ,实现相关成员方法 代码写在下面
输入样例:
3.5 2.67 13.8
输出样例:
货车装载的货物重量:10860.68000 kg
货车装载的货物重量:1526.60000 kg
我的答案:
interface ComputerWeight
{
double computerWeight();
}
class Truck
{
ComputerWeight[] goods = new ComputerWeight[650];
Truck(ComputerWeight[] goods) {
super();
this.goods = goods;
}
public void setGoods(ComputerWeight[] goods) {
this.goods = goods;
}
public double getTotalWeights()
{
double sum=0;
for(int i=0;i<goods.length;i++)
{
sum += goods[i].computerWeight();
}
return sum;
}
}
class Television implements ComputerWeight
{
double weight;
Television(double weight) {
super();
this.weight = weight;
}
@Override
public double computerWeight()
{
return weight;
}
}
class Computer implements ComputerWeight
{
double weight;
Computer(double weight)
{
this.weight=weight;
}
@Override
public double computerWeight()
{
return 2*weight;
}
}
class WashMachine implements ComputerWeight
{
double weight;
WashMachine(double weight)
{
this.weight=weight;
}
@Override
public double computerWeight()
{
return 3*weight;
}
}
6-3 锥体体积计算 (10 分)
定义一个接口IgetArea,有方法double getArea(); 用于计算形状面积,定义另外一个接口IgetPerimeter,有方法 double getPerimeter();用于计算形状周长。接口IShape 有常量 PI=3.14,继承 接口IgetArea和IgetPerimeter
定义一个直角三角形类(regular triangle)RTriangle类,实现接口IShape。两条直角边作为Triangle类的私有成员,类中包含参数为2条直角边的构造方法。
定义一个圆形类Circle,实现接口IShape。半径r作为Circle类的私有成员,类中包含参数为r的构造方法。
定义一个锥体类Cone ,类中有一个IShape类型的成员IS,和锥体高h的成员,包含一个构造方法给IS和h赋初值,另外还有一个 public double getVolume() 方法,用于计算锥体的体积
接口定义:
interface IgetArea{
double getArea();
}
interface IgetPerimeter{
double getPerimeter();
}
裁判测试程序样例:
import java.lang.*;
import java.util.Scanner;
public class Main {
public static void main(String[] args) {
Scanner input = new Scanner(System.in);
double a = input.nextDouble();
double b = input.nextDouble();
double r=input.nextDouble();
double h=input.nextDouble();
IShape[] is=new IShape[2];
is[0]=new RTriangle(a,b);
is[1]=new Circle(r);
Cone cn1;
for(int i=0;i<2;i++) {
cn1=new Cone(is[i],h);
String vol=String.format("%.2f", cn1.getVolume());
String p=String.format("%.2f",is[i].getPerimeter());
System.out.println("Volume"+i+"="+vol+" Perimeter="+p);
}
}
}
/* 将其他代码填写在下面 */
输入样例:
3 4 5 6
输出样例:
Volume0=12.00 Perimeter=12.00
Volume1=157.00 Perimeter=31.40
我的答案:
interface IgetArea{
double getArea();
}
interface IgetPerimeter{
double getPerimeter();
}
interface IShape extends IgetArea,IgetPerimeter{
double PI = 3.14;
double getArea();
double getPerimeter();
}
class RTriangle implements IShape{
private double a,b;
public RTriangle(double a2, double b2) {
this.a = a2;
this.b = b2;
// TODO Auto-generated constructor stub
}
@Override
public double getArea() {
// TODO Auto-generated method stub
double area = 0;
area = a*b*0.5;
return area;
}
@Override
public double getPerimeter() {
// TODO Auto-generated method stub
double Perimeter=0;
Perimeter = a+b+Math.sqrt(Math.pow(a,2)+Math.pow(b,2));
return Perimeter;
}
}
class Circle implements IShape{
private double r;
public Circle(double r2) {
this.r = r2;
// TODO Auto-generated constructor stub
}
@Override
public double getArea() {
// TODO Auto-generated method stub
double area;
area = r*PI*r;
return area;
}
@Override
public double getPerimeter() {
// TODO Auto-generated method stub
double Perimeter;
Perimeter = r*2*PI;
return Perimeter;
}
}
class Cone{
IShape IS;
double h;
Cone(IShape iS, double h) {
IS = iS;
this.h = h;
}
public double getVolume()
{
double v;
v=IS.getArea()*h/3;
return v;
}
}
6-4 浅拷贝与深拷贝问题 (10 分)
Java中的对象拷贝(Object Copy)指的是将一个对象的所有属性(成员变量)拷贝到另一个有着相同类类型的对象中去。举例说明:比如,对象A和对象B都属于类S,具有属性a和b。那么对对象A进行拷贝操作赋值给对象B就是:B.a=A.a; B.b=A.b;
浅拷贝(Shallow Copy):①对于数据类型是基本数据类型的成员变量,浅拷贝会直接进行值传递,也就是将该属性值复制一份给新的对象。因为是两份不同的数据,所以对其中一个对象的该成员变量值进行修改,不会影响另一个对象拷贝得到的数据。
②对于数据类型是引用数据类型的成员变量,比如说成员变量是某个数组、某个类的对象等,那么浅拷贝会进行引用传递,也就是只是将该成员变量的引用值(内存地址)复制一份给新的对象。因为实际上两个对象的该成员变量都指向同一个实例。在这种情况下,在一个对象中修改该成员变量会影响到另一个对象的该成员变量值。为了解决这个问题,引入深拷贝:
深拷贝 对于引用类型成员变量,比如数组或者类对象,深拷贝会在目标对象内新建一个对象空间,然后拷贝原对象对应成员变量实体对象里面的内容,所以它们指向了不同的内存空间。改变其中一个,不会对另外一个也产生影响。
在Java中 有一个方法为protected Object clone() throws CloneNotSupportedException,这个方法就是进行的浅拷贝。某个类要实现深拷贝 这个类需要实现Cloneable接口,然后对clone方法进行重写
重写clone方法定义:
class Car implements Cloneable{ //定义一个Car类 实现接口Cloneable
//成员变量定义
public Object clone(){ //重写clone方法
Car c = null;
try {
c = (Car)super.clone(); //调用父类Object实现浅拷贝
} catch (CloneNotSupportedException e) {
e.printStackTrace();
}
//编写代码实现深拷贝
}
//编写代码实现其他成员方法
}
Car
类中包含
1.属性:
private String name;
private CarDriver driver;
private int[] scores;
2.无参构造函数
public Car() {
}
3.成员方法:
@Override
public String toString() {
return "Car [name=" + name + ", driver=" + driver + ", scores=" + Arrays.toString(scores) + "]";
}
4.其他get和set成员方法:public String getName() ,public CarDriver getDriver(),public int[] getScores()和
public void setName(String name),public void setDriver(CarDriver dr),public void setScores(int[] s)
及 clone
方法实现深拷贝
CarDriver
为已定义好的类,如下:
class CarDriver {
private String name;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public CarDriver() {}
public String toString() {
return "CarDriver [name=" + name+"]";
}
}
public class Main {
public static void main(String[] args) {
Scanner sc=new Scanner(System.in);
int i=sc.nextInt();
switch(i) {
case 1: //深拷贝
CarDriver cd=new CarDriver();
Car c1=new Car();
c1.setDriver(cd);
cd.setName("d1");
c1.setName("car1");
int[] s=new int[2];
c1.setScores(s);
Car d1=(Car)c1.clone();
System.out.println("c1:"+(c1==d1)+" driver:"+(c1.getDriver()==d1.getDriver())+" scores:"+(c1.getScores()==d1.getScores()));
System.out.println(c1.toString()+" "+d1.getName()+" "+d1.getDriver().getName());
break;
case 2: //
Car c2=new Car();
Car d2=(Car)c2.clone();
System.out.println("c2:"+(c2==d2)+" driver:"+c2.getDriver()+" "+(c2.getDriver()==d2.getDriver())+" scores:"+c2.getScores()+" "+(c2.getScores()==d2.getScores()));
break;
case 3:
CarDriver cd1=new CarDriver();
Car c3=new Car();
c3.setDriver(cd1);
Car d3=(Car)c3.clone();
System.out.println("c3:"+(c3==d3)+" driver:"+c3.getDriver()+" "+(c3.getDriver()==d3.getDriver())+" scores:"+c3.getScores()+" "+(c3.getScores()==d3.getScores()));
break;
case 4:
//CarDriver cd3=new CarDriver();
Car c4=new Car();
//c4.setDriver(cd3);
int[] s1=new int[2];
c4.setScores(s1);
Car d4=(Car)c4.clone();
System.out.println("c4:"+(c4==d4)+" driver:"+c4.getDriver()+" "+(c4.getDriver()==d4.getDriver())+" scores:"+" "+(c4.getScores()==d4.getScores()));
break;
}
}
}
//现在 你只需要在 下面 写上 Car类的完整代码 即可
我的答案:
class Car implements Cloneable{
private String name;
private CarDriver driver;
private int[] scores;
public Car() {
}
public String getName() {
return name;
}
public CarDriver getDriver() {
return driver;
}
public int[] getScores() {
return scores;
}
public void setName(String name){
this.name=name;
}
public void setDriver(CarDriver dr){
this.driver=dr;
}
public void setScores(int[] s){
this.scores=s;
}
@Override
public String toString() {
return "Car [name=" + name + ", driver=" + driver + ", scores=" + Arrays.toString(scores) + "]";
}
public Object clone(){
Car c = null;
try {
c = (Car)super.clone();
} catch (CloneNotSupportedException e) {
e.printStackTrace();
}
if(driver!=null) {
c.driver=new CarDriver();
if(driver.getName()!=null)
c.driver.setName(new String(this.driver.getName()));
}
if(name!=null)
c.name=new String(this.name);
if(scores!=null) {
c.scores=new int[this.scores.length];
for(int i=0;i<this.scores.length;i++){
c.scores[i]=this.scores[i];
}
}
return c;
}
}
6-5 系统常用标准异常类 (10 分)
常用异常类NumberFormatException,IndexOutOfBoundsException、ArithmeticException等,本程序,建立一个Test_Exception类,里面有一个test方法,用于检测以上异常对象的发生并输出相应信息。 比如发生NumberFormatException异常,输出"数据格式异常";发生IndexOutOfBoundsException异常,输出"越界异常";发生ArithmeticException异常,输出"算术运算异常"。 ##。# Test_Exception类定义:
class Test_Exception{
void test() {
int n = 0,m = 0,t = 1000;
int[] a=new int[4];
int[] b=null;
Scanner sc=new Scanner(System.in);
String str=sc.nextLine();
try {
m = Integer.parseInt(str);
t=t/m;
a[m]=m;
b[0]=m;
}
//catch部分需要你们自己填写
catch(...){...}
catch(...){...}
catch(...){...}
catch(Exception e) {
System.out.println("Exception:"+e.getMessage());
} //先catch子类Exception,后catch父类
}
}
前面3个catch 需要你 编写,发生对应异常,输出相应信息。
裁判测试程序样例:
在这里给出函数被调用进行测试的例子。例如:
import java.util.Scanner;
public class Main{
public static void main(String[] args) {
Test_Exception te=new Test_Exception();
te.test();
}
}
/* 请在这里编写完整 Test_Exception类 */
输入样例:
0
输出样例:
算术运算异常
答案:
class Test_Exception
{
void test()
{
int n = 0,m = 0,t = 1000;
int[] a=new int[4];
int[] b=null;
Scanner sc=new Scanner(System.in);
String str=sc.nextLine();
try
{
m = Integer.parseInt(str);
t=t/m;
a[m]=m;
b[0]=m;
}
//catch部分需要你们自己填写
catch(NumberFormatException e){
System.out.println("数据格式异常");
}
catch(IndexOutOfBoundsException e){
System.out.println("越界异常");
}
catch(ArithmeticException e){
System.out.println("算术运算异常");
}
catch(Exception e) {
System.out.println("Exception:"+e.getMessage());
} //先catch子类Exception,后catch父类
}
}
6-6 检查物品是否为次品 (10 分)
工厂检查产品次品的设备,如果发现是次品就发出警告。编程模拟设备发现次品过程。
编写一个产品类Product,有成员变量name和isDefect(是否次品),有get和set方法。
编写一个Exception的子类DefectException,该子类message属性,有构造方法DefectException() 将"次品"赋值给message成员,有toShow()方法输出message的值
编写一个Machine类,该类的方法checkProduct(Product product)当发现参数product为次品时(product的 isDefect属性为true),将抛出DefectException异常对象。
程序在主类的main方法中的try…catch语句的try部分让Machine类的实例调用checkProduct方法,如果发现次品就在try…catch语句的catch部分处理次品。
设计的类定义:
class Product { //完整编写
boolean isDefect;
String name;
//补充代码
}
class DefectException extends Exception { //完整编写
String message;
//补充代码
}
class Machine {
public void checkProduct(Product product) throws DefectException {
if(product.isDefect()) {
DefectException defect=new DefectException();
//【代码1】 //抛出defect
}
else {
System.out.print(product.getName()+"不是次品! ");
}
}
}
裁判测试程序样例:
import java.util.Scanner;
public class Main {
public static void main(String[] args) {
Machine machine = new Machine();
String name[] ;
Scanner sc=new Scanner(System.in);
name=sc.nextLine().split(" ");
Product [] products = new Product[name.length]; //检查6件货物
for(int i= 0;i<name.length;i++) {
products[i] = new Product();
if(i%2==0) {
products[i].setIsDefect(false);
products[i].setName(name[i]);
}
else {
products[i].setIsDefect(true);
products[i].setName(name[i]);
}
}
for(int i= 0;i<products.length;i++) {
try {
machine.checkProduct(products[i]);
System.out.println(products[i].getName()+"检查通过");
}
catch(DefectException e) {
e.toShow();//【代码2】 //e调用toShow()方法
System.out.println(products[i].getName()+"被禁止!");
}
}
}
}
/* 将完整的Product类, DefectException类 和Machine类写在下面*/
输入样例:
电脑 炸药 西服 硫酸 手表 硫磺
输出样例:
电脑不是次品! 电脑检查通过
次品! 炸药被禁止!
西服不是次品! 西服检查通过
次品! 硫酸被禁止!
手表不是次品! 手表检查通过
次品! 硫磺被禁止!
答案:
class Product { //完整编写
boolean isDefect;
String name;
//补充代码
public boolean isDefect() {
return isDefect;
}
public void setIsDefect(boolean isDefect) {
this.isDefect = isDefect;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
}
class DefectException extends Exception { //完整编写
String message;
//补充代码
DefectException(){
}
void toShow() {
System.out.print("次品!");
}
}
class Machine {
public void checkProduct(Product product) throws DefectException {
if(product.isDefect()) {
DefectException defect=new DefectException();
//【代码1】 //抛出defect
throw defect;
}
else {
System.out.print(product.getName()+"不是次品! ");
}
}
}
6-7 jmu-Java-06异常-多种类型异常的捕获 (10 分)
如果try块中的代码有可能抛出多种异常,且这些异常之间可能存在继承关系,那么在捕获异常的时候需要注意捕获顺序。
补全下列代码,使得程序正常运行。
裁判测试程序:
public static void main(String[] args) {
Scanner sc = new Scanner(System.in);
while (sc.hasNext()) {
String choice = sc.next();
try {
if (choice.equals("number"))
throw new NumberFormatException();
else if (choice.equals("illegal")) {
throw new IllegalArgumentException();
} else if (choice.equals("except")) {
throw new Exception();
} else
break;
}
/*这里放置你的答案*/
}//end while
sc.close();
}
###输出说明
在catch
块中要输出两行信息:
第1行:要输出自定义信息。如下面输出样例的number format exception
第2行:使用System.out.println(e)
输出异常信息,e是所产生的异常。
输入样例
number illegal except quit
输出样例
number format exception
java.lang.NumberFormatException
illegal argument exception
java.lang.IllegalArgumentException
other exception
java.lang.Exception
答案:
catch(Exception e){
if (choice.equals("number"))
System.out.println ("number format exception");
if (choice.equals("illegal"))
System.out.println ("illegal argument exception");
if (choice.equals("except"))
System.out.println ("other exception");
System.out.println (e);
}