20160723 异常/

异常:

程序在执行过程中出现不正常的现象

import java.util.Scanner;

class ExceptionDemon1 
{
	public static void main(String[] args) 
	{
		Scanner sc=new Scanner(System.in);
		System.out.println("请输入除数: ");
		int b=sc.nextInt();
		System.out.println("请输入被除数: ");
		int a=sc.nextInt();

		int num=devide(a,b);//
		System.out.println("商为: "+num);
	}
<pre name="code" class="java">

//除法计算public static int devide(int a,int b){ return a/b;// }}

 
/*请输入除数:
0
请输入被除数:
1
Exception in thread "main" java.lang.ArithmeticException: / by zero
        at ExceptionDemon1.devide(ExceptionDemon1.java:20)
        at ExceptionDemon1.main(ExceptionDemon1.java:13)
请按任意键继续. . .*/

主方法是怎么处理异常的?

主方法在处理异常时是没有对异常做相关的处理操作,
仅仅是将异常的信息,以及相关的错误代码打印到控制台上

class ExceptionDemon2 
{
	public static void main(String[] args) 
	{
		int []array={1,4,6,8};

		for (int i=0;i<array.length ;i++ )
		{
			System.out.println(array[i]);
		}
	}
}

我们应该怎么去处理异常?

      由于异常的信息特别多,我们需要将异常的信息进行封装,
 我们之前学过面向对象,在这里可以采用面向对象的思维去对异常进行封装


 但是异常也分为严重与不严重的情况,通过面向对象的思维模式,可以将异常的这两种情况提取出来进行封装,在java中已经进行了一个体系
 其顶层是Throwable


 Throwable类 是java语言中所有错误和异常的超类


 Throwable
     Error:不在我们处理范围内的异常,属于严重的错误
 Exception:在我们处理范围内的异常,能够通过我们进行处理


       实例1:
    1.我们骑自行车出去玩,自行车的链条坏了----可处理范围内
2.我们骑自行车出去玩,路断了====不在处理范围内


       实例2:
    1.得了感冒----可以买要吃解决
2.得了癌症----吃药是无法解决的,属于严重错误

class ExceptionDemon3 
{
	public static void main(String[] args) 
	{
		byte [] by=new byte[1000*1024*1024];
		System.out.println(by);
 
		/*Exception in thread "main" java.lang.OutOfMemoryError: Java heap space---内存溢出
        at ExceptionDemon3.main(ExceptionDemon3.java:27)*/
	}
}

*Throwable(可抛出;异常;对象)有哪些方法?



  getMessage()--返回此Throwable的详细消息字符串(获取异常信息返回字符串)


  printStackTrace()--将此 throwable 及其追踪输出至标准错误流。(获取异常类名和异常信息,以及异常出现在程序中的位置,返回值void)


  printStackTrace(PrintStream s)--将此 throwable 及其追踪输出到指定的输出流。 (通常用该方法将异常内容保存在日志文件中,以便查阅)
                                 字节流
  printStackTrace(PrintWriter s)--将此 throwable 及其追踪输出到指定的 PrintWriter                                                 "自己去试"
                                  字符流


  toString()--返回此 throwable 的简短描述(获取异常类名和异常信息,返回字符串)


**自己怎么处理异常?
  1.try(发现异常)--catch(处理异常)  finally(处理)  catch是必带的,仅仅try是不可以的


