网站核验点,海口网站建设好,建设摩托车官网报价,wordpress 调整配置文件#x1f495;有效知识的前提是承认知识边界#xff0c;承认我们对边界那边的一切无可奉告。#x1f495; 作者#xff1a;Mylvzi 文章主要内容#xff1a;JavaSE学习值之--认识异常 一.什么是异常#xff1f; 异常就是程序在运行的时候产生的不正常的行为 … 有效知识的前提是承认知识边界承认我们对边界那边的一切无可奉告。 作者Mylvzi 文章主要内容JavaSE学习值之--认识异常 一.什么是异常 异常就是程序在运行的时候产生的不正常的行为 小细节没注意到发生了小的错误比如
1.算数异常 System.out.println(10/0);2.空指针异常 null.length int[] arr null;System.out.println(arr.length);3.数组越界异常 int[] arr new int[3];System.out.println(arr[5]); 可见Java中java中不同类型的异常都有与其对应的类来进行描述实际上Java中的异常是一个大的体系
二.异常的体系
异常它是由编译器识别并给出的证明其存在于编译器所自带的库文件中应该是一个类 1. Throwable 是异常体系的顶层类其派生出两个重要的子类, Error 和 Exception 2. Error 指的是Java虚拟机无法解决的严重问题比如JVM的内部错误、资源耗尽等典型代表 StackOverflowError和OutOfMemoryError一旦发生回力乏术。(递归调用时) 3. Exception 异常产生后程序员可以通过代码进行处理使程序继续执行。比如感冒、发烧。我们平时所说 的异常就是Exception。 三.异常的分类 主要是分为两大类 运行时异常不受查异常 RuntimeException() 编译时异常受查异常 1. RunTimeException 包括他的所有子类 在程序执行期间发生的异常称为运行时异常也称为非受检查异常(Unchecked Exception) 注意 在编写代码过程中出现的语法错误不是运行时异常比如把main写成了mian,编译器在编译的时候就会报错这叫错编译期错误而运行时异常的产生是所写代码已经经过编译生成.class文件了再交由JVM运行时产生的错误 补充RuntimeException的子类 2.编译时异常 在编译的时候就会发生的异常又称作受查异常Checked Exception 比如之前实现的Cloneable接口
class Stu implements Cloneable {String name;int age;public Stu(String name, int age) {this.name name;this.age age;}Overrideprotected Object clone() throws CloneNotSupportedException {return super.clone();}Overridepublic String toString() {return Stu{ name name \ , age age };}
}
public class Test1 {public static void main(String[] args){Stu stu new Stu(lvzi,18);Stu stu2 (Stu) stu.clone();System.out.println(stu2);
}
之前提到必须在main方法的签名中声明抛出异常,否则会出现异常 这种在编译阶段就报错的异常叫做编译时异常又叫做受查异常Checked Exception 四.异常的处理
1.防御式编程 错误的代码总是存在且不可避免地我们要做的就是当程序出现异常的时候及时告诉程序员来帮助他修改代码主要有两种思路
1.LBYL: Look Before You Leap. 在操作之前就做充分的检查. 即事前防御型 即对每一个流程都充分想到其可能会发生的错误及时处理
boolean ret false;
ret 登陆游戏();
if (!ret) {
处理登陆游戏错误;
return;
}
ret 开始匹配();
if (!ret) {
处理匹配错误;
return;
}
ret 游戏确认();
if (!ret) {
处理游戏确认错误;
return;
}
ret 选择英雄();
if (!ret) {
处理选择英雄错误;
return
} 每进行一步就进行一次检查但这种方式使正确代码和异常检查的代码混在一起使得整个代码很混乱不推荐
2.EAFP: Its Easier to Ask Forgiveness than Permission. 事后获取原谅比事前获取许可更容易. 也就是先操 作, 遇到问题再处理. 即事后认错型
try {
登陆游戏();
开始匹配();
游戏确认();
选择英雄();
载入游戏画面();
...
} catch (登陆游戏异常) {
处理登陆游戏异常;
} catch (开始匹配异常) {
处理开始匹配异常;
} catch (游戏确认异常) {
处理游戏确认异常;
} catch (选择英雄异常) {
处理选择英雄异常;
} catch (载入游戏画面异常) {
处理载入游戏画面异常;
} EAFP的思维简单来说就是管他三七二十一先执行再说产生的异常事后处理即可
这种思维是的操作部分和异常处理部分分离让程序员更加模块化的思考更有利于代码的编写 在Java中异常处理主要的5个关键字throw、try、catch、final、throws。 在编写程序时如果程序中出现错误此时就需要将错误的信息告知给调用者比如参数检测 在Java中可以借助throw关键字抛出一个指定的异常对象将错误信息告知给调用者。具体语法如下 throw new XXXException(异常产生的原因) 举例 public static int[] arr {1,2,3};public static int getElem(int index) {if(index 0 || index arr.length) {throw new ArrayIndexOutOfBoundsException(index 索引不正确数组越界);}return arr[index];}public static void main(String[] args) {int[] arr {1,2,3};System.out.println(getElem(0));// 正确 输出1System.out.println(getElem(10));// 异常System.out.println(getElem(1));// 不输出} 注意
throw必须写在方法内部抛出的异常必须是Exception或Exception的子类如果抛出的异常是RuntimeException或其子类不需要处理直接交给JVM处理如果抛出的异常是受查异常必须通过throws进行处理否则无法通过编译.异常一旦抛出其后的代码就不会执行
五.异常的捕获 异常的捕获 就是异常处理的具体方式包括两种方式 try,catch语句throws声明 1.异常声明throws 处在方法声明时参数列表之后当方法中抛出编译时异常用户不想处理该异常此时就可以借助throws将异常抛 给方法的调用者来处理。即当前方法不处理异常提醒方法的调用者处理异常。 语法格式 修饰符 返回值类型 方法名(参数列表) throws 异常类型1异常类型2...{ } 比如上文的Cloneable接口的实现 注意 throws必须跟在方法的参数列表之后声明的异常必须是 Exception 或者 Exception 的子类方法内部抛出了多个异常throws也要抛出多个异常异常之间通过”,“隔开如果异常之间存在父子关系只需声明父类异常即可
public class Config {
File file;
// public void OpenConfig(String filename) throws IOException,FileNotFoundException{
// FileNotFoundException 继承自 IOException
public void OpenConfig(String filename) throws IOException{
if(filename.endsWith(.ini)){
throw new IOException(文件不是.ini文件);
}
if(filename.equals(config.ini)){
throw new FileNotFoundException(配置文件名字不对);
}
// 打开文件
}
public void readConfig(){
}
}
调用声明抛出异常的方法时调用者必须对该异常进行处理或者继续使用throws抛出
2 try-catch捕获并处理 throws声明异常并没有处理异常只是将异常交给调用者去处理一直传递给JVM虚拟机要想真正处理异常就需要try-catch语句 注意
1.try中存放可能出现异常的代码也就是说不一定会抛出异常
2.catch存放异常的类型{}内部存放处理的代码处理完成后会继续执行后续代码如果没有捕获到异常则catch里的语句并不会被执行
3.finally中的语句一定会被执行
4.打印异常有三种 5.如果抛出异常类型与catch时异常类型不匹配即异常不会被成功捕获也就不会被处理继续往外抛直到 JVM收到后中断程序----异常是按照类型来捕获的 6.如果异常之间存在父子关系子类异常被捕获时在前父类在后如果顺序颠倒子类异常的捕获就没有任何意义了
public static void main(String[] args) {
int[] arr {1, 2, 3};
try {
System.out.println(before);
arr null;
System.out.println(arr[100]);
System.out.println(after);
} catch (Exception e) { // Exception可以捕获到所有异常
e.printStackTrace();
}catch (NullPointerException e){ // 永远都捕获执行到
e.printStackTrace();
}
System.out.println(after try catch);
}7.无论如何finally中的代码一定会被执行
public static int[] arr {1,2,3};public static int getElem(int index) {return arr[index];}public static void main(String[] args) {int[] arr {1,2,3};try{System.out.print(getElem(100));// 异常}catch (Exception e) {e.printStackTrace();}finally {System.out.println(finally中的代码一定会被执行);}
} 在写程序时有些特定的代码不论程序是否发生异常都需要执行比如程序中打开的资源网络连接、数据库 连接、IO流等在程序正常或者异常退出时必须要对资源进进行回收。另外因为异常会引发程序的跳转可能 导致有些语句执行不到finally就是用来解决这个问题的。 思考那我们该如何记录并处理异常呢什么时间去处理异常呢 在目前我们所写的代码中常常采取记录错误日志的方式来记录异常通过编译器的报错告诉程序员出错的地方 六.如何设计一个自定义类型的异常 将你可能出现的异常设计为一个继承Exception或RunTimeException的类添加一个带参数的构造方法用于打印错误信息,在调用时一旦出错就抛出对应的异常即可 注意继承Exception的类是受查异常必须在调用的方法声明中添加throws该异常
继承RunTimeException的类是非受查异常不需要添加声明 e.printStackTrace();打印异常信息 class UsernameException extends RuntimeException {public UsernameException(String message) {super(message);}
}class PasswdException extends RuntimeException {public PasswdException(String message) {super(message);}
}class Login {private String Username;private String Passwd;public static void logininfo(String Username,String Passwd) {if(!Username.equals(admin)) {throw new UsernameException(用户名错误);}else if(!Passwd.equals(123456)) {throw new PasswdException(密码错误);}}
}
public class Test1 {public static void main(String[] args) {try {Login.logininfo(admin2,123456);}catch (UsernameException ex) {ex.printStackTrace();}catch (PasswdException ex) {ex.printStackTrace();}}
}
异常总结
1.throw抛出一个异常 用于参数检测 一旦出错就可以达到终止程序运行的操作
比如传递数组和数组的下标 1.如果数组是null 直接抛出空指针异常程序停止运行 2.如果下标超过数组的范围直接抛出数组越界异常程序停止运行 之前出现这种错误只打印错误的信息比如arr null sout(数组为空)这种方式太温柔了只告诉你有错误但不会终止运行直接抛异常既能知道错误的信息又能终止程序的运行
2.异常处理关键字的理解
throws是一种甩锅行为通过在方法的生命中添加throws异常种类将这个可能出现的异常交给调用者处理而调用者可以在他的方法声明时添加throws异常交给jvm去处理就是一种甩锅但很方便不需要设置try catch
try catch finally throws并没有处理异常只是甩锅给其他人try catch是一种自己解决异常的方法通过catch捕获异常并记录异常的日志 所谓的捕获异常就是解决该异常异常都是被抛出的catch接受抛出的异常给他限制在笼子里这样就没有异常了
finally有些代码无论程序是否异常都必须要被执行比如电脑就算连不上网也要能看到界面啊再比如校园网欠费无法上网但是我还能打开缴费网站如果打不开那我怎么解决上网的问题所以finally就是用来解决这种任何情况下都要执行的代码(也就是说无论你欠不欠费都能打开缴费网站) 对于已受查异常来说其异常会在编译的时候发现必须通过tycatch语句捕获或者在方法签名使用throws抛出
3.异常处理的流程
程序先执行 try 中的代码 如果 try 中的代码出现异常, 就会结束 try 中的代码,看和 catch 中的异常类型是否匹配. 如果找到匹配的异常类型, 就会执行 catch 中的代码如果没有找到匹配的异常类型, 就会将异常向上传递到上层调用者.无论是否找到匹配的异常类型, finally 中的代码都会被执行到(在该方法结束之前执行).如果上层调用者也没有处理的了异常, 就继续向上传递.一直到 main 方法也没有合适的代码处理异常, 就会交给 JVM 来进行处理, 此时程序就会异常终止