第09章_异常处理拓展练习(代码阅读题,简答题,编程题)

文章目录

  • 第09章_异常处理拓展练习
    • 代码阅读题
      • 1、阅读代码,分析结果
      • 2、阅读代码,分析结果
      • 3、阅读代码,分析结果
      • 4、阅读代码,分析结果
      • 5、阅读代码,分析结果
      • 6、阅读代码,分析结果
      • 7、阅读代码,分析结果
      • 8、笔试题:补充代码
    • 简答题
      • 9、请描述异常的继承体系
      • 10、请描述你对错误(Error)的理解
      • 11、请描述你对异常(Exception)的理解
      • 12、请描述你对运行时异常(RuntimeException)的理解
      • 13、throw与throws的区别
      • 14、异常处理方式有几种,分别是什么?详细阐述每种方式对异常是如何处理的
      • 15、请列举常见异常,并说明产生原因。
    • 编程题
      • 16、新年倒计时
      • 17、演示OOM错误
      • 18、克隆对象
      • 19、输入两个整数相除
      • 20、数组工具类
      • 21、图形工具类,矩形工具类
      • 22、游戏角色
      • 23、银行账户类
      • 24、用户注册

第09章_异常处理拓展练习


代码阅读题

1、阅读代码,分析结果

	public static void main(String[] args) {
		int test = test(3,5);
		System.out.println(test);
	}

	public static int test(int x, int y){
		int result = x;
		try{
			if(x<0 || y<0){
				return 0;
			}
			result = x + y;
			return result;
		}finally{
			result = x - y;
		}
	}
/*
 * (1)finally块中的代码是无论try中是否发生异常,也无论catch是否可以捕获异常,
 * 也不管try和catch中是否有return语句,都会执行的部分
 * (2)如果finally中有return语句,那么try...catch...finally结构
 * 一定从finally中的return回去
 * (3)如果finally中没有return语句,那么try...catch...finally结构
 * 才会从try或catch中的return回去,但是finally值中代码不会影响最终的返回值
 */

2、阅读代码,分析结果

public class Exercise2 {
	public static void main(String[] args) {
		try{
			return;
		}finally{
			System.out.println("finally");
		}
	}
}
/*
 * finally块中的代码是无论try中是否发生异常,也无论catch是否可以捕获异常,
 * 也不管try和catch中是否有return语句,都会执行的部分
 */

3、阅读代码,分析结果

public class Exercise3 {
	{
		System.out.println("a");
	}
	static{
		System.out.println("b");
	}
	Test03(){
		System.out.println("c");
	}
	public static String getOut(){
		try{
			return "1";
		}catch(Exception e){
			return "2";
		}finally{
			return "3";
		}
	}
	public static void main(String[] args) {
		System.out.println(getOut());
	}
}
/*
 * (1)main()执行之前,需要先完成所在类的初始化
 * (2)类初始化由两部分代码组成:①静态变量的显式赋值代码②静态代码块
 * (3)没有创建对象,不会执行实例初始化相关的代码
 * (4)finally块中的代码是无论try中是否发生异常,也无论catch是否可以捕获异常,
 * 也不管try和catch中是否有return语句,都会执行的部分
 * (5)如果finally中有return语句,那么try...catch...finally结构
 * 一定从finally中的return回去
 */

4、阅读代码,分析结果

public class Exercise4 {
	static int i = 0;
	public static void main(String[] args) {
		System.out.println(test());
	}

	public static int test(){
		try{
			return ++i;
		}finally{
			return ++i;
		}
	}
}
/*
 * (1)finally块中的代码是无论try中是否发生异常,也无论catch是否可以捕获异常,
 * 也不管try和catch中是否有return语句,都会执行的部分
 * (2)如果finally中有return语句,那么try...catch...finally结构
 * 一定从finally中的return回去,但是try和catch中的return语句中返回值的表达式会执行。
 * (3)如果finally中没有return语句,那么try...catch...finally结构
 * 才会从try或catch中的return回去,但是finally值中代码不会影响最终的返回值
 */

5、阅读代码,分析结果