    a.try...catch             一发现一处理
b.try...catch...catch...  一发现多处理(无限多)


**原则:先处理小的,再处理大的

import java.util.Scanner;
import java.lang.ArithmeticException;
import java.lang.ArrayIndexOutOfBoundsException;//导入异常

class  ExceptionDemon4
{
	public static void main(String[] args) 
	{   
        //扫描控制台输入
		/*Scanner sc=new Scanner(System.in);
		System.out.println("请输入除数: ");
		int b=sc.nextInt();
		System.out.println("请输入被除数: ");
		int a=sc.nextInt();*/

        /*   try//发现异常
           //---
		      {
		      int num=devide(a,b);//
              System.out.println("商为: "+num);

			  int[]array={1,3};
			  System.out.println(array[2]);//取不到
              } 
	    */
	  
		     
		 /*  catch(ArithmeticException e)
                   //-----
			   {
                 System.out.println("报错了");
		       }
		   catch(ArrayIndexOutOfBoundsException e)
                 //-----
			   {
                 System.out.println("数组脚标越界");
		       }*/

        /*
                Exception in thread "main" java.lang.ArithmeticException: / by zero
                at ExceptionDemon1.devide(ExceptionDemon1.java:20)
                at ExceptionDemon1.main(ExceptionDemon1.java:13)
       */


			   try
			   {
				int[]array={1,3};
				System.out.println(array[2]);
//				                         -
			   }
			   catch (Exception e)//catch它的父类,下面任何子类报出来的时候,我们都能捕捉到//超级父类Throwable也可以,但一般会这么做,因为会包含Error的错误,Error也捕捉不到
			                                                                                 
			   {
				   System.out.println("报错了");
				   
				  // String message=e.getMessage();//获取异常信息返回字符串
				  // System.out.println(message);//2

				 // e.printStackTrace();//不返回什么,直接打印到控制台(获取异常类名和异常信息,以及异常出现在程序中的位置,返回值void)
				                      //报错了
                                      //java.lang.ArrayIndexOutOfBoundsException: 2--①
                                      //at ExceptionDemon4.main(ExceptionDemon4.java:71)

                 System.out.println(e.toString());//(获取异常类名和异常信息,返回字符串)
				                                  //java.lang.ArrayIndexOutOfBoundsException: 2--①
			   }

			   System.out.println("******结束******");//正常打印
			                                          

        /*
                Exception in thread "main" java.lang.ArithmeticException: / by zero
                at ExceptionDemon1.devide(ExceptionDemon1.java:20)
                at ExceptionDemon1.main(ExceptionDemon1.java:13)
       */


		
	}

    //除法计算
	public static int devide(int a,int b)
		{
		 return a/b;//
	    }
    
}
**①原则:先处理小的,再处理大的


         ②try处理的优先级问题


③try 和 finally 配合问题
  a.
  b.
  c.try...catch...finally(里面的内容为-无论是否异常-必须执行!)
             放在finally里执行的内容一般为:资源必须关闭等操作
           d.try..catch...catch... finally
  e.try...finally
  
