欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

java之9天 异常处理,throw 和 throws,finally

程序员文章站 2022-07-12 14:47:12
...
异常处理
/**
 *异常: 就是程序在运行时出现不正常情况
 *异常由来: 问题也是现实生活中的事物,也可以通过java类的形式进行描述,并进行封装. 
 *
 *对于问题的划分:  
 *   1: 严重的问题 (Error) :   java通过Error类进行描述,一般不编写针对性的代码进行处理
 *   2: 非严重的问题 (Exception): java通过Exception类进行描述,一般使用针对性的处理方式进行处理
 *   
 *无论 Error 或者 Exception 都具有一些共性的内容
 *比如: 不正常的情况信息,引发原因等  
 *  所以就出现了 "Throwable" 这个父类
 *  
 * Throwable
 *    |--Error
 *    |--Exception 
 *  
 *
 *2.异常的处理
 *  java 提供了特有的语句进行处理
 *  
 * try{
 *     需要被检测
 * }catch(异常类 变量){
 *    出来异常的代码:(处理方式)
 * }finally{
 *   一定会执行的语句
 * }
 * 
 * 3.对捕获到的异常信息进行处理
 *   1. String getMessage();        //打印  异常信息
 *   2. String toString();          //打印  异常名称 : 异常信息
 *   3. void printStackTrace();   //打印最全名:  异常 名称 : 异常信息  : 异常位置  ; 是 JVM 默认异常处理机制,就是调用这个方法
 * 
 * 4.问题: 发现下面的程序有时候能正常运行,有时候不能, 因为不是所以认得知道这个方法会抛出异常 ,也不是所有人都会处理 这个异常. 怎么办 ?
 *   所以就出现  throws  抛出异常
 */
class Demo{
	static int div(int a,int b){
		return a/b;
	}
}


public class ExceptionDemo {
	public static void main(String[] args) {
		//exception
		try{
			int x=Demo.div(4, 0); //除数不能为0 ,抛出 new ArithmeticException(); 程序会终止 
			System.out.println("x="+x);  //出现异常后  这句话就不会被执行  直接进入 catch 语句块中去了
		}catch(Exception e){  // Exceptioin e= new ArithmeticException();
			System.out.println("除数为0啦!");
			System.out.println(e.getMessage()); // "/ by zero"
			System.out.println(e.toString());//toString() 可以省略   打印   异常名称 : 异常信息
			e.printStackTrace();   //打印最全名:  异常 名称 : 异常信息  : 异常位置.
			
		}
		System.out.println("run over"); //运行 完  catch语句块后 , 接着运行 这句
		
		//error
		byte[] arr=new byte[1024*1024*6000];
		//超出虚拟据总内存大小  不管在怎么样 也不能超过物理内存大小 ,这程序也没戏了.
	}
}


throws  多异常处理

/**
 * throws
 * 1. throws: 在功能上通过throws的关键字声明该功能有可能出现问题.
 * 
 * 2.被声明后  我们必须告诉程序的处理方式
 *    1.采用 try catch 进行处理
 *    2.继续抛出 异常 ,由jVM 虚拟机 进行异常处理  不过这样 程序 就会终止.
 *    
 *    
 * 多异常的处理
 *   1.声明异常时,建议声明更为具体的异常,这样 处理的可以更具体 
 *     比如: 下面 throws ArithmeticException 而不写成 throws Exception
 *     
 *   2.对于声明多个异常,在调用的时候就应该有几个 catch块.不要定义多余的catch块 ,比如下面注释的 catch块
 *      如果多个catch中的异常出现了继承关系,父类异常catch块 放在最下面 .
 *      
 *   建议:在进行catch处理时,catch一定要定义具体的处理方式
 *       不要简单的一句. e.printStackTrace();
 *       也不要简单的就书写一条输出语句 ,一般采用log日志文件 进行 异常信息记录
 *
 */

