异常处理
目前碰到的几种异常
- 下标越界异常
- 空指针异常
- 类型转换异常
- 数字格式化异常
- 算术异常(数学异常)
编程界的几种异常
- 除数为0,数学异常
- IO流,输入输出没有关闭
- 停电,物理异常
当一个程序抛出异常时,抛异常后面的语句不再执行
类似于return
的功能,将会终止方法的执行
MyException类
public class MyException extends Exception {
public MyException(String message) {
super(message);
}
}
MyRuntimeException类
public class MyRuntimeException extends RuntimeException {
public MyRuntimeException(String message) {
super(message);
}
}
ServiceException类
public class ServiceException extends RuntimeException {
// 错误码
private Integer code;
// 异常信息
private String message;
public ServiceException() {
}
public ServiceException(Integer code, String message) {
this.code = code;
this.message = message;
}
public Integer getCode() {
return code;
}
public void setCode(Integer code) {
this.code = code;
}
@Override
public String getMessage() {
return message;
}
public void setMessage(String message) {
this.message = message;
}
}
简单的运用
public static void main(String[] args) {
int num1 = 10;
int num2 = 0;
if(num2 != 0){
System.out.println(num1 / num2);
}
double num3 = 0;
BigDecimal bigDecimal1 = new BigDecimal(13.0);
BigDecimal bigDecimal2 = new BigDecimal(0);
System.out.println(bigDecimal1.divide(bigDecimal2));
System.out.println("我很重要...");
}
异常的继承体系结构
最顶级的异常错误类
Throwable
Error
正常情况下,不太可能出现的。绝大多数Error
都会导致程序处于
非正常的状态下,很难恢复。外力的作用下,不考虑。Error
是Throwable
的子类。它是在Java程序处理范围之外的。
Exception
在Java语言中,将程序执行中发生的不正常的情况称之为异常。
编译期异常:写代码的时候,抛异常。如果编译器不解决,会编译不通过,一直报红。
运行期异常:RuntimeException
,运行时会抛异常,平时没事
自定义异常
Java中异常机制,需要结合实际业务。
那么该如何自定义异常呢?
- 所有异常必须是
Throwable
的子类(大材小用,没必要) - 如果要定义一个编译期异常,需要继承
Exception
类。 - 如果要定义一个运行期异常,需要继承
RuntimeException
类。
public static void main(String[] args) {
int num1 = 10;
int num2 = 2;
try{
// 把有可能抛异常的代码放到try语句块里
System.out.println(num1 / num2);
}catch (Exception e){
System.out.println("除数不能为0");
e.printStackTrace();
}
System.out.println("我很重要...");
}
在一个语句块中,如果使用
throw
抛出一个编译期异常
就必须在方法的声明处使用throw
关键字来标记异常类型
还有一种处理方式,就是直接try...catch
我们为什么要手动抛异常?
因为要配合全局异常处理机制来解决问题,后面的事。
public static void fun(int i,int j) throws MyException {
if(j == 0){
throw new MyException("除数不能为0");
}
System.out.println(i / j);
}
public static void main(String[] args) {
try {
fun(1,1);
} catch (MyException e) {
// 打印异常信息
e.printStackTrace();
}
}
throw
语句是可以当做方法的返回值的
在一个有返回值的方法中,如果有条件分支
一定要保证每种情况下都有返回值,哪怕是抛异常
开发中,大部分情况下使用的都是运行期异常!!!
public static String show(String str) {
if(!Objects.isNull(str)){
return str.concat("hello");
}
// throw new RuntimeException("参数不能是空");
throw new ServiceException(101,"账号不能为空。");
}
public static void main(String[] args) {
show(null);
}
异常链
一个异常被抛出去之后会继续被调用这个方法的方法捕获或抛出,异常会扩散。
只要说解决异常,处理异常,捕获,就是try...catch
。
class A{
public void a() {
throw new ServiceException(201,"业务异常...");
}
}
class B {
public void b() {
A aa = new A();
try {
aa.a();
} catch (Exception e) {
e.printStackTrace();
}
System.out.println("b方法的语句");
}
}
class C {
public void c(){
B b = new B();
b.b();
System.out.println("c方法的语句..");
}
}
public class Ch05 {
public static void main(String[] args) {
C c = new C();
c.c();
System.out.println("Ch05的语句");
}
}
如果一个方法没有捕获一个编译期异常,该方法必须使用throws
来声明。throws
并不是真正的解决了异常,只是把异常抛给了下一级调用者。
方法的声明处,抛出多个异常,用逗号隔开。
public void show() throws MyException,RuntimeException,NullPointerException,IndexOutOfBoundsException {
}
public void info() throws MyException {
show();
}
// JVM
public static void main(String[] args) {
try {
new Ch06().info();
} catch (MyException e) {
throw new RuntimeException(e);
}
}
finally关键字
finally
用来创建在try
代码块后面执行的代码块
无论是否发生异常,finally
代码块中的代码一定会执行。
一般finally
中的代码都是用来释放资源。
语句:try...catch...finally
public static void main(String[] args) {
int num1 = 10;
int num2 = 2;
String str = null;
try {
System.out.println(num1 / num2);
System.out.println(str.length());
main(args);
}finally{
System.out.println("finally...");
}
}
catch
可以写多个,有顺序问题。
先写小的,再写大的。
public static void main(String[] args) {
int num1 = 10;
int num2 = 0;
try {
System.out.println(num1 / num2);
// 开发角度来说,应该写指定的。
} catch (ArithmeticException e) {
e.printStackTrace();
System.out.println("除数不能为0");
} catch (Exception e){
System.out.println("未知错误");
}
}
方法的重写
重写的方法不能抛出比被重写方法更大的异常类型
interface Inter01 {
void show() throws Exception;
}
public class Ch09 implements Inter01 {
@Override
public void show() throws NullPointerException {
}
}
身份证的一些判断
传入的身份证为
String
类型的idCard
首先要判断身份证是否完全为数字,那么该如何判断呢?
简单的用Long.parseLong()
即可,若字符串中存在不是数字的内容
将会抛出异常,无法赋值。确认身份证完全都是数字后再进行其他判断身份证需要是18位数字、第一位不能是
0
生日的年份不能大于LocalDate.now()
,月份要对应年份
不能小于1,也不可以大于该月份的正常最大值(要考虑闰年的问题)
年龄(当日年份-身份证年份)需要在18-60区间,否则抛出异常
public void judgeIdCard(String idCard) {
long id=0L;
try {
id = Long.parseLong(idCard);
} catch (Exception e) {
throw new MyRuntimeException("身份证中存在未知的其他字符");
}
if (idCard.length() != 18 || idCard.charAt(0) == '0') {
throw new RuntimeException("身份证号错误!(位数错误)");
}
int year = Integer.parseInt(idCard.substring(6,10));
int month = Integer.parseInt(idCard.substring(10,12));
int day = Integer.parseInt(idCard.substring(12,14));
LocalDate localDate = LocalDate.now();
if (year >localDate.getYear()) {
throw new RuntimeException("身份证号错误!(年份错误)");
}
if (month >12 || month <1) {
throw new RuntimeException("身份证号错误!(月份错误)");
}
int verifyDay;
if (month == 1|| month ==3 || month==5||
month==7 || month==8 ||month==10||month==12) {
verifyDay = 31;
}else if (month == 4 || month==6 || month==9 || month==11) {
verifyDay = 30;
}else {
if ((year %4 ==0 && year%100 !=0) || year%400 ==0) {
verifyDay = 29;
} else {
verifyDay = 28;
}
}
if (day<0 || day >verifyDay) {
throw new RuntimeException("身份证号错误!(日期错误)");
}
int age = localDate.getYear() - year;
if (age > 60) {
throw new MyRuntimeException("年龄过高");
}
if (age < 18) {
throw new MyRuntimeException("年龄过低");
}
this.age = localDate.getYear() - year;
this.birth = year+"-"+idCard.substring(10,12)+"-"+idCard.substring(12,14);
}
整个判断中没有太多要考虑的事情,前期完成Long.parseLong()
的操作
后期就可以随便赋值了,通过String
中的subString
方法
来准确的拿到相应的年份、月份、日期、性别等信息
整个判断没有太多细节,正规的身份证号码应该有更多的判断
以上代码只是提供一些小思路,不完全正确,仅供参考!
“异常”常见习题
请描述异常的继承体系
异常继承体系为:异常的根类是 java.lang.Throwable
,其下有两个子类: java.lang.Error
与 java.util.Exception
。而Exception又分为编译时期异常:checked
异常,与运行时期异常:runtime
异常。
请描述你对错误(Error
)的理解
Error
:表示不可修复的恶性的错误,只能通过修改代码规避错误的产生,通常是系统级别的,所以很严重。
请描述你对异常(Expection
的理解)
Exception
:表示可修复的良性(相对于错误)的异常,异常产生后程序员可以并且应该通过代码的方式纠正,使程序继续运行,是必须要处理的。
请描述你对运行时异常(RuntimeException
)的理解
运行时期异常:runtime
异常。编译期不报错,运行时出现异常信息,也可以提前在编译期处理,而checked
异常 必须在编译期处理。
请描述throw
的使用位置,作用是什么?
throw
关键字通常用在方法体中,并且抛出一个异常对象。程序在执行到throw
语句时立即 停止,它后面的语句都不执行。
请描述throws
的使用位置,作用是什么?
throws
关键字通常被应用在声明方法时,用来指定可能抛出的异常。多个异常可以使用逗号隔开。当在主函数中调用该方法时,如果发生异常,就会将异常对象抛给方法调用处。
异常处理方式有几种,分别是什么?
异常的处理方式有两种,分别是使用throws
和try...catch...finally
详细阐述每种方式对异常是如何处理的
throws
用在方法的声明上后接异常类名,是把异常抛给调用者进行处理try...catch...finally
是捕获异常,自己处理,处理完毕后面的程序可以继续运行a.try
代码块中是可能出现异常的代码
b.catch
代码块,是遇到异常,对异常进行处理的代码
c.finally
代码块是无论是否发生异常,都必须执行的代码,用于释放资源.
请列举常见异常,并说明产生原因。
NullPointerException
:空指针异常。 当应用试图在要求使用对象的地方使用了null
时,抛出该异常。
譬如:调用null
对象的实例方 法、访问null
对象的属性、计算null
对象的长度等等。
ArrayIndexOutOfBoundsException
:数组索引越界异常。 当对数组的索引值为负数或大于等于数组大小时抛出此异常。
ArithmeticException
:算术运算异常。 程序中出现了除以零这样的运算就会出这样的异常,对这种异常,大家就要好好检查一下自己程序中涉及到数学运算的地方,公式是不是有不妥了。
NumberFormatException
:数字格式异常。
当试图将一个String转换为指定的数字类型,而该字符串确不满足数字类型要求的格式时,抛出该异常。
4 条评论
每篇感觉都有启发我 !!
加油
航宝是我的谁也不许抢 航宝是我的谁也不许抢 航宝是我的谁也不许抢 航宝是我的谁也不许抢 航宝是我的谁也不许抢 航宝是我的谁也不许抢 航宝是我的谁也不许抢 航宝是我的谁也不许抢 航宝是我的谁也不许抢 航宝是我的谁也不许抢 航宝是我的谁也不许抢 航宝是我的谁也不许抢 航宝是我的谁也不许抢 航宝是我的谁也不许抢 航宝是我的谁也不许抢 航宝是我的谁也不许抢 航宝是我的谁也不许抢 航宝是我的谁也不许抢 航宝是我的谁也不许抢 航宝是我的谁也不许抢 航宝是我的谁也不许抢 航宝是我的谁也不许抢 航宝是我的谁也不许抢 航宝是我的谁也不许抢 航宝是我的谁也不许抢 航宝是我的谁也不许抢 航宝是我的谁也不许抢 航宝是我的谁也不许抢 航宝是我的谁也不许抢 航宝是我的谁也不许抢 航宝是我的谁也不许抢 航宝是我的谁也不许抢 航宝是我的谁也不许抢 航宝是我的谁也不许抢 航宝是我的谁也不许抢 航宝是我的谁也不许抢 航宝是我的谁也不许抢 航宝是我的谁也不许抢 航宝是我的谁也不许抢 航宝是我的谁也不许抢 航宝是我的谁也不许抢 航宝是我的谁也不许抢 航宝是我的谁也不许抢 航宝是我的谁也不许抢 航宝是我的谁也不许抢 航宝是我的谁也不许抢 航宝是我的谁也不许抢 航宝是我的谁也不许抢 航宝是我的谁也不许抢 航宝是我的谁也不许抢 航宝是我的谁也不许抢 航宝是我的谁也不许抢 航宝是我的谁也不许抢 航宝是我的谁也不许抢 航宝是我的谁也不许抢 航宝是我的谁也不许抢 航宝是我的谁也不许抢 航宝是我的谁也不许抢 航宝是我的谁也不许抢 航宝是我的谁也不许抢 航宝是我的谁也不许抢 航宝是我的谁也不许抢 航宝是我的谁也不许抢 航宝是我的谁也不许抢 航宝是我的谁也不许抢
ヾ(≧∇≦*)ゝ