  ④为什么不报错的代码我们不一起放到try中?
     (try中要报错的系统会预分配内存)
放在try中的内容,在执行过程中java虚拟机会进行分配相应的空间
如果把没有报异常的代码一并放入try中,会降低程序的执行效率,所以通常不报错的代码不放在try中
*/
import java.util.Scanner;
import java.lang.ArithmeticException;
import java.lang.ArrayIndexOutOfBoundsException;//导入异常

class  ExceptionDemon5
{
	public static void main(String[] args) 
	{   
        //扫描控制台输入
		
		Scanner sc=new Scanner(System.in);
		System.out.println("请输入除数: ");
		int b=sc.nextInt();
		System.out.println("请输入被除数: ");
		int a=sc.nextInt();

     /*      try//发现异常
         //---
		      {
		      int num=devide(a,b);//
              System.out.println("商为: "+num);

			  //int[]array={1,3};
			  //System.out.println(array[2]);//取不到
              } */
	    
	  
		     
		/*  catch(ArithmeticException e)
         //-----
			   {
                 System.out.println("报错了");
		       }
		   catch(ArrayIndexOutOfBoundsException e)
         //-----
			   {
                 System.out.println("数组脚标越界");
		       }
		     catch(Exception e)
         //-----
			   {
                 System.out.println("展现的是父类异常");
		       }*/

System.out.println("------------------分隔符----------------------");
		/*	       try//发现异常
         //---
		      {
		      int num=devide(a,b);//
              System.out.println("商为: "+num);

			  int[]array={1,3};
			  System.out.println(array[2]);//取不到
              } 
	    
	         catch(ArrayIndexOutOfBoundsException e)
         //-----
			   {
                 System.out.println("数组脚标越界");
		       }

		     catch(Exception e)
         //-----
			   {
                 System.out.println("展现的是父类异常");
		       }
			   finally 
				   {
				    System.out.println("最终执行,必须执行我");
			       }*/
System.out.println("------------------分隔符1----------------------");
         /*   	       try//发现异常
         //---
		      {
		      int[]array={1,3};
			  System.out.println(array[2]);//取不到
              } 
	    
	         catch(ArrayIndexOutOfBoundsException e)
         //-----
			   {
                 System.out.println("数组脚标越界");
		       }

			   finally 
				   {
				    System.out.println("最终执行,必须执行我1");
			       }

          try//发现异常
         //---
		      {
		      int num=devide(a,b);//
              System.out.println("商为: "+num);
             } 
	   
		     catch(Exception e)
         //-----
			   {
                 System.out.println("展现的是父类异常");
		       }
			   finally 
				   {
				    System.out.println("最终执行,必须执行我2");
			       }*/
System.out.println("------------------分隔符2----------------------");
			 
			 //System.exit(0);//相当于是程序式的直接中断,之下的内容就不会被执行
			  
			  try//发现异常
         //---
		      {
		      int num=devide(a,b);//
              System.out.println("商为: "+num);

              System.exit(0);//放在这里也可以,无异常时,num输出,finally也不会被执行,没有"结束"
			                   //但是异常时,直接跳到finally执行,输出printStackTrace(),没有"结束"
             } 
			   finally 
				   {
				    System.out.println("最终执行,必须执行我2");
			       }//异常的话,执行依然报错,所以没有"结束"
			System.out.println("******结束******");//正常打印

		}

    //除法计算
	public static int devide(int a,int b)
		{
		 return a/b;//
	    }
    
}

异常的第二种处理方式:

