OOP h08
Test 1
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53
| package com.huawei.classroom.student.h08;
public class Test1 {
public Test1() { }
public static void main(String[] args) { Dog dog=new Dog();
try{ dog.feed(); dog.feed(); dog.feed(); System.out.println("做对了第1步"); dog.feed(); System.out.println("第2步做错了");
}catch(Exception e){ if(e.getMessage().equals("I can not eat more!")){ System.out.println("做对了第2步"); } }
}
}
|
阅读 Test1
,可以发现需要创建 Dog
类,包括 feed
方法,且需要记录次数。
可以定义属性 count
记录 feed
的次数,定义 MAX_FEED_COUNT
为最大次数 3 次。feed
时检测当前已 feed
次数,大于等于最大次数则抛出 Exception
异常,输出 "I can not eat more!"
。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20
| package com.huawei.classroom.student.h08;
public class Dog { private int count; private static final int MAX_FEED_COUNT = 3; public Dog() { this.count = 0; }
public void feed() throws Exception{ if (this.count < MAX_FEED_COUNT) { this.count++; } else { throw new Exception("I can not eat more!"); } } }
|
Test 2
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36
| package com.huawei.classroom.student.h08;
public class Test2 {
public Test2() { }
public static void main(String[] args) { LoginUtil loginUtil = new LoginUtil(); try { loginUtil.login("a", "a"); System.out.println("做对了第1步"); loginUtil.login("b", "b");
} catch (InvalidUserExcetpion e) { System.out.println("做对了第2步");
} }
}
|
阅读 Test2
,可以发现需要创建 LoginUtil
类,判断 login
传入参数是否全为 "a"
,否则需要抛出自定义的 InvalidUserExcetpion
异常。
异常是一种类,继承 Exception
。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18
| package com.huawei.classroom.student.h08;
public class LoginUtil { private static final String VALID_USERNAME = "a"; private static final String VALID_PASSWD = "a"; public LoginUtil() {
}
public void login(String username, String passwd) throws InvalidUserExcetpion{ if (!username.equals(VALID_USERNAME) || !passwd.equals(VALID_PASSWD)) { throw new InvalidUserExcetpion(); } } }
|
1 2 3 4 5 6 7 8 9 10
| package com.huawei.classroom.student.h08;
public class InvalidUserExcetpion extends Exception{ public InvalidUserExcetpion() { super(); } }
|
Test 3
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41
| package com.huawei.classroom.student.h08;
public class Test3 {
public Test3() { }
public static void main(String[] args) { Bank bank = new Bank(); try { bank.save(100); bank.save(300);
bank.get(200); System.out.println("做对了第1步"); bank.get(300);
} catch (NoMoneyException e) { System.out.println("做对了第2步");
} } }
|
阅读 Test3
,可以发现需要创建 Bank
类,包括 save
和 get
方法。应定义存款属性,save
存储 get
取出。取出时需要判断余额是否足够,不足时抛出自定义的 NoMoneyException
异常。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24
| package com.huawei.classroom.student.h08;
public class Bank { private int deposit; public Bank() { this.deposit = 0; }
public void save(int money) { if (money > 0) { this.deposit += money; } } public void get(int money) throws NoMoneyException { if (money > 0 && money < this.deposit) { this.deposit -= money; } else { throw new NoMoneyException(); } } }
|
1 2 3 4 5 6 7 8 9 10
| package com.huawei.classroom.student.h08;
public class NoMoneyException extends Exception{ public NoMoneyException() { super(); } }
|
Test 4
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37
| package com.huawei.classroom.student.h08;
public class Test4 {
public Test4() { }
public static void main(String[] args) {
AgeCheckInterface ageCheck = new AgeCheck(); ageCheck.checkAge(10); System.out.println("做对了第1步"); try { ageCheck.checkAge(-10); } catch (Exception e) { System.out.println("做对了第2步"); } }
}
|
1 2 3 4 5 6 7 8 9 10 11 12 13
| package com.huawei.classroom.student.h08;
public interface AgeCheckInterface {
public void checkAge(int age) ;
}
|
阅读 Test4
,可以发现需要创建 AgeCheck
类,实现 AgeCheckInterface
接口,用于判断 checkAge
中的参数是否满足大于 0 且小于 200,否则抛出异常。
注意,接口中未声明 throws
,即不可以在AgeCheck
类中实现接口时 throws
。且 Test4
中第一次调用 checkAge
时未包含在 try-catch
语句中。
关于异常
异常处理的基本模式
抛出的异常必须是 Throwable 的子类,只要是 Throwable 的子类,都可以 throw 或 catch。不是 Throwable 的子类,不可以 throw 和 catch。
Throwable 包括 Error、Exception 和 RuntimeException:
- Error 类表示 Java 运行时产生的系统内部错误或资源耗尽等严重错误,程序无法控制和解决;
- Exception 及其子类(不包括 RuntimeException)又称为「可检异常」或「非运行时异常」,程序可以处理;
- RuntimeException 及其子类被称为「运行时异常」或「非必检异常」,一般发生在 JRE 内部,编译器不检查,即使没有用
try-catch
语句捕获,也没有用 throws-throw
抛出,也会编译通过。
如果抛出了可以捕捉的东西,一定要在方法后面加 throws
吗?
- 若抛出的是 Exception 的子类,且非 RuntimeException 的子类,必须抛出或者捕捉;
- 若抛出的是 RuntimeException 的子类,或者 Error 的子类,则不需要显式抛出。
可不可以在不抛出内容的情况下 catch
?
- Exception 的子类,且非 RuntimeException 的子类,必须在抛出的情况下捕捉;
- RuntimeException 的子类,或者 Error 的子类,可以在不抛出的情况下捕捉。
catch Exception
能捕捉到所有抛出的东西吗?
不能,要捕捉所有抛出的东西,必须 catch Throwable
。
异常会首先被符合条件的 catch
捕捉。
一个方法必须通过 throws
语句在方法的声明部分说明它可能抛出而并未捕获的所有的「必检异常」,如果没有这么做,将不能通过编译。
如果在子类中覆盖了父类的某一方法,那么该子类方法不可以比其覆盖的父类方法抛出更多的异常。
所以此处可以抛出 RuntimeException
。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21
| package com.huawei.classroom.student.h08;
public class AgeCheck implements AgeCheckInterface{ private static final int MIN = 0; private static final int MAX = 200;
public AgeCheck() {
}
@Override public void checkAge(int age) { if (age < MIN || age > MAX) { throw new RuntimeException(); } } }
|
Test 5
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34
| package com.huawei.classroom.student.h08;
public class Test5 {
public Test5() { }
public static void main(String[] args) { TypeValidator v = new TypeValidator(); v.validate("abc"); System.out.println("做对了第1步"); try { v.validate(123);
} catch (Exception e) { System.out.println("做对了第2步"); } } }
|
阅读 Test5
,可以发现需要创建 TypeValidator
类。同 Test4
,不符合要求则抛出 RuntimeException
。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17
| package com.huawei.classroom.student.h08;
public class TypeValidator { public TypeValidator() {
}
public void validate(Object test){ if (!(test instanceof String)) { throw new RuntimeException(); } }
}
|