少壮不努力,老大徒伤悲!

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


代码阅读题

1、阅读代码,分析结果

JAVA
	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;
		}
	}
JAVA
/*
 * (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、阅读代码,分析结果

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

3、阅读代码,分析结果

JAVA
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());
	}
}
JAVA
/*
 * (1)main()执行之前,需要先完成所在类的初始化
 * (2)类初始化由两部分代码组成:①静态变量的显式赋值代码②静态代码块
 * (3)没有创建对象,不会执行实例初始化相关的代码
 * (4)finally块中的代码是无论try中是否发生异常,也无论catch是否可以捕获异常,
 * 也不管try和catch中是否有return语句,都会执行的部分
 * (5)如果finally中有return语句,那么try...catch...finally结构
 * 一定从finally中的return回去
 */

4、阅读代码,分析结果

JAVA
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;
		}
	}
}
JAVA
/*
 * (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、阅读代码,分析结果

JAVA
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");
		}
	}
}
JAVA
/*
 * (1)throw用于手动抛出异常
 * (2)无论是JVM抛出的异常还是throw抛出的异常都需要catch处理
 * (3)catch是多分支结构,从上到下按顺序匹配,只会进入第一个匹配上的catch分支
 * (4)finally块中的代码是无论try中是否发生异常,也无论catch是否可以捕获异常,
 * 也不管try和catch中是否有return语句,都会执行的部分
 */

6、阅读代码,分析结果

JAVA
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);
	}
}

JAVA
/*
 * (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、阅读代码,分析结果

JAVA
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");
		}
	}
}  
JAVA
/*
 * (1)finally块中的代码是无论try中是否发生异常,也无论catch是否可以捕获异常,
 * 也不管try和catch中是否有return语句,都会执行的部分
 * (2)throw用于手动抛出异常
 * (3)throws用于将异常抛给调用者处理
 */

8、笔试题:补充代码

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

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

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

PLAINTEXT
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
Java把所有的非正常情况分成两种:异常(Exception)和错误(Error),它们都继承Throwable父类。

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

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

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

JAVA
Exception分为两大类:

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

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

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

13、throw与throws的区别

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

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

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

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

JAVA
在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、请列举常见异常,并说明产生原因。

JAVA
(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类,这个类有一个静态方法:

JAVA
public static void sleep(long millis) throws InterruptedException

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

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

  • 每循环1次执行一次sleep方法,可以模拟1秒输出一个数字。
  • 使用try…catch处理异常
JAVA
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错误

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

JAVA
/*
设置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赋值
JAVA
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();
    }
}

JAVA
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,请用户重新输入。

JAVA
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分别测试(不用写,直接用)

JAVA
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工具类代码:

JAVA
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)在测试类中测试调用

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

    public InvalidValueException(String message) {
        super(message);
    }
}
JAVA
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();
        }
    }
}
JAVA
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)方法,传入一个负数,运行程序

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

JAVA
public class NoLifeValueException extends RuntimeException{

	public NoLifeValueException() {
		super();
	}

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

JAVA
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;
	}
	
}

JAVA
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、编写测试类,创建账号对象,并调用取款和存款方法,并传入非法参数,测试发生对应的异常。

JAVA
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;
    }
}

JAVA
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

​ ① 包含如下成员变量:

JAVA
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)测试类,实现如下运行效果

JAVA
--------尚硅谷----------
		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
JAVA
public class UsernameAlreadyExistsException extends Exception {
    public UsernameAlreadyExistsException() {
    }

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

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

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

JAVA
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 + '\'' +
                '}';
    }
}

JAVA
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("登录失败");
    }
}

JAVA
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("注册成功");
    }
}

版权声明:如无特别声明,本站收集的文章归  HuaJi66/Others  所有。 如有侵权,请联系删除。

联系邮箱: GenshinTimeStamp@outlook.com

本文标题:《 练习-第09章_异常处理.md 》

本文链接:/java/%E7%BB%83%E4%B9%A0%E9%A2%98/%E7%AC%AC09%E7%AB%A0_%E5%BC%82%E5%B8%B8%E5%A4%84%E7%90%86.html