public class Exercise5 {
	public static void main(String[] args) {
		int a = -1;
		try{
			if(a>0){
				throw new RuntimeException("");
			}else if(a<0){
				throw new IOException("");
			}else{
				return ;
			}
		}catch(IOException ioe){
			System.out.println("IOException");
		}catch(Throwable e){
			System.out.println("Throwable");
		}finally{
			System.out.println("finally");
		}
	}
}
/*
 * (1)throw用于手动抛出异常
 * (2)无论是JVM抛出的异常还是throw抛出的异常都需要catch处理
 * (3)catch是多分支结构,从上到下按顺序匹配,只会进入第一个匹配上的catch分支
 * (4)finally块中的代码是无论try中是否发生异常,也无论catch是否可以捕获异常,
 * 也不管try和catch中是否有return语句,都会执行的部分
 */

6、阅读代码,分析结果

public class Exercise6 {
	public static int fun(){
		int result = 5;
		try{
			result = result / 0;
			return result;
		}catch(Exception e){
			System.out.println("Exception");
			result = -1;
			return result;
		}finally{
			result = 10;
			System.out.println("I am in finally.");
		}
	}
	public static void main(String[] args) {
		int x = fun();
		System.out.println(x);
	}
}

/*
 * (1)finally块中的代码是无论try中是否发生异常,也无论catch是否可以捕获异常,
 * 也不管try和catch中是否有return语句,都会执行的部分
 * (2)如果finally中有return语句,那么try...catch...finally结构
 * 一定从finally中的return回去
 * (3)如果finally中没有return语句,那么try...catch...finally结构
 * 才会从try或catch中的return回去,但是finally值中代码不会影响最终的返回值
 */

7、阅读代码,分析结果

public class Exercise7 {
public static int aMethod(int i)throws Exception{
		try{
			return i / 10;
		}catch(Exception ex){
			throw new Exception("exception in aMethod");
		}finally{
			System.out.println("finally");
		}
	}
	public static void main(String[] args) {
		try {
			aMethod(0);
		} catch (Exception e) {
			System.out.println("exception in main");
		}
	}
}  
/*
 * (1)finally块中的代码是无论try中是否发生异常,也无论catch是否可以捕获异常,
 * 也不管try和catch中是否有return语句,都会执行的部分
 * (2)throw用于手动抛出异常
 * (3)throws用于将异常抛给调用者处理
 */

8、笔试题:补充代码

给出下面的不完整的方法:

1
2	{ int success = connnect();
3		if(success == -1){
4			throw new TimedOutException();
5		}
6	}

TimedOutException 不是一个 RuntimeException,继承于Exception。下面的哪些声明可以被加入第1行完成此方法的声明?( B、C)

A. public void method()
B. public void method() throws Exception
C. public void method() throws TimedOutException
D. public void method() throw TimedOutException
E. public throw TimedOutException void method()

简答题

9、请描述异常的继承体系

Java把所有的非正常情况分成两种:异常(Exception)和错误(Error),它们都继承Throwable父类。

10、请描述你对错误(Error)的理解

Error错误,一般是指与虚拟机相关的问题,如系统崩溃、虚拟机错误、动态链接失败等,这种错误无法恢复或不可能捕获,将导致应用程序中断。
通常应用程序无法处理这些错误,因此应用程序不应该试图使用catch块来捕获Error对象。
在定义该方法时,也无须在其throws子句中声明该方法可能抛出Error及其任何子类

11、请描述你对异常(Exception)的理解

Exception分为两大类:

运行时异常 [即程序运行时,发生的异常]。
编译时异常 [即编程时编译器检查出的异常,Checked异常]。
所有的RuntimeException类及其子类的实例被称为Runtime异常;不是RuntimeException类及其子类的异常实例则被称为Checked异常。

12、请描述你对运行时异常(RuntimeException)的理解

RuntimeException即程序运行时发生的异常,编译时检测不到这种异常,程序运行后,抛出异常
Runtime异常则更加灵活,Runtime异常无须显式声明抛出,如果程序需要捕获Runtime异常,也可以使用trycatch块来实现

13、throw与throws的区别

区别一:throw 是语句抛出一个异常;throws 是方法抛出一个异常;

区别二:throws可以单独使用,但throw不能;

区别三:throw要么和try-catch-finally语句配套使用,要么与throws配套使用。但throws可以单独使用,然后再由处理异常的方法捕获

14、异常处理方式有几种,分别是什么?详细阐述每种方式对异常是如何处理的

