文章目录
异常
-
程序执行时,出现了不可预见的错误信息,被称为异常
-
java将该异常输出到控制台上,供程序员参考,进行程序的修改,使得程序更加健壮
-
异常在java中以类形式存在,每一个异常类都可以创建异常对象 ——例题一
-
异常的继承结构:使用UML图描述
- UML是统一建模语言,UML描述类与类之间的关系,程序执行的流程,对象的状态
-
Exception是 Throwable(可抛出的)的子类
- Throwable包括两个子类,另外一个是Error【不可处理,直接退出JVM】,而Exception是可处理的
- exception包括ExceptionSubClass和RuntimeException两个之类
- ExceptionSubClass属于编译时异常(受检异常),编译时异常表示必须在编译程序的时候预先对这种异常进行处理,如果不处理编译器报错。【语法错误】【编译异常和运行异常都发生在运行阶段,编译时异常发生概率较高,运行时异常发生概率较低。对于较高概率的异常,需要在运行之前对其进行预处理】
- RuntimeException属于运行时异常(未受检异常) ——例题二
-
java语言对异常的处理包括两种方式 ——例题三
- 方式一:在方法声明的位置上,使用throws关键字,抛给上一级【谁调用抛给谁】。
- 方式二:使用try …catch进行异常捕捉。
-
异常的重要方法: ——例题六
- 获取异常简单的描述信息 String msg = exception.getMessage();
- 打印异常追踪的堆栈信息 exception.printStackTrace();
- 使用自动生成try catch方法的时候在catch语句块会打印异常信息。程序员理解异常信息可以帮助自己快速调解程序。【异常现象从上往下看,看自己编写的类,找到根源】
-
关于try catch中的finally子句 ——见例七
- 在finally子句中的代码最后执行,并且一定会执行,即使try语句块代码出现异常
- finally语句必须和try一起出现,不能单独编写
- finally子句的适用情况:通常在finally语句块完成资源的释放/关闭。
- try中的return和fianlly执行顺序
- try语句块中执行退出jvm,finally将不再执行!!
-
子类继承父类,继续方法的重写,重写之后的方法不能比重写之前的方法抛出更多(更宽泛)的异常,可以更少。
- 父类不抛,子类不能抛
- 父类抛FileNotFoundException,子类不能抛Exception
- 父类抛IOException,子类可以抛IOException,也可以抛FileNotFoundException等IOException的子类,也可以不抛。
- 异常使用的关键字
- try catch finally
- throws 在方法声明时使用,表示上报异常信息给调用者
- thorw是手动抛异常。
空指针异常
- NullPointerException
数组下标越界异常
- ArrayIndexOutOfBoundsException
类型转换异常
- ClassCastException
数字格式化异常
- NumberFormatException
- Integer m1 = new Integer(“张掖”); //虽然Integer可以传入字符串,但是字符串要求是以数字类型组成的
例题一
package Advance.exception;
/**
* @author 衣鱼
* java提供异常机制的作用
* 程序执行时,出现了不可预见的错误信息,被称为异常
* java将该异常输出到控制台上,供程序员参考,进行程序的修改,使得程序更加健壮
*
* 异常在java中以类形式存在,每一个异常类都可以创建异常对象
*/
public class EXceptionTest01 {
public static void main(String[] args) {
//通过异常类,实例化异常对象
NumberFormatException nfe = new NumberFormatException("数字格式化异常");
System.out.println(nfe); //toString方法
ClassCastException cce = new ClassCastException("类型转换异常");
System.out.println(cce);
ArrayIndexOutOfBoundsException aobe = new ArrayIndexOutOfBoundsException("数组下标越界异常");
System.out.println(aobe);
NullPointerException npe = new NullPointerException("空指针异常");
System.out.println(npe);
}
}
例题二
package Advance.exception;
public class ExceptionTest02 {
public static void main(String[] args) {
System.out.println(100/0);
/**
* 程序执行到此发生了ArithmeticException异常
* 底层new ArithmeticException异常对象
* 然后抛出ArithmeticException给main方法
* main方法没有处理,将这个异常自动抛给JVM
* jvm最终终止程序执行 所不会输出hello world
*
* ArithmeticException属于运行时异常
*/
System.out.println("hello world !");
}
}
例题三
package Advance.exception;
/**
* @author 衣鱼
* doSome()方法调用报错的原因是什么?
*/
public class ExceptionTest03 {
//第一种处理:在方法声明上继续使用throws ,来完成异常的继续上抛 ,抛给调用者
//上抛类似推卸责任 ,将异常抛给调用者
//public static void main(String[] args) throws ClassNotFoundException {
/**
* main方法调用doSome()方法
* 因为doSome()方法声明位置上有throws ClassNotFoundException
* 所以在调用doSome()方法时,必须对异常进行预先处理
* 如果不处理,编译器会报错
*/
// doSome(); //编译器报错 :Unhandled exception type ClassNotFoundException
// }
//第二种方式 try ......catch 进行捕捉
//捕捉相当于把异常拦下来,上层不知道
public static void main(String[] args) {
try {
doSome();
}catch(ClassNotFoundException e) {
e.printStackTrace();
}
}
/**
* doSome方法在方法声明的位置使用了throws ClassNotFoundException
* 这个代码表示doSome()方法在执行过程中,可能出现ClassNotFoundException异常
* ClassNotFoundException的父类属于Exception,所以 ClassNotFoundException属于编译时异常
* @return
* @throws ClassNotFoundException
*/
public static void doSome() throws ClassNotFoundException{
//System.out.println("dosome !");
}
}
例题四
package Advance.exception;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
/**
* @author 衣鱼
*
*/
public class ExceptionTest04 {
public static void main(String[] args) {
System.out.println("main begin");
m1();
System.out.println("main over");
}
private static void m1() {
System.out.println("m1begin");
m2();
System.out.println("m1over");
}
private static void m2() {
System.out.println("m2begin");
m3();
System.out.println("m2over");
}
private static void m3() {
//调用sun jdk的构造方法
/**
* 运行报错
* 该处调用了一个构造方法: FileInputStream();
* 该方法的源代码声明位置上有:throws FileNotFoundException
* 通过类的继承结构看到:FileNotFoundException 父类是IOException
* IOException的父类Exception,所以,FileNotFoundException是编译时异常
*
* 编译时异常要求程序员编写程序对该程序进行处理,不处理就会报错。
*/
//new FileInputStream("C:\\Users\\衣鱼\\Desktop\\课后题.docx"); //创建一个输入流对象,该流指向一个文件
try {
new FileInputStream("C:\\Users\\衣鱼\\Desktop\\课后题.docx"); //创建一个输入流对象,该流指向一个文件
}catch(FileNotFoundException ffe) { //往上写父类没有问题
System.out.println("文件未找到");
}
}
}
例题五
package Advance.exception;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
/**
* @author 衣鱼
* 异常捕捉的情况下,方法的后续代码照样执行。
* 异常上抛的情况下,方法的后续代码不再执行。
*
* try catch
* 1、catch后的小括号中的类型可以是具体的异常类型,也可以是该异常类型的父类型
* 2、catch可以写多个,建议精确到一个个处理,有利于程序调试
* 3、catch多个情况处理时,从上到下必须遵从从小到大的原则。先子类再父类。
*/
public class ExceptionTest04 {
public static void main(String[] args) {
System.out.println("main begin");
m1();
System.out.println("main over");
}
private static void m1() {
System.out.println("m1begin");
m2();
System.out.println("m1over");
}
private static void m2() {
System.out.println("m2begin");
m3();
System.out.println("m2over");
}
private static void m3() {
//调用sun jdk的构造方法
/**
* 运行报错
* 该处调用了一个构造方法: FileInputStream();
* 该方法的源代码声明位置上有:throws FileNotFoundException
* 通过类的继承结构看到:FileNotFoundException 父类是IOException
* IOException的父类Exception,所以,FileNotFoundException是编译时异常
*
* 编译时异常要求程序员编写程序对该程序进行处理,不处理就会报错。
*/
//new FileInputStream("C:\\Users\\衣鱼\\Desktop\\课后题.docx"); //创建一个输入流对象,该流指向一个文件
try {
new FileInputStream("C:\\Users\\衣鱼\\Desktop\\课后题.docx"); //创建一个输入流对象,该流指向一个文件
}catch(FileNotFoundException ffe) {
System.out.println("文件未找到");
}
try {
new FileInputStream("C:\\Users\\衣鱼\\Desktop\\随机算法.docx"); //创建一个输入流对象,该流指向一个文件
}catch(FileNotFoundException ffe) {
System.out.println("文件未找到");
}catch(IOException ie) {
System.out.println("读文件报错");
}
}
}
例题六
package Advance.exception;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
/**
* @author 衣鱼
* 异常对象的重要方法
* String msg = exception.getMessage(); //获取异常简单的描述信息
* exception.printStackTrace(); //打印异常追踪的堆栈信息
*/
public class ExceptionTest05 {
public static void main(String[] args) {
NullPointerException e = new NullPointerException("空指针异常dfhhediue"); //new异常对象,但没有抛出 不会中断程序
//获取异常信息,构造方法的String参数
String msg = e.getMessage(); //空指针异常dfhhediue
System.out.println(msg);
//打印异常堆栈信息
e.printStackTrace(); //后台打印信息的时候,采用了异步线程的方式
System.out.println("hello world ");
m1();
}
private static void m1() {
m2();
}
private static void m2() {
m3();
}
private static void m3() {
//自动生成try catch
try {
new FileInputStream("C:\\Users\\衣鱼\\Desktop\\课后题.docx");
} catch (FileNotFoundException e) {
//System.out.println("文件未找到");
e.printStackTrace(); //异常追踪信息
System.out.println("=======================================");
String msg = e.getMessage();
System.out.println(msg);
}
}
}
例题七
package Advance.exception;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
/**
* @author 衣鱼
* 关于try catch中的finally子句:
* 1、在finally子句中的代码最后执行,并且一定会执行,即使try语句块代码出现异常
* 2、finally语句必须和try一起出现,不能单独编写
* 3、finally子句的适用情况:通常在finally语句块完成资源的释放/关闭。
*/
public class ExceptionTest06 {
public static void main(String[] args) {
FileInputStream fs = null; //声明位置放在try的外面,这样在finally中才能使用
try {
fs = new FileInputStream("C:\\Users\\衣鱼\\Desktop\\课后题.docx");
//空指针异常
String s = null;
s.toString();
System.out.println("+++++======+++++++"); //不会在控制台输出,因为空指针异常;所以try中以后的代码也不会执行
//关闭流 流不关闭还是需要占用资源的
//目标:即使上面的程序出现异常,流仍然需要关闭
//fs.close();
}catch (FileNotFoundException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (IOException e) { //关闭流
// TODO Auto-generated catch block
e.printStackTrace();
}finally {
//finally的代码一定会执行,即使try出现异常
//将关闭流的代码放入finally更适合
if(fs!=null){
//fs.close(); //IO异常,进行捕捉
try {
fs.close();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
System.out.println("................................................................."); //输出,finally语句中都会执行
}
}
}
package Advance.exception;
/**
* @author 衣鱼
* finally的深层次理解
* try中的return和fianlly执行顺序
*/
public class ExceptionTest07 {
public static void main(String[] args) {
//try finally 没有catch 是可以的
/*
//代码的执行顺序:
//先执行try
//再执行finally
//最后执行return [return执行,方法必然结束]
try {
System.out.println("try......");
return; //finally内的代码块依旧会执行
}finally {
System.out.println("finally......");
}
//System.out.println("==============="); //代码不会执行
*/
try {
System.out.println("try......");
//退出jvm
System.exit(0); //退出jvm finally不会执行
}finally {
System.out.println("finally......");
}
}
}
finally面试题
package Advance.exception;
/**
* @author 衣鱼
* 面试题:
* 输出结果是什么?——100
*
*java语法规则:
* 方法体中的代码必须遵循自上而下的顺序依次执行
* return语句一旦执行,整个方法必须结束
*/
public class ExceptionTest08 {
public static void main(String[] args) {
int result = m();
System.out.println(result);
}
public static int m() {
int i =100; //流程①
try {
//这行代码出现在int i= 100 后面 所以最终返回必须是100
//return一定是最后执行的,一旦执行,整个方法结束
return i; //流程③
}finally {
i++; //流程②
}
}
/*
m()反编译之后的效果
public static int m() {
int i =100;
int j = i;
i++;
return j;
}
*/
}
final finally finalize 区别
package Advance.exception;
/**
* @author 衣鱼
*
*/
public class ExceptionTest09 {
public static void main(String[] args) {
//final 是一个关键字 表示最终的不变的
final int i =100;
//finally 是一个关键字 和try联合使用
//finalize 是Object类中的一个方法 作为一个方法名存在
//标识符 该方法由垃圾回收器调用
}
}
见Object文章
自定义异常
- SUN提供的JDK内置的异常是不够用的,且具体的业务具有自己独特的问题,出现的异常在JDK中是不存在的。
- java中自定义异常
- ①编写一个类继承Exception或者RuntimeException
- ②提供两个构造方法,一个无参,一个有参。
package Advance.exception;
/**
* @author 衣鱼
* 自定义异常
* 异常类型:MyException
* 父类: Exception
*/
public class MyException extends Exception {
public MyException() {
}
public MyException(String s) {
}
}
package Advance.exception;
/**
* @author 衣鱼
* 测试自定义的异常类
*/
public class MyExceptionTest {
public static void main(String[] args) {
MyException me = new MyException("用户名不能为空"); //调用自定义的异常测试程序的时候需要throw出去
//throw me; //如果自定义异常是编译时异常,需要进行预处理,此时我们刚抛出去异常,不能在使用catch捕捉,在方法上继续throws
me.printStackTrace();
}
}
模拟用户注册
package homework;
/**
* @author 衣鱼
* 编写程序模拟用户注册
* 1、程序执行,需要用户输入”用户名“、”密码“
* 2、输入信息后。后台java程序模拟用户注册
* 3、注册用户名要求长度【3-10】之间。其他为异常
*
*/
public class Register {
public static void main(String[] args) {
UserServise us = new UserServise();
try {
us.register(args[0],args[1]);
} catch (MyUserException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
/**
*
* @author 衣鱼
* username 用户名
* password 密码
* 当用户名为空、用户名小于3位、用户名大于10位 出现MyUserException 异常
*/
class UserServise{
public void register(String username ,String password) throws MyUserException {
//引用等于null判断最好放在最前面
//username == null 不如写成 null==username 考虑到程序员失误,把双等于写成一个赋值等于
if(null ==username||username.length()<3||username.length()>10) {
//MyUserException mue =new MyUserException("注册用户名要求长度【3-10】之间");
//throw mue;
throw new MyUserException("注册用户名要求长度【3-10】之间");
}else {
System.out.println("注册成功");
}
}
}
//自定义异常类
class MyUserException extends Exception{
public MyUserException() {
}
public MyUserException(String s) {
super(s);
}
}