Java第七章——异常

异常分类

  1. Throwable的子类包含哪两类?简述Java Error类与Exception类的区别。
    在这里插入图片描述

Error:致命异常。标识系统发生了不可控的错误。程序无法处理,智能人工介入。例如,虚拟机产生的错误StackOverflowError、OutOfMemoryError。

Exception:非致命异常。程序可处理,分为收编译器检测的checked异常(受检异常)和不受编译器检测的unchecked异常(非受检异常)。

  1. Exception又分为checked异常和unchecked异常,请分别举例说明。

将派生于Error或者RuntimeException的异常称为unchecked异常,所有其他的异常称为checked异常。

checked异常在编译时检查,这意味着如果一个方法抛出checked异常,那么它应该使用try-catch块或者使用throws关键字来处理这个异常,否则的话程序会报编译错误,命名为checked异常是因为是在编译时checked的。

import java.io.*;
class Example{  
   public static void main(String args[]){
   	FileInputStream fis=null;
	/*This constructor FileInputStream(File filename)
	 throws FileNotFoundException which is a checked
	 exception*/
    fis = new FileInputStream("myfile.txt");
    int k; 
	/*Method read() of FileInputStream class also throws 
	 a checked exception: IOException*/
	while((k=fis.read())!=-1){ 
		System.out.print((char)k); 
	}
	/*The method close() closes the file input stream
	 It throws IOException*/
	 fis.close(); 	
   }
}

输出结果:

Exception in thread "main" java.lang.Error: Unresolved compilation problems: 
Unhandled exception type FileNotFoundException
Unhandled exception type IOException
Unhandled exception type IOException

如何解决?
方法一:使用throws关键字声明异常

import java.io.*;
class Example {  
   public static void main(String args[]) throws IOException{
      FileInputStream fis=null;
      fis=new FileInputStream("myfile.txt"); 
      int k;
      while((k=fis.read())!=-1){ 
	   System.out.print((char)k); 
      } 
      fis.close(); 	
   }
}

方法二:使用try-catch块处理异常

import java.io.*;
class Example{  
   public static void main(String args[]){
	FileInputStream fis=null;
	try{
	    fis=new FileInputStream("B:/myfile.txt"); 
	}catch(FileNotFoundException fnfe){
            System.out.println("The specified file is not "+"present at the given path");
	 }
	int k; 
	try{
	    while((k=fis.read())!=-1){ 
		System.out.print((char)k); 
	 	} 
	fis.close(); 
	}catch(IOException ioe){
	    System.out.println("I/O error occurred: "+ioe);
	 }
   }
}
  1. 简述StackOverflowError和OutOfMemoryError两类错误的发生情形和原因。

StackOverflow——栈溢出
原因:线程调用生成的栈桢深度超过了虚拟机允许的深度
情形:
①递归可能造成StackOverflowError
②不断创建线程可能造成StackOverflowError
OutOfMemoryError——内存溢出
原因:内存不够,发生了内存溢出
情形:
①栈的深度(大小类似于弹夹深度)可以自动扩展,扩展时无法申请到足够的内存
②如果在堆中没有内存完成实例分配,并且堆也无法再扩展时
③当方法区无法满足内存分配需求时
④当常量池(方法区的一部分)无法再申请到内存
⑤各个内存区域的总和大于物理内存限制(包括物理上的和操作系统级的限制),从而导致动态扩展

除了程序计数器外,虚拟机内存其他运行时区域都会发生OutOfMemoryError。
JVM管理的内存大致包括三种不同类型的内存区域:Permanent Generation space(永久保存区域)、Heap space(堆区域)、Java Stacks(Java栈)。
永久保存区域主要存放Class(类)和Meta的信息,Class第一次被Load的时候被放入PermGen space区域,Class需要存储的内容主要包括方法和静态属性。
堆区域用来存放Class的实例(即对象),对象需要存储的内容主要是非静态属性。每次用new创建一个对象实例后,对象实例存储在堆区域中,这部分空间也被JVM的垃圾回收机制管理。
Java栈存储基本类型变量以及方法的输入输出参数。Java程序的每个线程中都有一个独立的堆栈。

容易发生内存溢出问题的内存空间包括:Permanent Generation space和Heap space。
参考原文

异常处理

  1. 简述异常处理的两种方式,并举例说明区别。
    方法一:声明抛出处理(向调用方传播异常)
    ①显式声明抛出——throws语句
    ②隐式声明抛出——throws语句可省略

方法二:程序捕获处理(在当前方法捕获处理异常)
嵌套/非嵌套——try/catch/finally语句

  1. 选取RuntimeException类的五个子类,编写抛出并捕获上述子类异常的程序。(例如算术异常,空指针异常,类转换异常,数组越界异常等)

①EmptyStackException类——空栈异常

public class P {
    private String name;
    public void setName(String name){
            this.name=name;
    }
    public void print(){
        printString(name);
    }
    private void printString(String s){
        System.out.println(s +"("+s.length()+")");
    }
    public static void main(String[] args){
        P p=new P();
        try{
            p.print();
        }catch(NullPointerException e){
            System.out.println("Empty Stack");}
        }
}