在java中,有一组关键字被用来进行异常的捕捉,它就是try-catch-finally。代码如下所示:

 try{
    // 尝试执行的可能会抛出异常的代码
 }catch(异常类型1 异常的变量名1){
    // 当异常抛出时,根据异常的类型和变量名执行对应的catch语句
    //catch语句用来捕获异常。
 }catch(异常类型2 异常的变量名2){
    // 程序代码
 }finally{
    // 不管最终如何,一定要执行的语句,一般做清理类型等收尾善后性质的工作
    //finally不是必要出现的
 }

此外,还有一组关键字被用来抛出异常,它就是throws/throw关键字:
如果一个方法没有捕获一个可查异常,那么该方法必须使用 throws 关键字来声明。throws 关键字放在方法签名的尾部。
也可以使用 throw 关键字抛出一个异常,无论它是新实例化的还是刚捕获到的。

下面方法的声明抛出一个 RemoteException 异常:
import java.io.*;
public class className{
   public void deposit(double amount) throws RemoteException{
      // Method implementation
      throw new RemoteException();
   }
   //Remainder of class definition
}
一个方法可以声明抛出多个异常,多个异常之间用逗号隔开。

例如,下面的方法声明抛出 RemoteExceptionInsufficientFundsExceptionimport java.io.*;
public class className{
   public void withdraw(double amount) throws RemoteException,InsufficientFundsException{
       // Method implementation
   }
   //Remainder of class definition
}

15、请列举常见异常,并说明产生原因。

(1)java.lang.NullPointerException——空指针异常,
   出现原因:调用了未经初始化或者不存在的对象。

(2)java.lang.ClassNoFoundException—— 指定类找不到,
   出现原因:类的名称和路径加载错误,通常是试图通过字符串来加载某个类时可能引发异常。

(3)java.lang.NumberFormatException——字符串转换为数字异常,
   出现原因:字符串数据中包含非数字型字符。

(4)java.lang.IndexOutOfBoundsException——数组下标越界异常,
   出现原因:调用的下标超出了数组的范围。
    
(5)java.lang.IllegalArgumentException—— 方法传递参数错误,
   出现原因:在很多j2me的类库中的方法,在一些情况下会引发这样的错误,比如本该是正数的被写成了负数。
     
(6)java.lang.ClassCastException——数据类型转换异常,
   出现原因:强制类型转换类型不匹配时出现此异常。
     
(7)java.lang.illegalaccessexception——没有访问权限,
   出现原因:当程序要调用一个类时,但是当前的方法没有对该类的访问权限。
     
(8)java.lang.SQLException——SQL异常,
   出现原因:在执行sql语句时出现的各种异常。
     
(9)java.lang.InstantiationException——实例化异常,
   出现原因:指不能实例化对象而出现的异常。
     
(10)java.lang.NoSuchMethodExceptioin—— 方法不存在异常,
   出现原因:这个异常出现的原因有两个,第一,缺少某些jar文件;第二,某些jar文件有重复。
  
(11)java.lang.arithmeticexception——数学运算异常,
   出现原因:出现不符合定义的运算,例如除以零。

编程题

16、新年倒计时

(1)已知java.lang包下有一个Thread类,这个类有一个静态方法:

public static void sleep(long millis) throws InterruptedException

调用这个方法可以实现程序休眠millis毫秒(1000毫秒=1秒)。

(2)在测试类的main中,在for循环中调用上面的sleep方法,实现新年倒计时10,9,8,…,1,新年到!

  • 每循环1次执行一次sleep方法,可以模拟1秒输出一个数字。
  • 使用try…catch处理异常
