第十周
PTA作业
f7.1 jmu-Java-06异常-多种类型异常的捕获
如果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是所产生的异常。
import java.util.*;
public class Main {
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;
}catch(NumberFormatException e){
System.out.println("number format exception");
System.out.println(e);
}catch(IllegalArgumentException e){
System.out.println("illegal argument exception");
System.out.println(e);
}catch(Exception e) {
System.out.println("other exception");
System.out.println(e);
}
}//end while
sc.close();
}
}
f7.2 jmu-Java-06异常-finally
代码中向系统申请资源,到最后都要将资源释放。
现有一Resource
类代表资源类,包含方法:
open(String str)
打开资源,声明为抛出Exception
(包含出错信息)。
close()
方法释放资源,声明为抛出RuntimeException
(包含出错信息)
现在根据open(String str)
中str
的不同,打印不同的信息。str的内容分为4种情况:
fail fail
,代表open
和close
均会出现异常。打印open
的出错信息与close
的出错信息。
fail success
,代表open
抛出异常,打印open
出错信息。close
正常执行,打印resource release success
success fail
代表open
正常执行,打印resource open success
。close
抛出异常,打印close
出错信息。
success success
,代表open
正常执行,打印resource open success
,close
正常执行打印resource release success
。
注1:你不用编写打印出错信息的代码。
注2:捕获异常后使用System.out.println(e)
输出异常信息,e
是所产生的异常。
System.out.println("resource open success");
}catch(Exception e){
System.out.println(e);
}
try{
resource.close();
System.out.println("resource release success");
}catch(RuntimeException e){
System.out.println(e);
}
f7.3 (选做) jmu-Java-06异常-ArrayIntegerStack异常改进版
改造接口章节的ArrayIntegerStack
,为其pop()
、push()
、peek()
方法添加出错时抛出异常的功能。
ArrayIntegerStack
类内部使用数组实现。创建时,可指定内部数组大小。
属性:
int capacity
;//代表内部数组的大小
int top
;//代表栈顶指针。栈空时,初始值为0。
Integer[] arrStack
;//用于存放元素的数组
方法:
public Integer push(Integer item); //如果item为null,则不入栈直接返回null。如果栈满,抛出FullStackException(系统已有的异常类)。
public Integer pop(); //出栈。如果栈空,抛出EmptyStackException,否则返回
public Integer peek(); //获得栈顶元素。如果栈空,抛出EmptyStackException。
public Integer push(Integer item)throws FullStackException{
if(item==null) return null;
else if(top==capacity) throw new FullStackException();
else{
arrStack[top++]=item;
return item;
}
}
public Integer pop()throws EmptyStackException{
if(top==0) throw new EmptyStackException();
else{
return arrStack[--top];
}
}
public Integer peek()throws EmptyStackException{
if(top==0) throw new EmptyStackException();
else{
return arrStack[top-1];
}
}
7.1 jmu-Java-06异常-01-常见异常
main
方法
事先定义好一个大小为5的数组。
根据屏幕输入产生相应异常。
提示:可以使用System.out.println(e)
打印异常对象的信息,其中e
为捕获到的异常对象。
输入说明:
- arr 代表产生访问数组是产生的异常。然后输入下标,如果抛出
- ArrayIndexOutOfBoundsException异常则显示,如果不抛出异常则不显示。
- null,产生NullPointerException
- cast,尝试将String对象强制转化为Integer对象,产生ClassCastException。
- num,然后输入字符,转化为Integer,如果抛出NumberFormatException异常则显示。
其他,结束程序。
import java.util.*;
public class Main {
public static void main(String[] args){
int[] arr=new int[5];
Scanner cin=new Scanner(System.in);
while(cin.hasNext()){
String op=cin.next();
if(op.equals("arr")){
int index=cin.nextInt();
try{
arr[index] = 0;
}catch (ArrayIndexOutOfBoundsException e){
System.out.println(e);
}
}else if(op.equals("null")){
try{
String str=null;
System.out.println(str.length());
}catch(NullPointerException e) {
System.out.println(e);
}
}else if(op.equals("cast")){
try{
Object obj="Hello";
Integer num=(Integer) obj;
}catch(ClassCastException e){
System.out.println(e);
}
}else if(op.equals("num")){
String str = cin.next();
try{
Integer num=Integer.parseInt(str);
}catch (NumberFormatException e){
System.out.println(e);
}
}else{
break;
}
}
}
}
7.2 jmu-Java-06异常-02-使用异常机制处理异常输入
main
方法:
输入n,创建大小为n的int数组。
输入n个整数,放入数组。输入时,有可能输入的是非整型字符串,这时候需要输出异常信息,然后重新输入。
使用Arrays.toString
输出数组中的内容。
import java.util.*;
public class Main {
public static void main(String[] args){
Scanner cin=new Scanner(System.in);
int n=cin.nextInt();
int[] arr=new int[n];
for(int i=0;i<n;i++)
{
try{
String str=cin.next();
int x=Integer.parseInt(str);
arr[i]=x;
}catch(NumberFormatException e){
System.out.println(e);
i--;
}
}
System.out.println(Arrays.toString(arr));
cin.close();
}
}
7.3 jmu-Java-06异常-03-throw与throws
题目内容
编写类ArrayUtils
方法:public static double findMax(double[] arr,int begin, int end)
方法功能:用来返回arr数组中在下标begin与end-1之间(包括end-1)的最大值。
注意:必须使用throws
关键字声明findMax
。
方法说明:
要求begin<end,否则抛出相应的异常(IllegalArgumentException)。
begin不得小于0,end不得大于arr.length,否则也抛出异常。
注意:抛出异常时,应让用户知道错误发生的原因。
main方法:
- 输入n,创建大小为n的int数组。
- 输入n个整数,放入数组。
- 输入若干对整数,代表begin与end,然后调用ArrayUtils.findMax方法。当输入的不是整数类型字符串,则退出输入循环。
最后使用如下代码打印标识信息
try {
System.out.println(ArrayUtils.class.getDeclaredMethod("findMax", double[].class,int.class,int.class));
} catch (Exception e1) {
}
import java.util.*;
public class Main {
public static void main(String[] args){
Scanner cin=new Scanner(System.in);
int n=cin.nextInt();
double[] arr=new double[n];
for(int i=0;i<n;i++){
arr[i]=cin.nextDouble();
}
while(cin.hasNext()){
try{
int l=cin.nextInt();
int r=cin.nextInt();
double max=ArrayUtils.findMax(arr,l,r);
System.out.println(max);
}catch(InputMismatchException e){
break;
}catch (IllegalArgumentException e){
System.out.println(e);
}
}
try{
System.out.println(ArrayUtils.class.getDeclaredMethod("findMax", double[].class,int.class,int.class));
}catch (Exception e1) {
}
cin.close();
}
}
class ArrayUtils{
public static double findMax(double[] arr,int begin,int end) throws IllegalArgumentException{
if(begin>=end) {
throw new IllegalArgumentException("begin:" + begin + " >= end:" + end);
}
if(begin<0) {
throw new IllegalArgumentException("begin:" + begin + " < 0");
}
if (end>arr.length){
throw new IllegalArgumentException("end:" + end + " > arr.length");
}
double max=arr[begin];
for(int i=begin+1;i<end;i++){
if(arr[i]>max){
max=arr[i];
}
}
return max;
}
}
7.4 (选做) jmu-Java-06异常-04-自定义异常(综合)
定义Student类。
属性:
private String name;
private int score;
方法:
toString //自动生成
setter/getter //自动生成
改造setName //如果姓名首字母为数字则抛出IllegalNameException
public int addScore(int score) //如果加分后分数<0 或>100,则抛出IllegalScoreException,加分不成功。
main方法
输入new
则新建学生对象。然后输入一行学生数据,格式为姓名
年龄
,接着调用setName,addScore。否则跳出循环。
setName不成功则抛出异常,并打印异常信息,然后继续下一行的处理。
addScore不成功则抛出异常,并打印异常信息,然后继续下一行的处理。如果2、3都成功,则打印学生信息(toString
)
如果在解析学生数据行的时候发生其他异常,则打印异常信息,然后继续下一行的处理。
Scanner也是一种资源,希望程序中不管有没有抛出异常,都要关闭。关闭后,使用System.out.println("scanner closed")
打印关闭信息
import java.util.*;
public class Main {
public static void main(String[] args){
Scanner cin=new Scanner(System.in);
while(cin.hasNext()){
String op=cin.nextLine();
if(op.equals("new")){
Student student=new Student();
try{
String str=cin.nextLine();
String[] words=str.split(" ");
if(words.length!=2) throw new NoSuchElementException();
String name=words[0];
student.setName(name);
int score=Integer.parseInt(words[1]);
student.addScore(score);
System.out.println(student);
}catch(IllegalNameException | IllegalScoreException | NoSuchElementException e){
System.out.println(e);
}catch(Exception e){
System.out.println(e);
}
}
else break;
}
System.out.println("scanner closed");
cin.close();
}
}
class IllegalNameException extends Exception{
public IllegalNameException(String message){
super(message);
}
}
class IllegalScoreException extends Exception{
public IllegalScoreException(String message){
super(message);
}
}
class Student{
private String name;
private int score;
public String toString(){
return "Student [name=" + name + ", score=" + score + "]";
}
public void setName(String name) throws IllegalNameException{
if(Character.isDigit(name.charAt(0))){
throw new IllegalNameException("the first char of name must not be digit, name=" + name);
}
this.name=name;
}
public int addScore(int score) throws IllegalScoreException{
int newScore=this.score+score;
if(newScore<0||newScore>100) {
throw new IllegalScoreException("score out of range, score=" + newScore);
}
this.score=newScore;
return this.score;
}
}
7.5 (选做) jmu-java-日期类的基本使用
- 给定一个日期,判定是否为合法日期。如果合法,判断该年是否闰年,该日期是当年第几天、当月第几天、当周第几天。
- 给定起始日期与结束日期,判定日期是否合法且结束日期是否早于起始日期。如果均合法,输出结束日期与起始日期之间的相差的天数、月数、念书。
输入格式:
第一行输入一个日期字符串,格式为"YYYY-MM-dd"
第二行输入两个日期字符串,中间使用空格隔开。分别代表开始日期与结束日期。
输出格式:
如果第一行日期字符串非法,输出自定义的错误信息。
如果第一行日期有效,输出相关信息,如果是闰年要输出是闰年。
如果第二行两个日期,只要有一个无效。就输出相关错误信息。
如果第二行两个日期有效且结束日期不早于开始日期,输出相关信息。
import java.time.LocalDate;
import java.time.temporal.ChronoUnit;
import java.util.*;
public class Main {
public static void main(String[] args){
Scanner cin=new Scanner(System.in);
int cnt=0;
String s1=cin.next();
int[] months={0, 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31};
int year1=0,month1=0,day1=0;
int year2=0,month2=0,day2=0;
int year3=0,month3=0,day3=0;
for(int i=0;i<s1.length();i++)
{
if(s1.charAt(i)=='-') {cnt++;continue;}
int tmp=Integer.parseInt(s1.substring(i,i+1));
if(cnt==0) year1=year1*10+tmp;
else if(cnt==1) month1=month1*10+tmp;
else day1=day1*10+tmp;
}
int leap=0;
if(year1%400==0||(year1%100!=0&&year1%4==0)) leap=1;
if(month1>12||s1.length()!=10) System.out.println(s1+"无效!");
else{
int tmp=0;
if(month1==2&&leap==1) tmp=1;
if(day1>months[month1]+tmp) System.out.println(s1+"无效!");
else{
if(leap==1) System.out.println(s1+"是闰年.");
LocalDate date=LocalDate.of(year1,month1,day1);
int dayOfYear=date.getDayOfYear();
int dayOfMonth=date.getDayOfMonth();
int dayOfWeek=date.getDayOfWeek().getValue();
System.out.print(s1+"是当年第"+dayOfYear+"天,");
System.out.print("当月第"+dayOfMonth+"天,");
System.out.println("当周第"+dayOfWeek+"天.");
}
}
String s2=cin.next(),s3=cin.next();
cnt=0;
for(int i=0;i<s2.length();i++)
{
if(s2.charAt(i)=='-') {cnt++;continue;}
int tmp=Integer.parseInt(s2.substring(i,i+1));
if(cnt==0) year2=year2*10+tmp;
else if(cnt==1) month2=month2*10+tmp;
else day2=day2*10+tmp;
}
cnt=0;
for(int i=0;i<s3.length();i++)
{
if(s3.charAt(i)=='-') {cnt++;continue;}
int tmp=Integer.parseInt(s3.substring(i,i+1));
if(cnt==0) year3=year3*10+tmp;
else if(cnt==1) month3=month3*10+tmp;
else day3=day3*10+tmp;
}
if(month2>12||month3>12||s2.length()!=10||s3.length()!=10) System.out.println(s2+"或"+s3+"中有不合法的日期.");
else{
int leap2=0,leap3=0;
if(year2%400==0||(year2%100!=0&&year2%4==0)) leap2=1;
if(year3%400==0||(year3%100!=0&&year3%4==0)) leap3=1;
int tmp2=0,tmp3=0;
if(month2==2&&leap2==1) tmp2=1;
if(month3==2&&leap3==1) tmp3=1;
if(day2>months[month2]+tmp2||day3>months[month3]+tmp3) System.out.println(s2+"或"+s3+"中有不合法的日期.");
else{
LocalDate date2=LocalDate.of(year2,month2,day2);
LocalDate date3=LocalDate.of(year3,month3,day3);
if(date3.isBefore(date2)){
System.out.println(s3+"早于"+s2+",不合法!");
}
else{
long daysBetween=date2.until(date3,ChronoUnit.DAYS);
System.out.println(s3+"与"+s2+"之间相差"+daysBetween+"天,所在月份相差"+(month3-month2)+",所在年份相差"+(year3-year2)+".");
}
}
}
cin.close();
}
private static void exit(int i) {
}
}