class Demo{
	static int div(int a,int b) throws ArithmeticException{
		
		return a/b;
	}
}

class Demo1{
	static int div(int a,int b) throws ArithmeticException,ArrayIndexOutOfBoundsException{
		int [] arr=new int[a];
		System.out.println(arr[a+1]);  //出现越界
		return a/b;
	}
}

public class ExceptionDemo1 {

	/**
	 * thrwos
	 */
	public static void main(String[] args) {
		// 使用第一种方法处理
		try {
			Demo.div(4, 0);
		} catch (Exception e) {
			System.out.println(e.toString());
		}
	}
	
	// 使用第二种方法处理  继续往上抛出异常 让 JVM 帮我处理  
	public static void otherMethod() throws ArithmeticException{
		Demo.div(4, 0);
	}

	/**
	 * 多异常处理
	 */
	public static void otherMethod1() throws ArithmeticException,ArrayIndexOutOfBoundsException{
		Demo1.div(4, 0);
	}
	
	public static void otherMethod2() {
		try {
			Demo1.div(4, 0);
		} catch (ArithmeticException e) {
			System.out.println(e.toString());
			System.out.println("被0除了");
		}catch(ArrayIndexOutOfBoundsException e){
			System.out.println(e.toString());
			System.out.println("角标越界");
		}/*catch(Exception e){  //这样做只会隐藏 异常 ,这样做是不对的
			System.out.println(e.toString());
		}*/
		 
	}
	
}


throws 和throw 的区别   
自定义 异常类


/**
 * 因为项目中会出现特有的问他你.
 * 而这些问题并未被java所描述和封装成对象
 * 所以对于一些特有的问题可以安装java的对问题封装的思想.
 * 将特有的问题,进行自定义的异常封装
 * 
 * 
 * 自定义异常
 * 
 * 需求: 在本程序中,对于除数 是-1 也视为错误的,是无法进行运算.
 * 那么就需要对这个问题进行自定义的描述.
 *
 *当函数内部初相了throw抛出异常对象,那么就必须要给对应的处理动作.
 *要么在内部 try catch 处理
 *要么子啊函数上声明让调用者处理.
 *
 *一般情况下, 函数内部出现异常,函数上需要声明.
 *
 *发现 打印的结果中只有异常的名称,却没有异常的信息
 *因为自定义的异常并未定义信息
 *
 *如何定义异常信息呢?
 *  因为父类中已经把异常信息的操作都做完了
 *  所以子类只要在构造时,将异常信息传递给父类通过super语句
 *  就可以直接通过getMessage获取自定义的异常信息
 *
 *自定义异常:必须是自定义类继承 Exception
 *
 *继承Exception原因:
 *  异常体系有一个特点,因为异常类和异常对象都被抛出
 *  因为他们都具备可抛性,这个可抛性是Trowable这个体系中独有的特点.
 *
 *  只有这个体系中的类和对象才可以被throw 和 throw 操作
 *  
 *throws 和throw 的区别
 *throws:使用在函数上
 *throw:使用在函数内
 *
 *throws:后面跟的异常类,可以跟多个,用逗号分开
 *throw:后跟的是异常对象.
 */
class FuShuException extends Exception{
	
	/*
	private String msg;
	FuShuException(String msg){
		this.msg=msg;
	}
	public String getMessage(){
		return this.msg;
	}
	*/
	FuShuException(String msg,int num){
		super(msg);
		this.value=num;
	}
	private int value;
	
	public int getValue(){
		return value;
	}
	
}

//自定义 异常类
class Demo{
	
	static int div(int a,int b) throws FuShuException{
		if(b<0)
			throw new FuShuException("出现了除数为零的情况  / by fushu",b);  //手动通过throw 关键字抛出一个自定义异常对象.
		return a/b;
	}
}


public class ExceptionDemo2 {