      自己不处理该异常,将该异常[抛出,谁调用谁处理
 抛异常的关键字是throws


*主函数调用了这个异常,主函数两种处理方式
 ①try..catch 处理掉
 ②直接抛掉不再处理(不处理,谁调用谁处理)


*处理异常的两种方式到底哪一种好?
 原则:能处理则处理,处理不好则抛出
class  ExceptionDemon6
{
	public static void main(String[] args) throws Exception//下边也不想处理了,直接交给java虚拟机处理---②
	{
		//int num=devide(10,2);---零
		//System.out.println(num);//5

        //int num=devide(10,0);---零
		//System.out.println(num);//不能除以0
		                        //0
        //int num=devide(10,1);---②
		//System.out.println(num);//10

        int num=devide(10,0);//---②
		System.out.println(num);//报异常,printStackTrace()类型

     /*   try                        //---①
        {
			int num=devide(10,0);
			System.out.println(num);
        }
        catch (Exception e)
        {
			System.out.println("不能除以0");//输出"不能除以0"
        }*/

  /*  try                           //---①
        {
			int num=devide(10,1);
			System.out.println(num);
        }
        catch (Exception e)
        {
			System.out.println("不能除以0");//输出="10"
        }*/
	}


	/*public static int devide(int a,int b)--零
		{

		 int result=0;

		 try
		 {
			result=a/b;
		 }
		 catch (ArithmeticException e)
		 {
			 System.out.println("不能除以0");
		 }
		 return result;
	    }*/

//System.out.println("----------分隔符-------------");

       public static int devide(int a,int b)throws Exception//---①,②
		   //ExceptionDemon6.java:13: 错误: 未报告的异常错误Exception; 必须对其进行捕获或声明以便抛出
		{

		 /*int result=0;

		 try
		 {
			result=a/b;
		 }
		 catch (ArithmeticException e)
		 {
			 System.out.println("不能除以0");
		 }
		 return result;*/
		 return a/b;
	    }

}

throws 和throw



  throws用于标识函数暴露出的异常
  throw用于抛出异常对象


  *区别:
   1. throws用在函数上,后面跟"异常类名"
   throw用在函数内,后面跟"异常对象"


   2.throws可以单独使用
   throw必须与throws组合使用(RuntimeException)




   处理异常:①抛给java虚拟机②try...catch


            还有一种:直接抛掉,不想交给谁去处理


     **RuntimeException 是那些可能在 Java 虚拟机正常运行期间抛出的异常的超类,
可能在执行方法期间抛出但未被捕获的 RuntimeException 的任何子类都无需在 throws 子句中进行声明。//--在大数据运用中缩短排查错的时间
                                                                                                 今后会教怎么用这种方式去排查错误,缩短查找时间


   RuntimeException与Exception的区别:
         1.Exception是编译时会检测的异常,是需要编写代码进行处理的
2.RuntimeException是运行时的异常,在编译过程中不检测
        
*/
class  ExceptionDemon7
{
/*	public static void main(String[] args) throws Exception          //--调用的是throws
	{
		

        int num=devide(10,0);
		System.out.println(num);
     }

       public static int devide(int a,int b)throws Exception 
		{
		 return a/b;
	    }*/
      
//----------------------------------------------------------------------------------------
    /*
      	public static void main(String[] args) throws Exception  
	{
		

        int num=devide(10,0);
		System.out.println(num);//10(非异常)
     }

       public static int devide(int a,int b) throws Exception
		{
		 int result=0;

		 try
		 {
			result=a/b;
		 }
		 catch (ArithmeticException e)
		 {
			 throw new Exception("不能除以0");//带有了构造函数--异常的话,printStackTrace(),异常名称为"不能除以0"
		 }
		 return result;
	    }*/
//------------------------------------------------------------------------------------
     /*
       	public static void main(String[] args) 
	{
		  try                        
        {
			int num=devide(10,0);
			System.out.println(num);//10(非异常)
        }
        catch (Exception e)
        {
			System.out.println("不能除以0");//输出"不能除以0"(异常)
        }

        //int num=devide(10,1);
		//System.out.println(num);
     }

       public static int devide(int a,int b) throws Exception
		{
		 int result=0;

		 try
		 {
			result=a/b;
		 }
		 catch (ArithmeticException e)
		 {
			 throw new Exception("不能除以0");//带有了构造函数
		 }
		 return result;
	    }*/
//---------------------------------------------------------------------
/*
       	public static void main(String[] args) throws Exception
	{
		//  try                        
        // {
		//	int num=devide(10,0);
		//	System.out.println(num);//10(非异常)
        //  }
        // catch (Exception e)
        // {
		//	System.out.println("不能除以0");//输出"不能除以0"(异常)
        //  }

        int num=devide(10,0);
		System.out.println(num);
     }

       public static int devide(int a,int b) throws Exception
//                                                  ---------
//                                                  到时候抛的不是这个异常,而是其他异常,从114行抛出时,可以有效的帮助我们在前面的代码中查找错误
		{
		 int result=0;

		 try
		 {
			result=a/b;
		 }
		 catch (ArithmeticException e)
		 {
			 throw new Exception("不能除以0");//带有了构造函数--异常的话,printStackTrace(),异常名称为"不能除以0"
			                                  //可以帮我们达到异常的转换目的
		 }
		 return result;
	    }*/
//---------------------------------------------------------------------------------------------------------------
 	public static void main(String[] args) //不抛--------------抛出的是RuntimeException的时候,主函数中谁调用都不需再处理,
	                                       //                  也不需要再进行一个声明
	{
		/*  try                        
        {
			int num=devide(10,0);
			System.out.println(num);//10(非异常)
        }
        catch (Exception e)
        {
			System.out.println("不能除以0");//输出"不能除以0"(异常)
        }*/

        int num=devide(10,0);
		System.out.println(num);
     }

       public static int devide(int a,int b) //不抛
		{
		 int result=0;

		 try
		 {
			result=a/b;
		 }
		 catch (ArithmeticException e)
		 {
			 throw new RuntimeException("不能除以0");//带有了构造函数--异常的话,printStackTrace(),异常名称为"不能除以0"
			                                  //可以帮我们达到异常的转换目的
		 }
		 return result;                           
	    }                                     //输出为:Exception in thread "main" java.lang.RuntimeException: 不能除以0
	                                          //at ExceptionDemon7.devide(ExceptionDemon7.java:154)
	                                          //at ExceptionDemon7.main(ExceptionDemon7.java:140)
}

finalize 当垃圾回收器确定不存在对该对象的更多引用时,由对象的垃圾回收器调用此方法。
            子类重写 finalize 方法,以配置系统资源或执行其他清除。


    final finally finalize三者之间的区别?
final:可以有来修饰类,成员变量,成员方法;如果用来修饰类,则此类不能被继承
     如果用来修饰成员变量,则此变量不能被改变,如果用来修饰成员方法,
 则此方法不能被重写
    finally:属于是异常体系中的一个关键词,一般用于释放资源,永远被执行
       但特殊情况System.exit(0)除外
    finalize:是Object类中的一个方法,当垃圾回收器确定不存在对该对象的更多引用时,由对象
        的垃圾回收器调用此方法

class  FinallyDemon8
{
	public static void main(String[] args) 
	{
		int final String line="测试";
//          -----
		try
		{
			int value=devide(a,b);
			System.out.println("商为:"+value);
		}
		finally ()
		{
			System.out.println("必须执行我");
		}
	}

    //除法计算
	public static int devide(int a,int b)
		{
		 return a/b;
	    }
}

/*

  总结:

   Exception异常体系在继承中的表现情况?
     a.在继承过程中,子类继承方法不能抛比父类中更多更大的异常
b.但可以抛父类中异常的子类异常或是相同的异常,一般是直接抛和父类中相同的异常

*/

/*class Demon
{
public static void printTest()throws ClassNotFoundException
{
System.out.println("调用我会抛异常");//方法抛出了一个异常-----①
                                    //ExtendDemon9.java:12: 错误: 未报告的异常错误ClassNotFoundException; 必须对其进行捕获或声明以便抛出
   }
}
class ExtendDemon9 extends Demon
{
public static void main(String[] args) throws Exception//加上(抛出最大的异常)此句后,输出①
//                                       ----------------
{
printTest();
}
}*/


//-----------------------------------------------------------


/*
  第二项中
   a.throws NotBoundException--ExtendDemon9.java:36: 错误: 找不到符号
   b.throws Exception---ExtendDemon9.java:44: 错误: ExtendDemon9中的printTest()无法覆盖Demon中的printTest()
  
 ** 在子类中不能抛比①中异常还大的异常,可以抛比它小的异常吗?
*/
/*class Demon
{
public static void printTest()throws ClassNotFoundException//--①
{
System.out.println("调用我会抛异常");
   }
}
class ExtendDemon9 extends Demon
{
public static void main(String[] args) throws Exception


{
printTest();
}


public static void printTest()                         //throws NotBoundException与throws Exception//都拋不过去  
//                                ------------------------
{
System.out.println("我是子类");//重写之后,输出"我是子类"
   }
}*/


//*************************************************************************************


//** 在子类中(②)不能抛比①中异常还大的异常,可以抛比它小的异常吗?(①与②的抛出交换)
//                                      A:  只能是相同或是父类中异常的子类  (绝对不能抛上面"没有"的异常)


class Demon
{
	public static void printTest()throws Exception//--①
		{
		System.out.println("调用我会抛异常");
	    }
}
class ExtendDemon9 extends Demon
{
	public static void main(String[] args) throws Exception

	{
		printTest();
	}

	public static void printTest()throws ClassNotFoundException//--②
//                                
		{
		System.out.println("我是子类");//输出:我是子类
	    }
}




/*
  Q1:为什么要采用自定义异常?(有了java体系定义的那一套异常,为什么还要自定义)
  A1:因为java定义的异常是常用的异常,根据我们的业务需求,是无法全部满足的
    所以需要自定义异常

  Q2;怎么定义自定义异常?
  A2:继承Exception或RuntimeException(抛了后者这个异常,不需要在编写代码中做任何处理,但一般很少用这个异常,一般处理一些特殊跟踪异常才会用到)

根据自己的需求,报什么异常,为了跟踪什么错误,然后我们就自己直接自定义异常
*/
/*
class MyException extends Exception
{
	private int  number;
	public MyException(String message,int number)
		{
		 super(message);
		 this.number=number;
	    }
    public int getNumber()
		{
		 return number;
	    }
}

class Demon
{
	public void devide(int a,int b) throws MyException//如果没这个抛出,则ExceptionDemon10.java:30: 错误: 未报告的异常错误MyException; 必须对其进行捕获或声明以便抛出
		{
           if (b<0)
           {
			   throw new MyException("除数不能为0",b);
           }
		   else
			   {
                 System.out.println("商为:"+a/b);
		       }
	    }
}

class ExceptionDemon10
{
	public static void main(String[] args) 
	{
		Demon demon=new Demon();
		demon.devide(2,3);//ExceptionDemon10.java:44: 错误: 无法将类 Demon中的方法 devide应用到给定类型;
		                  //加上"2,3"后,ExceptionDemon10.java:44: 错误: 未报告的异常错误MyException; 必须对其进行捕获或声明以便抛出
	}
}
*/

//------------------------------------------------------------------------------------------------


/*class MyException extends Exception//------------------这里是自定义的异常
{
	private int  number;
	public MyException(String message,int number)
		{
		 super(message);
		 this.number=number;
	    }
    public int getNumber()
		{
		 return number;
	    }
}*/

class MyRuntimeException extends RuntimeException
{
        public MyRuntimeException(String message)
		{
		 super(message);
		 
	    }
}

/*class Demon
{
	public void devide(int a,int b) throws MyException
		{
           if (b==0)
           {
			   throw new MyException("除数不能为0",b);//抛出了"除数不能为零"+0
           }
		   else
			   {
                 System.out.println("商为:"+a/b);
		       }
	    }
}*/

class Demon1
{
	public void devide(int a,int b)throws MyRuntimeException
		{
		 if (b==0)
		 {
			 throw new MyRuntimeException("除数不能为零");//多了",b",//ExceptionDemon10.java:98: 错误: 无法将类 MyRuntimeException中的构造器 MyRuntimeException应用到给定类型;
		 }
		 else 
			 {
			  System.out.println("商为:"+a/b);
		     }
	    }
}

class ExceptionDemon10
{
	public static void main(String[] args) //throws MyException//此处相对于上为新增加--不抛,因为要打印异常信息
	{
		
		/*try
		{
			Demon demon=new Demon();
		    //demon.devide(4,2);//商为:2
            demon.devide(4,-0);//0----除数不能为0
			//demon.devide(4,-2);//商为:-2
		}
		catch (MyException e)
		{
			System.out.println(e.getNumber()+"----"+e.getMessage());
		}*/

		Demon1 demon1=new Demon1();//上面的已经抛了,这里不需要再做声明了
		//demon1.devide(6,1);//6
		demon1.devide(6,0);//Exception in thread "main" MyRuntimeException: 除数不能为零
	                       //at Demon1.devide(ExceptionDemon10.java:98)
	                       //at ExceptionDemon10.main(ExceptionDemon10.java:126)
						   //以上为直接交给java虚拟机进行的处理
	}
}



  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值