public class Exercise16 {
    public static void main(String[] args) {
        for (int i = 10; i >=1 ; i--) {
            System.out.println(i);
            try {
                Thread.sleep(1000);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
        System.out.println("新年到!");
    }
}

17、演示OOM错误

public class Exercise17 {
	public static void main(String[] args) {
		int[] arr = new int[Integer.MAX_VALUE];
	}
}

/*
设置JVM参数
-verbose:gc
-Xms20M
-Xmx20M
-Xmn10M
-XX:+PrintGCDetails
-XX:SurvivorRatio=8

其中:
Xms:最小堆
Xmx:最大堆
Xmn:新生代的大小
PrintGCDetails:打印GC日志
SurvivorRatio:Eden区和Survivor比例
 */
public class Exercise17 {
	public static void main(String[] args) {
		ArrayList list=new ArrayList();
	    //通过不断的创建对象达到OOM
	    while (true){
	        list.add(new Object());
	    }
	}
}

18、克隆对象

(1)声明一个Rectangle矩形类,

  • 属性:length和width
  • 无参和有参构造
  • 提供get/set方法
  • 重写toString方法,返回矩形对象信息
  • 实现java.lang.Cloneable接口,重写Object类的clone()方法

(2)在测试类中,创建一个Rectangle矩形对象,调用矩形对象的clone方法克隆出一个新对象,

  • 使用try…catch处理CloneNotSupportedException异常,在catch中手动创建一个矩形对象,并用原来的矩形对象的length和width为新创建的矩形对象的length和width赋值
public class Rectangle implements Cloneable{
    private double length;
    private double width;

    public Rectangle() {
    }

    public Rectangle(double length, double width) {
        this.length = length;
        this.width = width;
    }

    public double getLength() {
        return length;
    }

    public void setLength(double length) {
        this.length = length;
    }

    public double getWidth() {
        return width;
    }

    public void setWidth(double width) {
        this.width = width;
    }

    @Override
    public String toString() {
        return "Rectangle{" +
                "length=" + length +
                ", width=" + width +
                '}';
    }

    @Override
    protected Object clone() throws CloneNotSupportedException {
        return super.clone();
    }
}

public class Exercise18 {
    public static void main(String[] args) {
        Rectangle r1 = new Rectangle(4,2);
        System.out.println("r1 = " + r1);
        Rectangle r2;
        try {
            r2= (Rectangle) r1.clone();
        } catch (CloneNotSupportedException e) {
            e.printStackTrace();
            r2 = new Rectangle();
            r2.setLength(r1.getLength());
            r2.setWidth(r1.getLength());
        }
        System.out.println("r2 = " + r2);
    }
}

19、输入两个整数相除

从键盘输入两个整数,求它们的商。尽量考虑和避免异常,无法避免的使用try…catch处理。

(1)如果用户输入的非整数,使用try…catch处理,并且让用户重新输入

(2)如果用户输入的除数为0,请用户重新输入。

public class Exercise19 {
    public static void main(String[] args) {
        Scanner input = new Scanner(System.in);
        
        int a ;
        while(true) {
            try {
                System.out.print("请输入被除数:");
                a = input.nextInt();
                break;
            } catch (Exception e) {
                input.nextLine();
                System.out.println("输入错误,请重新输入!");
            }
        }
        int b ;
        while(true) {
            try {
                System.out.print("请输入除数:");
                b = input.nextInt();
                if(b==0){
                    System.out.println("除数不能为0,请重新输入");
                }else {
                    break;
                }
            } catch (Exception e) {
                input.nextLine();
                System.out.println("输入错误,请重新输入!");
            }
        }

        System.out.println(a + "/" + b + "=" +  a/b);

        input.close();
    }
}

20、数组工具类

(1)声明数组工具类ArrayTools(自己写)

  • 声明public static int max(int[] arr)返回数组的最大值。
  • 声明public static boolean fromSmallToLarge(int[] arr)判断数组元素是否从小到大排序,如果是返回true,否则返回false。
  • 声明public static int binarySearch(int[] arr ,int value)使用二分查找法返回value元素在arr的下标,如果有多个,返回第一次找到它的下标,如果不存在返回-1。另外,如果arr数组不是按照升序排列的数组抛出new RuntimeException(“数组元素不是从小到大”)异常对象。
  • 以上三个方法都要对arr数组进行检查,如果arr为null抛出new NullPointerException(“数组不能为null”)异常对象,如果arr.length为0抛出new ArrayIndexOutOfBoundsException(“数组不能没有元素”)
  • 声明public static String toString(int[] arr)返回数组的元素,如果arr为null,返回"“,如果arr.length为0,返回”[]“,否则返回元素,例如:“[1,2,3,4,5]”。

(2)运行如下测试类代码,对不同的arr分别测试(不用写,直接用)

public class Exercise20 {
    public static void main(String[] args) {
      //  int[] arr = null;
       // int[] arr = {}
        // int[] arr = {3,2,1,4};
        int[] arr = {1,5,16,28,39};

        try {
            System.out.println(ArrayTools.toString(arr));
            System.out.println("最大值:" + ArrayTools.max(arr));
            System.out.println("查找5:" + ArrayTools.binarySearch(arr,5));
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
}

ArrayTools工具类代码:

public class ArrayTools {
    private static void checkArr(int[] arr){
        if(arr == null){
            throw new NullPointerException("数组不能为null");
        }
        if(arr.length == 0){
            throw new ArrayIndexOutOfBoundsException("数组不能没有元素");
        }
    }
    public static int max(int[] arr){
        checkArr(arr);
        int max = arr[0];
        for (int i = 1; i < arr.length; i++) {
            if(arr[i] > max){
                max = arr[i];
            }
        }
        return max;
    }
    public static boolean fromSmallToLarge(int[] arr){
        checkArr(arr);
        for (int i = 0; i < arr.length - 1; i++) {
            if(arr[i] > arr[i+1]){
                return false;
            }
        }
        return true;
    }

    public static int binarySearch(int[] arr ,int value){
        checkArr(arr);
        if(!fromSmallToLarge(arr)){
            throw new RuntimeException("数组元素不是从小到大");
        }
        for(int left = 0,right = arr.length-1; left<=right; ){
            int mid = left + (right-left)/2;
            if(arr[mid] == value){
                return mid;
            }else if(value > arr[mid]){
                left = mid + 1;
            }else{
                right = mid - 1;
            }
        }
        return -1;
    }

    public static String toString(int[] arr){
        if(arr == null){
            return "";
        }
        String str = "[";
        for (int i = 0; i < arr.length; i++) {
            if(i==0){
                str += arr[i];
            }else{
                str += "," + arr[i];
            }
        }
        str += "]";
        return str;
    }
}

21、图形工具类,矩形工具类

(1)自定义InvalidValueException异常,继承Exception

(2)声明图形工具类GraphicTools

声明public static void printRectangle(int line, int column, char sign)输出line行column列由sign接收的字符组成的矩形,如果line或column<=0则抛出new InvalidValueException(“矩形的长和宽必须是正整数”)异常对象,如果sign字符编码不在[33,126]范围,则抛出new InvalidValueException(“组成矩形的必字符必须是数字字母和基本标点符号”)异常对象。

(3)在测试类中测试调用

public class InvalidValueException extends Exception{
    public InvalidValueException() {
    }

    public InvalidValueException(String message) {
        super(message);
    }
}
public class GraphicTools {
    public static void printRectangle(int line, int column, char sign) throws InvalidValueException {
        if(line <=0 || column<=0){
            throw new InvalidValueException("矩形的长和宽必须是正整数");
        }
        if(sign<33 || sign>126){
            throw new InvalidValueException("组成矩形的必字符必须是数字字母和基本标点符号");
        }
        for (int i = 1; i <= line; i++) {
            for (int j = 1; j <= column; j++) {
                System.out.print(sign);
            }
            System.out.println();
        }
    }
}
public class Exercise21 {
    public static void main(String[] args) {
        try {
            GraphicTools.printRectangle(5,5,'*');
        } catch (InvalidValueException e) {
            e.printStackTrace();
        }
    }
}

22、游戏角色

案例:

  • 在一款角色扮演游戏中,每一个人都会有名字和生命值,角色的生命值不能为负数。

  • 要求:当一个人物的生命值为负数的时候需要抛出自定的异常

操作步骤描述:

(1)自定义异常类NoLifeValueException继承RuntimeException

​ ① 提供空参和有参构造

​ ② 在有参构造中,需要调用父类的有参构造,把异常信息传入

(2)定义Person类

​ ① 属性:名称(name)和生命值(lifeValue)

​ ② 提供空参构造

​ ③ 提供有参构造:使用setXxx方法给name和lifeValue赋值

​ ④ 提供setter和getter方法:

在setLifeValue(int lifeValue)方法中,首先判断,如果 lifeValue为负数,就抛出NoLifeValueException,异常信息为:生命值不能为负数:xx;然后在给成员lifeValue赋值。

(3)定义测试类Test08

​ ① 使用满参构造方法创建Person对象,生命值传入一个负数。由于一旦遇到异常,后面的代码的将不在执行, 所以需要注释掉上面的代码

​ ② 使用空参构造创建Person对象

​ 调用setLifeValue(int lifeValue)方法,传入一个正数,运行程序

​ 调用setLifeValue(int lifeValue)方法,传入一个负数,运行程序

​ ③ 分别对①和②处理异常和不处理异常进行运行看效果

public class NoLifeValueException extends RuntimeException{

	public NoLifeValueException() {
		super();
	}

	public NoLifeValueException(String message) {
		super(message);
		
	}
}

public class Person {
	private String name;
	private  int lifeValue;
	public Person() {
		super();
	}
	public Person(String name, int lifeValue) {
		super();
		setName(name);
		setLifeValue(lifeValue);
	}
	public String getName() {
		return name;
	}
	public void setName(String name) {
		this.name = name;
	}
	public int getLifeValue() {
		return lifeValue;
	}
	public void setLifeValue(int lifeValue) {
		if(lifeValue<0){
			throw new NoLifeValueException("生命值不能为负数:" + lifeValue);
		}
		this.lifeValue = lifeValue;
	}
	
}

public class Exercise22 {
	public static void main(String[] args) {
		try {
			Person p = new Person("白蛇",-1);
		} catch (Exception e) {
			e.printStackTrace();
		}
		
		try {
			Person p2 = new Person();
			p2.setLifeValue(10);
			p2.setLifeValue(-10);
		} catch (Exception e) {
			e.printStackTrace();
		}
	}
}

23、银行账户类

1、声明银行账户类Account

(1)包含账号、余额属性,要求属性私有化,提供无参和有参构造,get/set方法(其中balance没有set方法)

(2)包含public void withdraw(double money)取款方法,当取款金额为负数时,抛出Exception,异常信息为“越取你余额越多,想得美”,当取款金额超过余额时,抛出Exception,异常信息为“取款金额不足,不支持当前取款操作”

(3)包含public void save(double money)存款方法,当取款金额为负数时,抛出Exception,异常信息为“越存余额越少,你愿意吗?”

2、编写测试类,创建账号对象,并调用取款和存款方法,并传入非法参数,测试发生对应的异常。

public class Account {
    private String id;
    private double balance;

    public Account() {
    }

    public Account(String id, double balance) {
        this.id = id;
        this.balance = balance;
    }

    public String getId() {
        return id;
    }

    public void setId(String id) {
        this.id = id;
    }

    public double getBalance() {
        return balance;
    }

    public void withdraw(double money) throws Exception {
        if(money<0){
            throw new Exception("越取你余额越多,想得美");
        }
        if(money>balance){
            throw new Exception("取款金额不足,不支持当前取款操作");
        }
        balance -= money;
    }
    public void save(double money) throws Exception {
        if(money<0){
            throw new Exception("越存余额越少,你愿意吗?");
        }
        balance += money;
    }
}

public class Exercise23 {
    public static void main(String[] args) {
        Account a = new Account("111111",5000);

        try {
            a.withdraw(-5000);
        } catch (Exception e) {
//            e.printStackTrace();
            System.err.println("取款失败," + e.getMessage());
        }finally {
            System.out.println("尝试取款-5000后," + a.getBalance() );
        }

        try{
            a.withdraw(1000);
        }catch (Exception e) {
//            e.printStackTrace();
            System.err.println("取款失败," + e.getMessage());
        }finally {
            System.out.println("尝试取款1000后," + a.getBalance() );
        }

        try{
            a.withdraw(5000);
        }catch (Exception e) {
//            e.printStackTrace();
            System.err.println("取款失败," + e.getMessage());
        }finally {
            System.out.println("尝试取款5000后," + a.getBalance() );
        }

        try{
            a.save(-5000);
        }catch (Exception e) {
//            e.printStackTrace();
            System.err.println("存款失败," + e.getMessage());
        }finally {
            System.out.println("尝试存款-5000后," + a.getBalance() );
        }
        try{
            a.save(5000);
        }catch (Exception e) {
//            e.printStackTrace();
            System.err.println("存款失败," + e.getMessage());
        }finally {

            System.out.println("尝试存款5000后," + a.getBalance() );
        }

    }
}

24、用户注册

(1)自定义异常类UsernameAlreadyExistsException(用户名已存在异常)继承Exception。

(2)自定义异常类LoginFailException(登录失败异常)继承Exception。

(3)用户类User,包含用户名和密码属性,私有化,提供有参、无参构造器,提供get/set、toString

(4)用户管理类UserManager

​ ① 包含如下成员变量:

private static User[] arr ; //存储已经注册的用户
private static int total; //存储实际注册的用户数量

​ ② 包含无参构造器

​ ③ 包含如下方法:

  • public void checkUsernameExists(String username):检查用户名是否已经存在,如果已经存在抛出UsernameAlreadyExistsException(用户名已存在异常)。
  • public void add(User user):添加新用户到arr数组中
  • public void login(User user):判断用户名和密码是否正确,如果没有匹配的用户名和密码,就报LoginFailException(登录失败异常)

(5)测试类,实现如下运行效果

--------尚硅谷----------
		1、注册
		2、登录
		3、退出
	请选择:1
用户名:song
密码:123456
注册成功
--------尚硅谷----------
		1、注册
		2、登录
		3、退出
	请选择:1
用户名:song
用户名已存在
用户名:lin
密码:123456
注册成功
--------尚硅谷----------
		1、注册
		2、登录
		3、退出
	请选择:2
用户名:song
密码:123456
登录成功
--------尚硅谷----------
		1、注册
		2、登录
		3、退出
	请选择:2
用户名:lin
密码:654321
com.atguigu.homework10.LoginFailException: 登录失败
	at com.atguigu.homework10.UserManager.login(UserManager.java:36)
	at com.atguigu.homework10.Exercise24.login(TestUser.java:42)
	at com.atguigu.homework10.Exercise24.main(TestUser.java:23)
--------尚硅谷----------
		1、注册
		2、登录
		3、退出
	请选择:3
public class UsernameAlreadyExistsException extends Exception {
    public UsernameAlreadyExistsException() {
    }

    public UsernameAlreadyExistsException(String message) {
        super(message);
    }
}

public class LoginFailException extends Exception {
    public LoginFailException() {
    }

    public LoginFailException(String message) {
        super(message);
    }
}

public class User {
    private String username;
    private String password;

    public User() {
    }

    public User(String username, String password) {
        this.username = username;
        this.password = password;
    }

    public String getUsername() {
        return username;
    }

    public void setUsername(String username) {
        this.username = username;
    }

    public String getPassword() {
        return password;
    }

    public void setPassword(String password) {
        this.password = password;
    }

    @Override
    public String toString() {
        return "User{" +
                "username='" + username + '\'' +
                ", password='" + password + '\'' +
                '}';
    }
}

public class UserManager {
    private static User[] arr ;
    private static int total;

    public UserManager(){
        arr = new User[5];
    }

    public void checkUsernameExists(String username) throws UsernameAlreadyExistsException {
        for (int i = 0; i < total; i++) {
            if(username.equals(arr[i].getUsername())){
                throw new UsernameAlreadyExistsException("用户名已存在");
            }
        }
    }

    public void add(User user){
        if(total>=arr.length){
            User[] newArr = new User[arr.length + (arr.length>>2)];
            for (int i = 0; i < total; i++) {
                newArr[i] = arr[i];
            }
            arr = newArr;
        }
        arr[total++] = user;
    }

    public void login(User user) throws LoginFailException {
        for (int i = 0; i < total; i++) {
            if(user.getUsername().equals(arr[i].getUsername()) && user.getPassword().equals(arr[i].getPassword())){
               return;
            }
        }
        throw new LoginFailException("登录失败");
    }
}

public class Exercise24{
    private static Scanner input = new Scanner(System.in);
    private static UserManager um = new UserManager();

    public static void main(String[] args) {
        boolean flag  = true;
        while(flag){
            System.out.println("--------尚硅谷----------");
            System.out.println("\t\t1、注册");
            System.out.println("\t\t2、登录");
            System.out.println("\t\t3、退出");
            System.out.print("\t请选择:");
            int select = input.nextInt();
            switch (select){
                case 1:
                    regist();
                    break;
                case 2:
                    login();
                    break;
                case 3:
                    flag = false;
            }
        }

        input.close();
    }

    private static void login() {
        System.out.print("用户名:");
        String username = input.next();

        System.out.print("密码:");
        String password = input.next();

        User user = new User(username,password);
        try {
            um.login(user);
            System.out.println("登录成功");
        } catch (LoginFailException e) {
            e.printStackTrace();
        }
    }

    private static void regist(){
        String username;
        while(true) {
            System.out.print("用户名:");
            username = input.next();
            try {
                um.checkUsernameExists(username);
                break;
            } catch (UsernameAlreadyExistsException e) {
                System.err.println(e.getMessage());
                input.nextLine();
            }
        }

        System.out.print("密码:");
        String password = input.next();

        User user = new User(username,password);
        um.add(user);
        System.out.println("注册成功");
    }
}

第09章_异常处理拓展练习(代码阅读题,简答题,编程题)_第1张图片

你可能感兴趣的:(JavaSE拓展练习,java,异常处理,异常的继承体系,throw与throws的区别,异常处理方式,常见异常,运行时异常)