Java面向对象_27 异常


什么是异常?

异常就是指程序执行过程中遇到的非正常情况,导致JVM非正常停止。

Java中有哪些异常?

在这里插入图片描述
Java中的异常有两个体系:

  • Errorerror是严重的错误问题,也就是无法处理的错误,只能事先避免,比如内存溢出;
  • Exception:Exception是我们最常遇到的,java.lang.Exception被称作异常类,它表示程序本身可以处理的问题。

所有的异常都继承Throwable类,Throwable继承Object类。我们考虑到的ErrorException都是直接继承Throwable的。

作为一名Java程序员,在软件开发中,Exception是不可能避免的,所以你至少应当具备分析异常原因、处理异常的能力。

Exception就是标题所介绍的异常,异常还分为编译时异常运行时异常

  • 编译时异常也可称为检查异常,IDE中会提示处理,否则代码无法编译;
  • 运行时异常也可称为非检查异常,这样的异常代码不会报错,但是在程序运行的时候可能会出现,你也可以在代码中就处理,但是这样你就不能通过日志来排查问题了。
  • 运行时异常有个独立的类RuntimeException,所有的运行时异常都需要继承它,而除此之外的异常我们都将其归类为编译时异常或者检查异常。

异常处理 try-catch

可以看下面这个例子:

	int[] arr = {12,32,34};
	try {
	    System.out.println(arr[3]);//尝试访问越界索引,会被catch捕获
	}catch (ArrayIndexOutOfBoundsException e){//异常类型 名称
		e.printStackTrace(); //在命令行打印异常信息在程序中出错的位置及原因。
	    System.out.println("数组下标越界异常"); //自定义catch内代码
	    System.out.println("catch语句继续往下执行");
	}

在这里插入图片描述
当程序抛出一个异常后,在异常代码处跳出,Java虚拟机检测和寻找和try关键字匹配的处理该异常的catch块。如果找到,将控制权交给catch块中的代码,然后继续往下执行程序,try块中发生异常的代码不会被重新执行;如果没有找到处理该异常的catch块,最终运行时会报错。

处理多个异常

	int[] arr = {12,32,34};
	try {
	    System.out.println(arr[3]);
	}catch (ArrayIndexOutOfBoundsException e){
		e.printStackTrace();
	    System.out.println("数组下标越界异常");
	    System.out.println("catch语句继续往下执行");
	}catch (RuntimeException e ){
	    System.out.println("父类异常");
	}catch (Exception e ){
	    System.out.println("总异常");
	}

当代码块中的代码可能有多个异常时,可以使用连起来的catch块。
如果同时存在父类和子类异常,必须把子类异常放在前面,如果子类异常已经能够处理,父类异常就不会再处理。

上面的方式看起来很冗余,如果是没有继承关系的异常,可以这么写:

    public static void main(String[] args) {
        int[] arr = {12, 32, 34};
        try {
            System.out.println(arr[3]);
        } catch (ArrayIndexOutOfBoundsException | NullPointerException | ArithmeticException e) {
            e.printStackTrace();
        }
    }