	public static void main(String[] args) {
		// TODO Auto-generated method stub
		try {
			Demo.div(4, -1);
		} catch (FuShuException e) {
			System.out.println(e.toString());
			System.out.println("除数出现负数了!");
			System.out.println("负数是:"+e.getValue());
		}
		System.out.println("over");
	}

}




RuntimeException

/**
 *RuntimeException:
 *  Exception中有一个非常特殊子类异常,RuntimeException 运行时异常
 *  如果在函数内部使用throw抛出异常,函数上可以不用throws声明,编译一样通过.
 *  如果在函数上使用throws声明了该异常,调用者可以不用进行处理,编译一样通过;
 *之所以不用在函数上使用throws声明,是因为不需要让调用者处理
 *当异常发送,JVM希望程序停止,因为在运行时,出现了无法继续运算的情况,希望停止程序后,然程序员对代码进行修正
 *
 *自定义异常时,如果该异常的发生,无法在继续进行运算,就让自定义异常继承RuntimeException.
 *
 *对于异常的分类
 *1.编译时被检测的异常 (必须使用 throws 或者 try catch进行处理)
 *
 *2.编译时不被检测的异常(运行时异常,RuntimeException以及其子类) 程序会停止掉,然后要改进代码
 *
 */
class Demo{
	static int div(int a,int b){ //发现  这里不需要 throws 怎么回事?
		if(b==0)
			throw new ArithmeticException("被零除了!"); //需改 java自定义异常中的提示,改成我们熟悉的
		return a/b;
	}
	
	static int div1(int a,int b)throws ArithmeticException{ 
		//if(b==0)
			//throw new Exception("被零除了!"); //需改 java自定义异常中的提示
		return a/b;
	}
	
	static int div2(int a,int b){ //发现  这里不需要 throws 怎么回事?
		if(b<0)
			throw new FuShuException("出现除数为负数了"); //需改 java自定义异常中的提示
		if(b==0)
			throw new ArithmeticException("被零除了!");
		return a/b;
	}
	
}
//自定义 运行时异常类
class FuShuException extends RuntimeException{
	
	public FuShuException(String msg) {
		super(msg);
	}
}

public class ExceptionDemo3 {

	public static void main(String[] args) {
		// TODO Auto-generated method stub
		/*Demo.div(4, 0);   // 
		Demo.div1(4, 0);  //发现没有 try catch  编译也通过
		
		Demo.div2(4, -9);*/
		
		
		//讲课
		Teacher t=new Teacher("张老师");
		try {
			t.prelect();
		} catch (NoPlanException e) {
			System.out.println(e.toString());
			System.out.println("换老师 或者 放假!");
		}
	}

}


/*
 * 老师上课
 * 
 * 思考上课中出现的问题 
 *   比如问题: 电脑蓝屏
 *           电脑冒烟
 *           
 *  要对问题进行封装成对象.
 *  冒烟后,出现讲课进度无法继续
 *  出现了讲师的问题,课时计划无法完成.
 *  
 *  throw 和 return 单独存在的时候,后面不能出现 其他语句 
 */
class Teacher{
	private String name;
	
	private Computer cmpt;
	Teacher(String name){
		this.name=name;
		this.cmpt=new Computer();
	}
	
	public void prelect()throws NoPlanException{
		try {
			cmpt.run();
		} catch (LanPingException e) {
			cmpt.reset();
		} catch (MaoYanException e) {
			test();
			throw new NoPlanException("课时无法继续"+e.getMessage());
			//test(); //不能放在这里 ,throw 和 return 单独存在的时候,后面不能出现 其他语句 
		}
		System.out.println("讲课");
	}
	
	public void test(){
		System.out.println("练习!");
	}
	
	
}
class Computer{
	private int status=3;
	public void run()throws LanPingException,MaoYanException {
		if(status==2)
			throw new LanPingException("蓝屏了");
		if(status==3)
			throw new MaoYanException("冒烟了");
		
		System.out.println("电脑运行");
	}
	public void reset(){
		this.status=1;
		System.out.println("电脑重启");
	}
}