②ArithmeticException类——算术异常

public class TestArithmeticException{
    public static void main(String[] args){
        int a,b,c;
        a=1;b=0;
        c=a/b;
        System.out.println(c);
    }
}
public class TestArithmeticException{
    public static void main(String[] args){
        try{
            int a,b,c;
            a=1;b=0;
            c=a/b;
            System.out.println(c);
        }catch(ArithmeticException e){
            System.out.println("除数为0");
        }
    }
}

③NullPointerException类——空指针异常

public class Test{
    private static int[] x;
    public static void main(String[] args){
        System.out.println(x[0]);
    }
}
public class Test{
    private static int[] x;
    public static void main(String[] args){
        try{
            System.out.println(x[0]);
        }catch(NullPointerException e){
            System.out.println("空指针异常");
        }
    }
}

④ArrayIndexOutOfBoundsException类——数组越界

public class Test{
    public static void main(String[] args){
        String f=args[1];
        System.out.println("f="+f);
    }
}
public class Test{
    public static void main(String[] args){
        try{
            String f=args[1];
            System.out.println("f="+f);
        }catch(ArrayIndexOutOfBoundsException e){
            System.out.println("数组下标越界");
        }
    }
}

⑤NegativeArraySizeException类——负数组长度

public class Test{
    public static void main(String[] args){
        int[] a;
        a=new int[-1];
    }
}
public class Test{
    public static void main(String[] args){
        try{
            int[] a;
            a=new int[-1];
        }catch(NegativeArraySizeException e){
            System.out.println("负数组长度异常");
        }
    }
}
  1. 根据某业务场景自定义一个异常类,并在某场景下抛出该异常对象。

注册操作

//注册异常
public class Test01_RegisterException  extends Exception{
    //空参构造
    public Test01_RegisterException(){
    }
    //异常提示
    public Test01_RegisterException(String message){
        super(message);
    }
}
===========================================================
import java.util.Scanner;
public class Test{
    public static void main(String[] args) {
        String[] str={"张三","王五","李四"};
        find_Exception(str);
    }
    private static void find_Exception(String[] str) {
        Scanner sc=new Scanner(System.in);
        for (String s:str) {
            try{
                checkUsername(s,str);
                //没有异常,注册成功
                System.out.println("注册成功");
            }catch (Test_RegisterException e){
                //处理异常
                e.printStackTrace();
            }
        }
    }
    //判断当前账户是否被注册
    //编译器异常,声明后抛出
    private static boolean checkUsername(String s,String[] str) throws Test01_RegisterException {
        for (String s1 : str) {
            if(s1.equals(s)){
                throw new Test01_RegisterException("对不起,这个号已经被注册了");
            }
        }
        return true;
    }
} 
===========================================================
//测试结果一
请输入一个账号:
张三
demo1_Exception.Test01_RegisterException: 对不起,该账号已被注册
	at demo1_Exception.Test01.checkUsername(Test01.java:32)
	at demo1_Exception.Test01.find_Exception(Test01.java:16)
	at demo1_Exception.Test01.main(Test01.java:8)
 
Process finished with exit code 0
===========================================================
//测试结果二
请输入一个账号:
赵六
注册成功
 

自定义异常与异常对象的创建

  1. 异常中的throws声明与throw语句的区别是什么?请举例说明。
    throw:用在方法体内,是具体向外抛异常的,抛出的是一个异常实例,
    如果执行了该方法,那一定是抛出了某种异常。
public class test1 {
    public static void main(String[] args){
        String s="abc";
        if(s.equals("abc")){
            throw new NumberFormatException();
        }else{
            System.out.println(s);
        }
    }
}

运行结果:

Exception in thread "main" java.lang.NumberFormatException
at test1.main(test1.java:5)

throws:用在方法声明后面,表示在抛出异常,由该方法的调用者来处理,
声明了是哪种异常,使它的调用者可以捕获这个异常,
如果执行了该方法,可能会出现该异常,但不一定。

public class test2 {
    public static void function() throws NumberFormatException{
        String s="abc";
        System.out.println(Double.parseDouble(s));
    }
    public static void main(String[] args){
        try{
            function();
        }catch(NumberFormatException e){
            System.err.println("非数据类型不能转换");
        }
    }
}

运行结果:

非数据类型不能转换
  1. finally子句的作用是什么?
    finally是这个组合语句的统一出口,一般用来进行一些善后清理操作,例如清理资源、释放连接、关闭文件、管道流等操作。它是可选的一部分,但一旦选定,必定执行。
public class Testfinally{
    public static void main(String[] args){
        System.out.println(testFinally());
    }
    private static int testFinally() {
        int temp=100;
        try {
            System.out.println("Try");
            return ++temp;//return的结果被暂存
        } finally {
            temp=1;
            System.out.println("Finally");
        }
    }
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值