异常(基础)

异常

异常的概念

在使用计算机语言开发项目时,即使程序员将代码写的十分严谨,在系统运行的时候也可能会出现错误,以为很多问题不是靠代码可以解决的.例如:客户输入的格式,文件是否存在,网络问题等等.

**异常概念:**在Java语言中,将程序执行中发生的不正常情况称为“异常”.

广义上异常:程序出现的所有不正常的

狭义上异常:是指程序在运行过程中出现的不正常现象,可以通过异常处理机制解决的

广义的异常可以分为两类:

Error:(又称错误) java虚拟机无法解决的问题.一般不编写代码处理.

Exception:(程序异常,狭义的异常)因编程错误或者是偶然的外在因素导致的一般性问题,可以编写针对性代码进行解决处理的

public class ExceptionDemo1 {
    //错误代码演示
    public static void main(String[] args) {
        ExceptionDemo1 demo1 = new ExceptionDemo1();
        demo1.sum(666);
    }
    public int sum (int a ){
        return sum(a-1);
    }
    //结果显示:Exception in thread "main" java.lang.StackOverflowError  表示栈溢出错误
}
//数组越界异常
public static void main(String[] args) {
        int[] a=new int[5];
        a[5]=16;

        //结果显示为:Exception in thread "main" java.lang.ArrayIndexOutOfBoundsException: 5    at com.ffyc.exceptions.ExceptionDemo1.main(ExceptionDemo1.java:17)
        //         异常        在"main"线程中,java.lang包下的ArrayIndexOutOfBoundsException类异常    位置在com.ffyc.exceptions.ExceptionDemo1中的main函数中的17行
        //表示数组越界,在编译期间是没有错误的,在运行时发生了异常
        //在运行时程序遇到未处理的异常时虚拟机就会停止运行.
    }
//算数异常
public static void main(String[] args) {
        int a=10;
        int b=0;
        System.out.println(a/b);
    }
//结果:Exception in thread "main" java.lang.ArithmeticException: / by zero
//	at com.ffyc.exceptions.ExceptionDemo1.main(ExceptionDemo1.java:28)
//类型转换异常 
public static void main(String[] args) {
        Object obj = "ajgh";
        Integer in = (Integer)obj;
    }
//结果:Exception in thread "main" java.lang.ClassCastException: java.lang.String cannot be cast to java.lang.Integer
//	at com.ffyc.exceptions.ExceptionDemo1.main(ExceptionDemo1.java:32)
//空指针异常
public static void main(String[] args) {
        String str = null;
        System.out.println(str.length());
    }
//结果:Exception in thread "main" java.lang.NullPointerException
//	at com.ffyc.exceptions.ExceptionDemo1.main(ExceptionDemo1.java:36)

对于这些异常,一般有两种解决方法:一是遇到异常就终止程序的运行。另一种方法是由程序员在编写程序时,就考虑到异常的检测、异常消息的提示,以及异常的处理。

异常的体系

异常分为运行期异常和编译期异常两种.

运行期异常,就是在运行期间抛出的异常,RuntimeException的所有子类都是运行期间异常.如以上提到的数组越界,算数异常,空指针异常等等.

编译期间异常,也叫检查异常,在编译时就必须要对其进行处理的.

public static void main(String[] args) {
        String str = "ajgag";
        byte[] s = str.getBytes("utf-8");
    }
//以上代码是没有问题的,但是getBytes是编译不通过的,需要使用try-catch 或者 向上抛出异常
public static void main(String[] args) {
        String str = "ajgag";
        try {
            byte[] s = str.getBytes("utf-8");
        } catch (UnsupportedEncodingException e) {
            e.printStackTrace();
        }
    }
//只要是在写代码的时候就需要处理的问题都称之为编译期异常

异常处理

异常处理通过5个关键字来实现,try,catch,finally,throws,throw

基本语法
try{
     可能会发生异常的代码
   }catch(异常类型 引用名){
     异常处理代码
   }finally{
     必须执行代码
   }

try:用于检测不安全的代码,即就是try可以发现异常.当try代码块中的任何一条语句发生了异常,其代码块后 面的代码都不执行,程序将直接跳转到异常处理代码块中,也就是catch代码块.

catch:把抓到的类型匹配的异常捕获,保证程序能继续运行下去catch语句必须跟在try语句后面,称为捕获异常,即异常处理函数,一个try后面可以跟多个catch,分别捕获不同类型的异常,跟多个catch时需要注意的是异常类型需要从子类往父类的顺序写,否则将会出现错误.

public static void main(String[] args) {
        int a=10;
        int b=0;
        try {
            int c=a/b;     //发现异常
        }catch (ArithmeticException e){
            /*
               ArithmeticException 异常的类型,如果此处的异常类型与
               try中发生的异常不同时将不会进入到此catch中,也就不会被
               此catch处理,如果没有匹配的异常类型,那么所发生的异常将不会被处理程序将会终止
            */
            System.out.println("算数异常");//处理异常,以保证后面的代码可以继续执行
        }
       System.out.println("执行后面的代码");
    }
//一个try可以跟多个catch,但是catch必须有子类到父类
public static void main(String[] args) {
        int a=10;
        int b=2;
        try {
            int c=a/b;
            String str = null;
            System.out.println(str.length());
        }catch (ArithmeticException e){
            System.out.println("算数异常");
        }catch (NullPointerException n) {
            System.out.println("空指针异常");
        }catch (Exception ex){
            System.out.println("系统忙,稍后再试");
        }
        System.out.println("后面的代码");
    }

