目录
? ? ? ? 异常是什么?异常是程序在“编译”和“运行”的过程中可能出现的问题,异常是应该尽可能去提前避免的,异常可能也是无法做到绝对避免的,异常的情况太多了,开发中只能提前干预。
? ? ? ? 异常一旦出现了,如果没有提前处理异常,程序可能退出JVM虚拟机而终止,开发中是需要提前处理的。
? ? ? ? 处理异常可以提高程序员的健壮性和安全性。
? ? ?
? ? ? ? ERROR:错误的意思,严重错误ERROR,无法通过处理的错误,一旦出现,程序员无能为力了,只能重启系统,优化项目。
? ? ? ? 比如:内存崩溃,JVM本身崩溃,这个程序员无需理会。?
? ? ? ? Exception:才是异常类,它才是开发中代码在编译或者执行过程中可能出现的错误,它是需要提前进行处理的,以便程序更加健壮。
? ? ? ? 1.编译时异常:继承来自Exception的异常和子类,编译阶段就会报错。
? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? 必须程序员处理的,否则代码编译就不能通过!!!
? ? ? ? 2.运行时异常:继承来自RuntimeException的异类和子类,编译阶段是不会出错的,它是在运行阶段有可能出现,运行时异常可以处理也可以不处理,编译时候发生,还是建议处理。
异常一旦出现,程序会终止,所以要研究异常,避免异常,处理异常,程序更加健壮,
例如:ArrayIndexOutofBoundsException运行时异常:
public static void main(String[] args) {
System.out.println("程序开始..");
int[] arr={1,12,3};
System.out.println(arr[3]);
//运行时异常
//Exception in thread "main" java.lang.ArrayIndexOutOfBoundsException: Index 3 out of bounds for length 3
System.out.println("程序结束");
}
? ? ? ?这是一个普通的面试题,常见的运行时异常有:
? ? ? ? 1.数组越界异常:ArrayIndexOutofBoundsException。
? ? ? ? 2.空指针异常:NullPointerException
? ? ? ? 3.类型转换异常:ClassCastException
? ? ? ? 4.迭代器遍历没有此元素异常:NoSuchElementException
? ? ? ? 5.数学操作异常:ArithemeticException.
? ? ? ? 6.数字转换异常:NumberFormatException.
System.out.println("程序开始...");
int[] arrs = {10,20};
// System.out.println(arrs[3]);
/*Exception in thread "main" java.lang.ArrayIndexOutOfBoundsException: 3*/
/*直接结束*/
String name = null;
// System.out.println(name.length());
/*Exception in thread "main" java.lang.NullPointerException*/
Object o ="齐天大圣";
String s =(String) o;
// Integer integer =(Integer) o;
/*Exception in thread "main" java.lang.ClassCastException: java.lang.String cannot be cast to java.lang.Integer*/
// int c=10/0;
/*Exception in thread "main" java.lang.ArithmeticException: / by zero*/
String num = "23aa";
Integer it = Integer.valueOf(num);
System.out.println(it+1);
System.out.println("程序结束。。。");
/*数字转换异常:Exception in thread "main" java.lang.NumberFormatException: For input string: "23aa"*/
}
? ? ? ? 编译时异常继承于Exception的异类或者子类,没有继承RuntimeException
? ? ? ? "编译时异常是编译阶段就会报错"
? ? ? ? 作用:提醒程序这串代码可能出现错误,请检查有没有bug,当认为没有时候就抛出。
public static void main(String[] args) throws ParseException {//已经抛出
String date = "2018-01-12 03:60:00";
SimpleDateFormat simpleDateFormat =new SimpleDateFormat("yyyy-MM/dd");
Date date1 = simpleDateFormat.parse(date);
System.out.println(date1);
//Exception in thread "main" java.text.ParseException: Unparseable date: "2018-01-12 03:60:00"
}
? ? ? ? (1)默认会在出现异常的代码那里创建一个异常对象。
? ? ? ? (2)异常会从方法中出现的点抛出给调用者,调用者最终抛出给虚拟机。
? ? ? ? (3)虚拟机接受到异常对象后,先在控制台直接输出异常栈信息数据。
? ? ? ? (4)直接从当前执行的异常点干掉程序。
? ? ? ? (5)后续代码没有机会执行了,因为程序已经死亡。
? ? ? ? 由此可见,异常的默认处理机制并不完美,异常一旦出现,程序就立即死亡了。
? ? ? ? (1)方法一:
? ? ? ? ? ? ? ? 方法 throws 异常1,异常2,...{
?????????????????}
? ? ? ? ? ? ? ? 出现异常的地方层层向上抛出,谁都不处理,最终抛出给虚拟机,这种方法虽然可以解决编译时异常,但是如果异常出现,程序就死亡了。
? ? ? ? (2)方式二:在出现异常的地方自己处理,谁出现谁处理。
? ? ? ? ? ? ? ? 自己捕获异常和处理异常的格式:捕获代码:
? ? ? ? ? ? ? ? try{
? ? ? ? ? ? ? ? //监视可能出现异常的代码
????????????????}catch(异常类型1 变量){
? ? ? ? ? ? ? ? //处理异常
????????????????}catch(异常类型2 变量){
? ? ? ? ? ? ? ? //处理异常
????????????????}
? ? ? ?优点:出现异常捕获处理,出现异常后代码不会死亡。
? ? ? ? 缺点:上层调用者不知道下层调用者的情况,这个可以自己处理。
? ? ? ? 方式三(推荐):在出现异常的地方把异常一层一层抛出给最外层调用者,最外层调用者集合处理.
这种方案最外层调用者可以知道底层执行的情况,同时程序在出现异常后也不会立即死亡,这是理论上最好的方案。
? ? ? ? 运行时异常编译阶段不会报错,可以处理也可以不处理,建议处理!!!
? ? ? ? 运行时异常可以自动抛出,不用我们手动抛出
? ? ? ? 运行时异常的处理规范,直接在最外层捕获,底层会自动抛出。
public static void main(String[] args) {
System.out.println("程序开始");
try{
chu(1,0);
System.out.println("成功了");
}catch (Exception e){
e.printStackTrace();
System.out.println("失败了");
}
System.out.println("程序结束");
}
public static void chu(int a,int b){
System.out.print(a/b);
}
? ? ? ? finally关键字
? ? ? ? 用在捕获处理的格式中
? ? ? ? try{
? ? ? ? //如果这里有return 语句会被finnally拽回来执行。
????????}catch(){
????????}finally{
? ? ? ? //无论是否有异常,都要执行这个代码。
????????}
? ? ? ? try:1次
? ? ? ? catch:0-N次
? ? ? ? finally:0-1次
? ? ? ? finally的作用:可以在代码执行完成以后进行资源的释放操作。通常用于资源回收,实现closable接口中的close()方法。
public static void main(String[] args) {
//chu
System.out.println(chu1());
}
public static int chu1(){
try {
int a = 10/0;
return a;
}catch (Exception e){
e.printStackTrace();
return -1;
}finally {
System.out.println("finally被执行");
//注意,finally不要加return ,这里相当危险,不建议
}
//java.lang.ArithmeticException: / by zero
// at _07异常_finally关键字.finallyDemo.chu1(finallyDemo.java:27)
// at _07异常_finally关键字.finallyDemo.main(finallyDemo.java:23)
//finally被执行
//-1
}
? ? ? ? 1.运行时异常被抛出可以不处理,可以自动抛出,编译时异常必须处理,按照规范处理!!
? ? ? ? 2.重写方法申明抛出的异常,应该与父类被重写的方法申明的异常一样或者范围更小。
? ? ? ? 3.方法默认都可以自动抛出运行时异常!throw RuntimeException可以省略不写。
? ? ? ? 4.在try/catch后可以追加finally代码块,其中的代码一定会被执行,通常用于资源回收操作。
????????
? ? ? ? Java中已经为开发中可能出现的异常都设计了一个类来表示,但是实际开发中,异常可能有很多种情况,Java无法为这个世界上所有的异常都设计一个类,这时候就需要我们根据业务在自定义异常了。
? ? ? ? 如有一个需求:年龄小于0,大于200是一个异常。
? ? ? ? 可以自定义两种异常,编译时和运行时,要么继承Exception要么继承RuntimeException。
? ? ? ? 步骤:
? ? ? ? 1.定义一个异常类继承自Exception/RuntimeException.
? ? ? ? 2.重写构造器。
? ? ? ? 3.在出现异常的地方用throw new 自定义异常对象抛出!!
? ? ? ? 编译时异常是编译的阶段就报错,提醒强烈,一定要处理!
? ? ? ? 而运行时异常不强烈,但是建议处理。
????????
/*
*
* 自定义编译时异常类:
* 1.继承Exception。
* 2.重写构造器。
*
*
* */
public class ExtendsException extends Exception{
public ExtendsException() {
}
public ExtendsException(String message) {
super(message);
}
public ExtendsException(String message, Throwable cause) {
super(message, cause);
}
public ExtendsException(Throwable cause) {
super(cause);
}
public ExtendsException(String message, Throwable cause, boolean enableSuppression, boolean writableStackTrace) {
super(message, cause, enableSuppression, writableStackTrace);
}
}
public class ExtendsRuntimeException extends RuntimeException{
public ExtendsRuntimeException() {
}
public ExtendsRuntimeException(String message) {
super(message);
}
public ExtendsRuntimeException(String message, Throwable cause) {
super(message, cause);
}
public ExtendsRuntimeException(Throwable cause) {
super(cause);
}
public ExtendsRuntimeException(String message, Throwable cause, boolean enableSuppression, boolean writableStackTrace) {
super(message, cause, enableSuppression, writableStackTrace);
}
}
在throw new 编译时异常的时候,我们需要用try捕获或者抛出给虚拟机,否则编译不通过:
public class ExceptionDemo {
public static void main(String[] args) {
try {
checkAge(2000);
} catch (Exception e) {
e.printStackTrace();
}
// checkAge(300);//运行时异常提醒不严重。
}
public static void checkAge(int age) throws ExtendsException {
if (age < 0 || age >200){
//出现异常了
//throws 用在方法上,用于抛出方法中的异常
//throw:用在出现异常的地方,用于创建异常对象且立即从此处抛出!
throw new ExtendsException("/ age is illegal!");
// throw new ExtendsRuntimeException("/ age is illegal!");//运行时
// _09异常_自定义异常.ExtendsException: / age is illegal!
// at _09异常_自定义异常.ExceptionDemo.checkAge(ExceptionDemo.java:41)
// at _09异常_自定义异常.ExceptionDemo.main(ExceptionDemo.java:31)
}else {
System.out.println("年龄是"+age);
}
}
}
在throw new 运行时异常的时候,是自动抛出的,可以不做手动抛出:
public class ExceptionDemo {
public static void main(String[] args) {
// try {
// checkAge(2000);
// } catch (Exception e) {
// e.printStackTrace();
// }
checkAge(300);//运行时异常提醒不严重。
}
public static void checkAge(int age) {
if (age < 0 || age >200){
//出现异常了
//throws 用在方法上,用于抛出方法中的异常
//throw:用在出现异常的地方,用于创建异常对象且立即从此处抛出!
// throw new ExtendsException("/ age is illegal!");
throw new ExtendsRuntimeException("/ age is illegal!");//运行时
// _09异常_自定义异常.ExtendsException: / age is illegal!
// at _09异常_自定义异常.ExceptionDemo.checkAge(ExceptionDemo.java:41)
// at _09异常_自定义异常.ExceptionDemo.main(ExceptionDemo.java:31)
}else {
System.out.println("年龄是"+age);
}
}
}