Java学习(六)异常


一、异常概述

1、异常的概念

public class Test{
    double f(int x){
	int y = 3;
            int z = y/x;
	return z;	
    }    
    public static void main(String args[]){
	Test t = new Test();
	System.out.println(t.f(0));
    }
}

异常是运行时发生的错误,不是编译错误或语法错误。
异常在java中代表一个错误的实体对象。
有些可能发生的异常在我们的程序当中必须处理,有些则不需要处理。
异常有5个关键字:
try、catch、finally、throw、throws

2、异常的体系结构

在这里插入图片描述

Throwable:所有异常类的父类。
Error:称为错误,由Java虚拟机生成并抛出,包括动态链接失败、虚拟机错误、系统崩溃等,程序对其不作处理。
Exception:因程序编码错误或外在因素导致的问题,这些问题能够被系统捕获并进行处理,从而避免应用程序非正常中断。又可分为以下两种:
非检查型异常:编译器不要求强制处置的异常,由于编码或设计不当导致的,可以避免,RuntimeException及其所有子类都属于非检查型异常。
检查型异常:编译器要求必须处理的异常,是程序运行时因外界因素而导致的,RuntimeException及子类之外的异常均为检查型异常。

在这里插入图片描述

3、异常处理机制

捕获异常:try…catch…finally…
将可能产生异常的代码放在try语句中进行隔离,如果遇到异常,程序会停止执行try块的代码,调到catch块中进行处理。
抛出异常:throw、throws
当前方法不知道如何处理所出现的异常,该异常应由上一级调用者进行处理,可在定义该方法时使用throws声明抛出异常。

二、捕获异常

1、单catch处理语句

public class SingleCatchDemo{
	public static void main(String[] args){
	try{
		int i = 10/0;
		System.out.println(“i的值为:”+i);
	}catch(Exception e){
		//输出异常信息
		e.printStackTrace();
	}
	System.out.println(“end”);
	}
}

运行结果:
在这里插入图片描述
单catch处理语句执行流程:
在这里插入图片描述

当执行try块中的语句产生异常时,try块中剩下的代码不会再执行,而是执行catch语句;catch语句处理结束后,程序继续往下执行。因此最后的输出语句会执行,”end”字符串被输出显示,程序正常退出。

异常对象的几个常用方法:
getMessage()——返回该异常的详细描述字符串。
printStackTrace()——将该异常的跟踪栈信息输出到标准错误输出。
getStackTrace()——返回该异常的跟踪栈信息。
注意:在使用getMessage()和getStackTrace()都需要print输出才能显示,而printStackTrace()会直接输出异常。

2、多catch处理语句

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

执行多catch处理语句时,当异常对象被其中的一个catch语句捕获,则剩下的catch语句将不再进行匹配。所以安排catch语句的顺序时,首先应该捕获一些子类异常,然后再捕获父类异常。如Exception异常一般放在最后。

MultiCatchDemo.java:

import java.util.Scanner;
public class MultiCatchDemo{
    public static void main(String[] args){
	Scanner scanner = new Scanner(System.in);
	int array[] = new int[3];
	try{
	    System.out.println("请输入第1个数:");
	    //从键盘获取一个字符串
	    String str = scanner.next();
	    //将不是整数的字符串转换成整数,会引发NumberFormatException
	    int n1 = Integer.parseInt(str);
	    System.out.println("请输入第2个数:");
	    //从键盘获取一个整数
	    int n2 = scanner.nextInt();
	    //两个数相除,除数为0,会引发ArithmeticException
	    array[0] = n1 / n2;
	    //给array[3]赋值,下标越界,会引发ArrayIndexOutOfBoundsException
	    array[3] = n1 * n2;
	    System.out.println("两个数的和是"  + (n1 + n2));
	}catch(NumberFormatException ex){
	    System.out.println("数字格式化异常!");
	}catch(ArithmeticException ex){
	    System.out.println("算术异常!");
	}catch(ArrayIndexOutOfBoundsException ex){
	    System.out.println("下标越界异常!");
	}catch(Exception ex){
	    System.out.println("其它未知异常!");
	}
	System.out.println("程序结束!");
    }
}

3、try…catch…finally语句

在这里插入图片描述

try块是必须的,catch块和finally块是可选的,但二者至少出现其一,也可以同时出现。
try…catch…finally语句顺序不能颠倒。
除非在try或catch块中调用System.exit()方法退出应用程序,否则finally块中的代码总会被执行。

FinallyDemo:

import java.io.*;
public class FinallyDemo{
    public static void main(String[] args){
	FileInputStream fis = null;
	try{
	    fis = new FileInputStream("1.txt");
	}catch(IOException ioe){
	    System.out.println(ioe.getMessage());
	}
	finally{
	    if(fis != null){
		try{
		    fis.close();
		}catch(IOException ioe){
	    	    System.out.println(ioe.getMessage());
		}
	    }
	    System.out.println("执行finally块中的资源回收!");
	}
    }
}

4、自动关闭资源的try语句