finally: 此代码块中的代码块总是会执行,并且只能有一个finally语句.

//try-catch组合 
public static void main(String[] args) {
        int a=10;
        int b=2;
        try {
            int c=a/b;
            String str = null;
            System.out.println(str.length());
        }catch (ArithmeticException e){
            System.out.println("算数异常");
        }catch (NullPointerException n) {
            System.out.println("空指针异常");
        }catch (Exception ex){
            System.out.println("系统忙,稍后再试");
        }finally {
            System.out.println("finally");
        }
        System.out.println("后面的代码");
    }
/*
空指针异常  //捕获的异常
finally   //执行finally语句
后面的代码   
*/
/*此处异常已经被finally之前的catch捕获处理,程序可以向后继续执行*/
//try-finally组合
public static void main(String[] args) {
        try {
            String str = null;
            System.out.println(str.length());
        }finally {
            System.out.println("finally");
        }
        System.out.println("后面的代码");
    }
/*结果:
Exception in thread "main" java.lang.NullPointerException
	at com.ffyc.exceptions.ExceptionDemo1.main(ExceptionDemo1.java:31)
finally
*/
/*由于异常并未catch捕获处理,所以程序将会抛出异常并停止,但是finally是总能执行的代码块,所以会输出finally*/
public class ExceptionDemo1 {
    public static void main(String[] args) {
        System.out.println(ExceptionDemo1.test());
    }
    public static int test(){
        int a=10;
        int b=0;
        try {
            return a/b;
        }catch (ArithmeticException ari){
            System.out.println("算数异常");
            return 0;
        }finally {
            System.out.println("最终执行代码");
        }
    }
    /*结果:
    算数异常   //此处之后应执行return 0;  但finally是总能执行的,先执行finally在return
    最终执行代码
    0
    */

throws:定义一个方法的时候可以使用throws关键字声明,表示此方法不处理异常,而交给方法调用者,让调用者进行处理.

任何方法都可以使用throws关键字,一个throws可以跑出多种异常.

public void test throws 异常1,异常2,异常3{

}
注意:1.使用throws抛出异常时,此异常一般直接或间接继承Exception,即就是编译期异常.
    2.子类重写父类的方法时,子类方法不能声明抛出比父类类型更大的异常(针对编译期异常).
    3.使用了throws的方法,在被调用的时候必须处理声明的异常,要么使用try-catch,要么继续使用throws.
import java.io.UnsupportedEncodingException;

public class Demo4{
    public static void main(String[] args){
        try {
            Demo4.test2();//调用test2,仍然需要处理异常,main是最顶层的放法,一般不能够继续向上抛出异常,使用try-catch处理.
        } catch (UnsupportedEncodingException e) {
            e.printStackTrace();
        }
    }
    /*
    throws  +  编译期异常  在调用该方法时,会显性的提示,在编译时就要进行处理异常
    throws  +  运行期异常  在编译期间不会显性的提示需要处理异常(需要看个人经验)
    */
    public static void test1() throws UnsupportedEncodingException {
        String s = null;
        s.getBytes("utf-8");//此处需要使用throws抛出异常
    }
    public static void test2() throws UnsupportedEncodingException {
        Demo4.test1();//调用论了test1,需要对test1中的异常进行处理,此处继续选择throws抛出异常
    }

}
//注:如果在底层就使用try-catch处理,上层在调用的时候是不知道底层出现了异常的,此时上层就不用再处理
//一般的在底层的方法通常会用throws进行抛出,因为在底层就处理上层是不知道的,上层仍在调用,导致返回的结果不正确

throw:用于显式的抛出异常,抛出的时候是抛出一个异常类的实例化对象.在方法中显式的抛出一个异常类的对象,表示此处实际发生了异常.

new + 有参构造方法(“异常原因”)

import java.io.UnsupportedEncodingException;

public class Demo3 {
    public static void main(String[] args) {
        try {
            test(110);
        } catch (UnsupportedEncodingException e) {
            e.printStackTrace();//在控制台打印异常信息  开发测试时使用,以便于更准确找到错误
            System.out.println(e.getMessage());//getMessage();属于Throwable中的方法,用于打印throw抛出的异常原因
        }
    }
    public static String test(int socer) throws UnsupportedEncodingException {
        if(socer<0||socer>100)
            throw new UnsupportedEncodingException("成绩错误");//表示出现异常,程序是不会继续向下执行的.
        if (socer>=90){
            return "a";
        }
        else {
            return "b";
        }
    }
}
//注:throws是声明异常
//   throw是抛出异常

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

自定义异常

为什么需要自定义异常类?

java中提供的是针对语法上的异常类,在多数项目实际情况下异常不单单是语法上的.例如成绩输入的异常,

因此我们可以自己定义一个异常类,在实际开发过程中,可以根据自己需求,自己开发一个异常类,用于表示某一类问题.

自定义一个异常类其实只需要写一个类继承某个异常类,在编写有参构造和无参构造,在分别调用父类构造方法就行了

//自定义一个分数异常类
public class ScoreException extends Exception {
    public ScoreException() {
        super();
    }

    public ScoreException(String message) {
        super(message);
    }
}
  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值