//封装问题
class LanPingException extends Exception{
	LanPingException(String message){
		super(message);
	}
}

class MaoYanException extends Exception{
	MaoYanException(String message){
		super(message);
	}
}
//冒烟后的异常
class NoPlanException extends Exception{
	NoPlanException(String message){
		super(message);
	}
}


finally

/**
 * finally代码快:定义一定要执行的代码
 * 通常用于关闭资源
 * 如果 catch中 有return 的时候  finally 代码会被执行 而其他的代码不会被执行.
 */
class FuShuException extends Exception{
	FuShuException(String msg){
		super(msg);
	}
}

class Demo{
	static int div(int a,int b)throws FuShuException{
		if(b<0)
			throw new FuShuException("除数为负数!");
		return a/b;
	}
}
class NoException extends Exception{
	
}
public class FinallyDemo1 {

	public static void main(String[] args) {
		test1();  //   除数为负数!     finally   over
		
		test2(); //   除数为负数!      finally
	}
	public static void test1(){
		try {
			int x=Demo.div(4, -1);                       //1
			System.out.println("x="+x);
		} catch (FuShuException e) {
			System.out.println(e.toString());            //2
		}finally{
			System.out.println("finally");               //3
		}
		System.out.println("over");                      //4
	}
	
	public static void test2(){
		try {
			int x=Demo.div(4, -1);                       //1
			System.out.println("x="+x); 
		} catch (FuShuException e) {
			System.out.println(e.toString());            //2  
			return; // 使用return后                                                                 //4
		}finally{
			System.out.println("finally");               //3
		}
		System.out.println("over");
	}
	
	
	/**
	 * 采用分层的思想来设计 一般不会抛出 SQLException 给调用者 而是给一个 调用者能看的懂的异常
	 */
	public void method()throws /*SQLException*/NoException {
		//连接数据库
		//数据操作:  //throw new SQLException();
		//关闭数据库
		
		try {
			//连接数据库
			//数据操作: 
		}catch (SQLException e) {
			//会对数据库进行异常操作
			//throw new SQLException();
			throw new NoException();
		}finally{
			//关闭数据库
		}
	}

}

/**
 * 
 *异常的几种格式
 *
 *记住一点:catch是用户处理异常,如果没有catch就代表异常没有被处理过,如果该异常是检测时异常,那么使用 throws必须声明.
 */
class ExceptionStyle{
	//异常的几种格式
	public void method(){
		//第一种格式
		try {
			
		} catch (Exception e) {
			// TODO: handle exception
		}
		
		//第二种格式
		try {
			
		} catch (Exception e) {
			// TODO: handle exception
		}finally{
			
		}
		//第三格式
		try{
			
		}finally{
			
		}
		
		//第四种 格式
		try {
			
		}catch (ArithmeticException e) {
			// TODO: handle exception
		}catch (Exception e) {
			// TODO: handle exception
		}
		
	}
	
	//看看下面几种情况 
	
	//错误       没有throws  Exception  编译不通过
	public void method1() /*throws  Exception*/{
		throw new Exception();   
	}
	
	//正确
	public void method2(){
		try {
			throw new Exception();
		} catch (Exception e) {
			// TODO: handle exception
		}
		
	}
	
	//错误           处理一个异常后  又抛出了异常  编译不通过
	public void method3(){
		try {
			throw new Exception();
		} catch (Exception e) {
			throw e;
		}
		
	}
	
	//正确         只要  e 被处理就可以了
	public void method4(){
		try {
			throw new Exception();
		} catch (Exception e) {
			try {
				throw e;
			} catch (Exception e2) {
				// TODO: handle exception
			} 
		}
		
	}
	
	//错误      没有catch 或则 throws 就是没有处理  编译 不通过 ,
	public void method5(){
		try {
			throw new Exception();
		}finally{
			//关闭资源   产生的异常 有调用者处理
		}
	}
	
}