zoukankan      html  css  js  c++  java
  • JAVA基础-异常

    1. 异常的概念

    在Java中异常被当做对象来处理,根类是java.lang.Throwable类。所有异常类分为两大类:Error和Exception

    • Error是无法处理的异常,比如OutOfMemoryError(内存),一般发生这种异

    常,JVM会选择终止程序。因此我们编写程序时不需要关心这类异常

    • Exception,也就是我们经常见到的一些异常情况,这些异常是我们可以处理的

    2. 常见的异常及捕获

    下表中列出了几个常见的异常,其中所有的异常都是Exception的子类:

    我们使用try catch块来捕获异常,最基本的用法如下,我们捕获一个NullPointerException异常:

    Ps:请留意异常的打印到栈的用法。

    public class Ex1 {
    
    
    	public static void main(String[] args) {
    		// TODO Auto-generated method stub
    		
    		try {
    			/*
    			 *  1.抛出到main的外面
    			 *  2.捕获
    			*/
    //			int a = 10/0;
    			String string = null;
    			System.out.println(string.length());
    			System.out.println("不报错");
    		} catch (Exception e) {
    			// TODO: handle exception
    			//异常的打印到栈
    			e.printStackTrace();
    			System.out.println("报错了");
    		}
    		
    		System.out.println("程序结束!!");
    	}
    
    }
    
    //输出:
    //java.lang.NullPointerException
    //报错了
    //程序结束!!
    //	at Ex1.main(Ex1.java:15)
    
    

    我们还可以捕获一个日期类型的异常:

    这里我们顺便复习了如何用Date类去统计某一段程序的运行时间。

    import java.text.ParseException;
    import java.text.SimpleDateFormat;
    import java.util.Date;
    
    public class Ex2 {
    
    	
    	public static void main(String[] args)  {
    		
    		//统计运行时间
    		Date d1=new Date();
    		System.out.println(d1);
    		long t1 = d1.getTime();
    		for(int i = 0;i < 100000000 ;i++) {
    			int a = i;
    			for(int j = 0;j < 100000000 ;j++) {
    				int b = 1;
    			}
    		}
    		Date d2 = new Date();
    		long t2 = d2.getTime();
    		System.out.println(t2-t1);
            
            //异常
    		SimpleDateFormat s = new SimpleDateFormat("yyyy-MM-dd");
    		try {
    			Date d3 = s.parse("2020-12-aaaaaaa");
    			System.out.println(s.format(d3));
    			System.out.println("okokoko");
    		} catch (ParseException e) {
    			// TODO Auto-generated catch block
    			e.printStackTrace();
    		}
    	}
    }
    
    
    /*
    Sun Apr 12 22:19:29 CST 2020
    78
    java.text.ParseException: Unparseable date: "2020-12-aaaaaaa"
    at java.base/java.text.DateFormat.parse(Unknown Source)
    at Ex2.main(Ex2.java:26)
     * */
     */
    

    上面这段程序的异常类型是ParseException类型,我们可以从parse函数的源码中知道为什么。

        public Date parse(String source) throws ParseException
        {
            ParsePosition pos = new ParsePosition(0);
            Date result = parse(source, pos);
            if (pos.index == 0)
                throw new ParseException("Unparseable date: "" + source + """ ,
                    pos.errorIndex);
            return result;
        }
    

    下面我们捕获一个ClassCastException异常;

    public class Man {
    	public static void main(String[] args) {
    		// TODO Auto-generated method stub
    		try {
                //向上转换
    			Man m1 = new Teacher();
    			Student s1 = (Student)m1;
    		} catch (Exception e) {
    			// TODO: handle exception
    			e.printStackTrace();
    		}
    		System.out.println("运行结束");
    	}
    }
    
    /*
    java.lang.ClassCastException: Teacher cannot be cast to Student
    运行结束
    	at Man.main(Man.java:12)
    */
    
    public class Student extends  Man{
    
    }
    
    public class Teacher extends Man{
    
    }
    

    下面是一个ArrayIndexOutOfBoundsException异常,同样的还有字符串对应的IndexOutOfBoundsException(不演示了);

    public class Ex3 {
    
    	public static void main(String[] args) {
    		// TODO Auto-generated method stub
    
    		try {
    			int[] num = new int[3];
    			num[4] = 2; 
    		} catch (Exception e) {
    			// TODO: handle exception
    			e.printStackTrace();
    		}
    	}
    
    }
    
    //
    //java.lang.ArrayIndexOutOfBoundsException: 4
    //at Ex3.main(Ex3.java:9)
    

    下面捕获一个输入异常InputMismatchException,如果我们输入了一个字符串,基本的情况如下;

    import java.util.Scanner;
    
    public class Ex4 {
    	
    	public int getInputNum() {
    		Scanner s = new Scanner(System.in);
    		return s.nextInt();
    	}
    
    	public static void main(String[] args) {
    		// TODO Auto-generated method stub
    		
    		Ex4 ex4 = new Ex4();
    		
    		System.out.println(ex4.getInputNum());
    
    	}
    
    }
    /**
    Exception in thread "main" java.util.InputMismatchException
    	at java.base/java.util.Scanner.throwFor(Unknown Source)
    	at java.base/java.util.Scanner.next(Unknown Source)
    	at java.base/java.util.Scanner.nextInt(Unknown Source)
    	at java.base/java.util.Scanner.nextInt(Unknown Source)
    	at Ex4.getInputNum(Ex4.java:7)
    	at Ex4.main(Ex4.java:14)
    */
    

    我们想要让这段代码具有更高的容错率,如果我们输入了字符串或其他,应该让我们重复输入,直到我们输入了正确的int类型:

    import java.util.Scanner;
    
    public class Ex4 {
    	
    	public int getInputNum() {
    		while (true) {
    			try {
    				System.out.println("请输入数字:");
    				Scanner s = new Scanner(System.in);
    				return s.nextInt();
    			} catch (Exception e) {
    				// TODO: handle exception
    				System.out.println("您的输入不是数字");
    			}
    		}
    	}
    
    	public static void main(String[] args) {
    		// TODO Auto-generated method stub
    		Ex4 ex4 = new Ex4();
    		System.out.println(ex4.getInputNum());
    	}
    
    }
    
    /**
    请输入数字:
    sen
    您的输入不是数字
    请输入数字:
    12
    12
    
    */
    

    3. 异常的抛出

    异常可以大致分为两类:编译时异常(显式异常)和运行时异常(隐式异常)

    首先我们来看一个显式异常的例子:

    这里的parseException是一个显式异常,必须在编译期处理,类似的还有SQLException和IOException

    我们对于这种异常,必须在编写程序的时候添加抛出(throws ParseException),不然编译器就会爆红;

    import java.text.ParseException;
    import java.text.SimpleDateFormat;
    import java.util.Date;
    
    public class Ex5 {
    
    	public Date getDate(String sDate) throws ParseException {
    		SimpleDateFormat simpleDateFormat = new SimpleDateFormat("yyyy-MM-dd");
    		return simpleDateFormat.parse(sDate);
    	}
    	
    	//parseException 显式异常,必须在编译期处理
    	//类似的还有SQLException和IOException
    	public static void main(String[] args) {
    		
    		Ex5 ex5 = new Ex5();
    		try {
    			System.out.println(ex5.getDate("2020-1-3"));
    		} catch (ParseException e) {
    			// TODO Auto-generated catch block
    			e.printStackTrace();
    		}
    		
    	}
    }
    
    

    下面再来看一个隐式异常:

    这里如果分母是0的话会出现异常,这种异常在编译期间是不处理的,编译期间不报错,如果不处理,一旦发生异常,就会造成程序的终止。

    public class Ex6 {
    
    	public int math(int a,int b) {
    		return a/b;
    	}
        
    	/**
    	 * 隐式异常(运行时异常)的处理
    	 * 这种异常在编译期间是不处理的,编译期间不报错;
    	 * 如果不处理,一旦发生异常,就会造成程序的终止
    	 */
    	public static void main(String[] args) {
    		// TODO Auto-generated method stub
    		Ex6 ex6 = new Ex6();
    		ex6.math(10, 0);
    		System.out.println("all is ok");
    	}
    }
    
    /**
    Exception in thread "main" java.lang.ArithmeticException: / by zero
    	at Ex6.math(Ex6.java:6)
    	at Ex6.main(Ex6.java:17)
    	*/
    

    在处理异常的时候我们有两个关键字 throws和throw

    throws的用法就是在函数的方法名后面可以抛出异常,throw可以用来转换异常。

    我们可以看出throw是动词,所以是一个转换的动作。

    注意,异常的抛出和截获要保持一致。

    这里利用throw把ParseException转换成IOException。(并没有什么用,仅仅为了演示用法)

    import java.io.IOException;
    import java.text.ParseException;
    import java.text.SimpleDateFormat;
    import java.util.Date;
    
    import javax.imageio.IIOException;
    
    public class Ex5 {
    	
    	public Date getDate(String sDate) throws IOException  {
    		SimpleDateFormat simpleDateFormat = new SimpleDateFormat("yyyy-MM-dd");
    		
    		try {
    			return simpleDateFormat.parse(sDate);
    		} catch (ParseException e) {
    			//利用throw把ParseException转换成IOException
                //同时,throws对应的异常也要改。
    			throw new IOException();
    		}
    	}
    	
    	//parseException 显式异常,必须在编译期处理
    	//类似的还有SQLException和IOException
    	public static void main(String[] args) {
    		
    		Ex5 ex5 = new Ex5();
    		try {
    			System.out.println(ex5.getDate("AAA-1-3"));
                //异常的抛出和截获要保持一致。
    		} catch (IOException e) {
    			// TODO Auto-generated catch block
    			e.printStackTrace();
    		}
    		
    	}
    }
    /**
    java.io.IOException
    at Ex5.getDate(Ex5.java:18)
    at Ex5.main(Ex5.java:28)
    */
    
    

    4. 自定义异常

    我门可以通过继承Exception来自定义异常,自定义异常实际上是实际上用的最多的地方。

    我门假设以下情况:

    1586761528379

    这里我们主要模拟这里的用户异常和系统异常。

    首先先创建系统异常和用户异常两个异常类,继承与Exception。

    package demo2;
    
    //自定义异常--用户级异常
    public class appException extends Exception{
    
    	//	异常码和异常信息
    	private int ErrorCode;
    	private String ErrMessags;
    	
    	/**
    	 * 有参数的构造器
    	 * @param errorCode
    	 * @param errMessags
    	 */
    	public appException(int errorCode, String errMessags) {
    		super();
    		ErrorCode = errorCode;
    		ErrMessags = errMessags;
    	}
    	
    	public int getErrorCode() {
    		return ErrorCode;
    	}
    	public void setErrorCode(int errorCode) {
    		ErrorCode = errorCode;
    	}
    	public String getErrMessags() {
    		return ErrMessags;
    	}
    	public void setErrMessags(String errMessags) {
    		ErrMessags = errMessags;
    	}
    }
    
    
    package demo2;
    
    
    //自定义异常--系统级异常
    public class systemException extends Exception{
    	//	异常码和异常信息
    	private int ErrorCode;
    	private String ErrMessags;
    	
    	/**
    	 * 有参数的构造器
    	 * @param errorCode
    	 * @param errMessags
    	 */
    	public systemException(int errorCode, String errMessags) {
    		super();
    		ErrorCode = errorCode;
    		ErrMessags = errMessags;
    	}
    
    	public int getErrorCode() {
    		return ErrorCode;
    	}
    	public void setErrorCode(int errorCode) {
    		ErrorCode = errorCode;
    	}
    	public String getErrMessags() {
    		return ErrMessags;
    	}
    	public void setErrMessags(String errMessags) {
    		ErrMessags = errMessags;
    	}
    }
    
    

    随后我们模拟上图中的两种异常:

    建立主函数来调用我们创建好的两个异常:

    package demo2;
    
    public class Ex8 {
    
    	public int math(int a,int b) throws appException, systemException {
    		try {
    //			数组越界异常,利用系统异常抛出
    			int[] nums = new int[3];
    			nums[3] = 8;
    //			数学运算异常,利用用户异常抛出
    			return a/b;
    		} catch (ArithmeticException e) {
    			//转换成自定义异常为用户级异常;
    			throw new appException(1001, "b不能为0!");
    		}catch (IndexOutOfBoundsException e) {
    			// TODO: handle exception
    			throw new systemException(999, "系统异常!");
    		}
    		
    	}
    	public static void main(String[] args) {
    		Ex8 ex8 = new Ex8();
    		
    		try {
    			ex8.math(20, 0);
    		} catch (appException e) {
    			System.out.println(e.getErrMessags());
    		}catch (systemException e) {
    			System.out.println(e.getErrMessags());
    		}
    		System.out.println("finished!");
    	}
    }
    
    //系统异常!
    //finished!
    
    
    
  • 相关阅读:
    SharePoint 2010 User Profile Sync Service自动停止
    如何区别多个svchost.exe?
    Log Parser分析IIS log的一个简单例子
    Timeout expired. The timeout period elapsed prior to obtaining a connection from the pool. This may have occurred because all pooled connections were in use and max pool size was reached.
    Windows中右键点击文件夹, 结果找不到共享选项卡, 怎么办?
    介绍SOS中的SaveModule命令
    SharePoint中Draft版本的文档不会收到document added的Alert Email
    和我一起学Windows Workflow Foundation(1)创建和调试一个WF实例
    门户网站
    C#基础—— check、lock、using语句归纳
  • 原文地址:https://www.cnblogs.com/JeasonIsCoding/p/13232538.html
Copyright © 2011-2022 走看看