在上一小节中,关闭资源的代码放在finally中,Java 7开始,允许在try关键字后紧跟一堆小括号,小括号内可以声明、初始化一个或多个资源,当try语句执行结束时会自动关闭这些资源。例子:略(课本P236)

5、嵌套的try…catch语句

例子:略(课本P237)

try{.
	try{.
	}catch(异常类 A){.
	}
}catch(异常类 B ){.
}

6、多异常捕获

例子:略(课本P239)

try{
	//业务实现代码(可能发生异常)}catch(异常类 A|异常类 B|异常类 C|){
//多异常捕获处理代码.
}

三、抛出异常

1、throw抛出异常对象

throw是用来手工抛出异常。throw语句抛出的不是异常类,而是一个异常实例对象,并且每次只能抛出一个异常实例对象。

ThrowDemo.java:

import java.util.Scanner;
public class ThrowDemo{
    public static void main(String[] args){
	Scanner scanner = new Scanner(System.in);
	try{
	    System.out.println("请输入年龄:");
	    int age = scanner.nextInt();
	    if(age<0||age>80){
		//抛出一个异常
		throw new Exception("请输入0-80之间的年龄");
	    }
	}catch(Exception ex){
	    ex.printStackTrace();
	}
	System.out.println("程序结束!");
    }
}

throw new Exception(“###”)抛出异常对象

2、throws声明抛出异常序列

如果在方法中会有异常发生,不想在方法中直接处理,而想要由方法的调用者来处理,则可使用 throws 关键词来声明这个方法可能会抛出某种异常。在调用该方法时需要对异常进行捕获处理。

示例:

void f() throws ArithmeticException{
        int z = x/y;
        throw new ArithmeticException(“错误报告”);
}

ThrowsDemo:

import java.util.Scanner;
public class ThrowsDemo{
public static void myThrowsFunction() throws NumberFormatException,ArithmeticException,Exception{
	Scanner scanner = new Scanner(System.in);
	System.out.println("请输入第1个数:");
	//从键盘获取一个字符串
	String str = scanner.next();
	//将不是整数的字符串转换成整数,会引发NumberFormatException
	int n1 = Integer.parseInt(str);
	System.out.println("请输入第2个数:");
	//从键盘获取一个整数
	int n2 = scanner.nextInt();
	//若除数为零,会引发ArithmeticException
	System.out.println("两个数相除的结果是"  + n1 / n2);
	}
public static void main(String[] args){
	try{
	    myThrowsFunction();
	}catch(NumberFormatException ex){
	    ex.printStackTrace();
	}catch(ArithmeticException ex){
	     ex.printStackTrace();
	}catch(Exception ex){
	     ex.printStackTrace();
	}
    }
}

四、自定义异常

根据业务逻辑,程序员在某些时候需要定义自己的异常类来处理一些业务。自定义异常类都继承Exception或RuntimeException类。

AgeException.java:

public class AgeException extends Exception{
	public AgeException(){
	}
	public AgeException(String msg){
		super(msg);
	}
}

MyExceptionDemo.java:

import java.util.*;
public class MyExceptionDemo{
    public static void main(String[] args){
	Scanner scanner = new Scanner(System.in);
	try{
		System.out.println("请输入年龄:");
		int age= scanner.nextInt();
		if(age<0||age>80){
			throw new AgeException("年龄不合法,必须在0-80之间");
		}
	}catch(AgeException ex){
		ex.printStackTrace();
	}
	System.out.println("程序结束!");
    }
}

五、垃圾收集机制

垃圾收集是将分配给对象不再使用的内存回收或释放的过程。
垃圾收集机制的特点:
(1)内存优化;
(2)动态回收:自动识别不再被程序引用的对象并回收,如果一个对象没有指向它的引用或将其赋值为null,则此对象将进行垃圾收集。
(3)回收的不确定性:优先级较低,一般在CPU空闲或者内存不足时自动进行。
(3)占用系统开销:JVM采用了不同的垃圾回收机制和回收算法以减少对系统的影响。


习题——内存解析

class Birthday {
	private int day;
	private int month;
	private int year;
	public Birthday(int d,int m,int y){
	  day=d;month=m;year=y;
	}
	public int getDay(){ return day;}
	public int getMonth(){return month;}
	public int getYear(){return year;}
	public void setDay(int d){day=d;}
	public void setMonth(int m)
	{month=m;}
	public void setYear(int y){year=y;}
	public void display(){
System.out.println
		(day+"-"+month+"-"+year);}
}
public class Test{
  public static void main(String[] args){
	Test test=new Test();
	int date=9;
	Birthday d1=new Birthday(24,1,1986);
	Birthday d2=new Birthday(13,9,1984);
	test.change1(date);
	test.change2(d1);
	test.change3(d2);
	System.out.println("date="+date);
	d1.display();
	d2.display();
  }
  public void change1(int i){i=1234;}
  public void change2(Birthday b){
	b=new Birthday(22,2,2022);}
  public void change3(Birthday b){b.setDay(22);}
}
  • 1
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

君知燕云归

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值