如果编译时异常的数量实在太多,添加很麻烦,你可以用它们的父类直接代替,比如用Exception,能处理所有异常。

    public static void main(String[] args) {
        int[] arr = {12, 32, 34};
        try {
            System.out.println(arr[3]);
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

异常处理 finally

	int[] arr = {12,32,34};
	try {
	    System.out.println(arr[3]);
	}catch (ArrayIndexOutOfBoundsException e){
		e.printStackTrace();
	    System.out.println("数组下标越界异常");
	    System.out.println("catch语句继续往下执行");
	}finally {
	   System.out.println("释放资源,此语句必须执行");
	}

在这里插入图片描述

  • finally语句为异常处理提供的一个统一的出口,使得在控制流程到程序其它部分之前,能够对程序的状态作统一的管理。
  • 无论try所指的程序是否抛出异常,finally所指定的代码必须执行。
  • 通常finally在语句中可以进行资源的释放工作,如关闭打开的文件,关闭数据库连接等。

throws

程序中会声明很多方法,这些方法中可能会因某些错误而引发异常,但不希望在这个方法中处理这些异常,而希望调用它的方法统一处理,这时候就需要使用throws关键字声明在这个方法上抛出异常。

  • 运行时异常可以不处理,出现问题后,需要我们回来修改代码。
    /**
     * throws抛运行时异常
     */
    static public void throwsDemo1() throws ArrayIndexOutOfBoundsException{
        int[] arr = {12,32,34};
        System.out.println(arr[3]);
    }
  • 编译时异常必须要处理
    /**
     * throws抛编译时异常
     */
    static public void throwsDemo2() throws ParseException {
        String date = "2045-2-23";
        SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd");
        Date date1 = sdf.parse(date);
        System.out.println(date1);
    }

try-catchthrows的区别?

try-catch即时处理,处理后就不需要再处理了。
throws是将来谁调用谁来处理。

如果一直throws,需要throws到入口程序

    public static void main(String[] args)throws ArrayIndexOutOfBoundsException,ParseException {
        throwsDemo1();
        throwsDemo2();
    }

throw

  • 当程序发生错误而无法处理时,会抛出对应的异常对象,除此之外,若想要自行抛出异常,此时需要用到“throw”关键字,并生成指定的异常对象后抛出。
  • throw定义在方法内,用来抛出一个异常对象。
    /**
     * throw关键字
     */
    static public void throwDemo3(int[] arr){
        if (arr == null) {
            throw new NullPointerException("访问的为数组空");
        }
    }

RuntimeException

RuntimeException类属于非检查异常,因为普通JVM操作引起的运行时异常随时可能发生,此类异常一般是由特定操作引发。但这些操作在Java应用程序中会频繁出现。因此它们不受编译期检查与处理或者声明规则的限制。

常见RuntimeException异常

子类异常说明
NullPointerException当应用程序试图在需要对象的地方使用null时,抛出该异常
ArrayIndexOutOfBoundsException当使用的数组下标超出数组允许范围时,抛出该异常
ClassCastException当试图将对象强制转换为不是实例的子类时,抛出该异常
NumberFormatException当应用程序试图将字符串转换成一种数值类型,但该字符串不能转换为适当的格式时,抛出该异常

自定义异常

异常机制可以保证程序更安全和健壮。虽然类库已经提供很多可以直接处理异常的类,但是有时候为了更加精准地捕获和处理异常以呈现更好的用户体验,需要开发者自定义异常。

public class ScoreException extends RuntimeException{
    public ScoreException(){
        super();
    }

    public ScoreException(String message){
        super(message);
    }
}
public class TestScoreException {
    public static void main(String[] args) {
        Scanner sc = new Scanner(System.in);
        int score = sc.nextInt();
        checkScore(score);
    }

    static public void checkScore(int score) {
        if (score < 60 || score > 100) {
            throw new ScoreException("输入的分数不在在指定范围内:60-100");
        } else {
            System.out.println(score);
        }
    }
}

在这里插入图片描述

/**
 * @Description: 父类构造抛出编译时异常
 */
public class Son1 extends Father{
    public Son1() throws ParseException {
        super();//这里super必须在第一行,不能使用try-catch
        //只能通过throws来处理
    }
}

/**
 * @Description: 父类构造抛出运行时异常
 */
public class Son2 extends Father {
    public Son2(){
        super(new Object());//不抛出异常
    }
}

垃圾回收机制GC

垃圾回收机制

  • 垃圾回收机制简称GC,它是JVM自带的一个线程,用于回收没有任何指向的对象
  • Java程序员不用考虑内存管理,因为垃圾收集器会自动进行回收管理;
  • 一般情况下,当我们需要GC线程即刻回收无用对象时,可以调用System.gc()方法;
  • System.gc()用于建议虚拟机马上调度GC线程回收资源,具体的实现由JVM决定。

finelize()

  • finelize()是Object中的方法,当垃圾回收器将要回收对象所占内存之前被调用。

内存泄漏

  • 不再使用的内存没有被及时回收,严重的内存泄漏会因过多的内存占用而导致程序的崩溃;

  • GC线程判断对象是否可以回收的依据是该对象是否有引用指向,因此,当该对象不再使用时,应该及时将其引用设置为null。

  • 内存泄漏和内存溢出有啥区别?

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值