JAVA实训第四天

目录

异常 

什么是异常?

 为什么要进行异常处理?

 方法的调用堆栈

 方法调用堆栈中异常对象的传递

 Java中的异常类

 常见的异常类

 常见的异常类及出现此异常的原因

•1、java.lang.NullpointerException(空指针异常)

•2、 java.lang.ClassNotFoundException(指定的类不存在)

•3、java.lang.ClassNotFoundExceptio(指定的类不存在)

•4、java.lang.IndexOutOfBoundsException(数组下标越界异常)

•5、java.lang.IllegalArgumentException(方法的参数错误)

•6、java.lang.IllegalAccessException(没有访问权限)

•7、java.lang.ArithmeticException(数学运算异常)

•8、java.lang.ClassCastException(数据类型转换异常)

•9、 java.lang.FileNotFoundException(文件未找到异常)

•10、java.lang.ArrayStoreException(数组存储异常)

•11、java.lang.NoSuchMethodException(方法不存在异常)

•12、 java.lang.EOFException(文件已结束异常)

•13、java.lang.InstantiationException(实例化异常)

•14、java.lang.InterruptedException(被中止异常)

•15、java.lang.CloneNotSupportedException (不支持克隆异常)

•16、java.lang.OutOfMemoryException (内存不足错误)

•17、java.lang.NoClassDefFoundException (未找到类定义错误)

 Error类

 常见的错误类

 检查异常与非检查异常

 异常处理的一般步骤

异常抛出

 Throw和Throws的区别

异常捕获

 finally

 Finally和final以及finalize的区别

 创建自己的异常类

异常处理

 作业


异常 

什么是异常?

JAVA实训第四天_第1张图片

 为什么要进行异常处理?

JAVA实训第四天_第2张图片

 方法的调用堆栈

JAVA实训第四天_第3张图片

 Java程序在执行的过程中,形成了一个先进后出的调用堆栈,各方法之间依照调用先后的不同,由先至后的进入调用堆栈,堆栈的最上层即是当前被调用执行的方法。该方法执行完毕后,会将处理器控制权交还给调用他的方法,依此类推。

 方法调用堆栈中异常对象的传递

 JAVA实训第四天_第4张图片

 

 当某一方法中的一个语句抛出一个异常时,如果该方法中没有处理该异常的语句,那么该方法就会中止执行,并将这个异常传递给堆栈中的下一层方法直到某一方法中含有处理该异常的语句为止。如果该异常被传递至主方法,而主方法中仍然没处理该异常的语句,则异常将会被抛至JVM,程序中断

 Java中的异常类

JAVA实训第四天_第5张图片

 Java语言中,任何的异常对象都是Throwable类的直接子类或间接子类的实例Java的类库已经提供了一些常见的异常类,如果这些异常类不能够满足要求,用户也可以创建自己的异常类。

 常见的异常类

JAVA实训第四天_第6张图片

 常见的异常类及出现此异常的原因

1java.lang.NullpointerException(空指针异常)

原因:这个异常经常遇到,异常的原因是程序中有空指针,即程序中调用了未经初始化的对象或者是不存在的对象。经常出现在创建对象,调用数组这些代码中,比如对象未经初始化,或者图片创建时的路径错误等等。对数组代码中出现空指针,是把数组的初始化和数组元素的初始化搞混淆了。数组的初始化是对数组分配空间,而数组元素的初始化,是给数组中的元素赋初始值

2java.lang.ClassNotFoundException(指定的类不存在)

原因:当试图将一个 String 类型数据转换为指定的数字类型,但该字符串不满足数值型数据的要求时,就抛出这个异常。例如将String 类型的数据 "123456" 转换为数值型数据时,是可以转换的的。但是如果 String 类型的数据中包含了非数字型的字符,如123*56 ,此时转换为数值型时就会出现异常。系统就会捕捉到这个异常,并进行处理

3java.lang.ClassNotFoundExceptio(指定的类不存在)

原因:是因为类的名称和路径不正确,通常都是程序试图通过字符串来加载某个类的时候可能会引发异常。例如:
调用 Class.forName () 、或者调用 ClassLoad finaSystemClass () 、或者是 LoadClass () 时出现异常

4java.lang.IndexOutOfBoundsException(数组下标越界异常)

原因:查看程序中调用的数组或者字符串的下标值是不是超出了数组的范围,一般来说,显示调用数组不太容易出这样的错,但隐式调用就有可能出错了,还有一种情况,是程序中定义的数组的长度是通过某些特定方法决定的,不是事先声明的,这个时候可以先查看一下数组的length,以免出现这个异常

5java.lang.IllegalArgumentException(方法的参数错误)

例如 g.setColor ( int red,int green,int blue)这个方法中的三个值,如果有超过255的会出现这个异常,如果程序中存在这个异常,就要去检查一下方法调用中的参数传递或参数值是不是有错

6java.lang.IllegalAccessException(没有访问权限)

当程序要调用一个类,但当前的方法即没有对该类的访问权限便会出现这个异常。如果程序中用了 Package 的情况下有可能出现这个异常

7java.lang.ArithmeticException(数学运算异常)

当数学运算中出现了除以零这样的运算就会出这样的异常。

8java.lang.ClassCastException(数据类型转换异常)

当试图将对某个对象强制执行向下转换,但该对象又不可转换或又不可转换为其子类的实例时将出现该异常

9java.lang.FileNotFoundException(文件未找到异常)

当程序打开一个不存在的文件来进行读写时将会引发该异常。该异常由 FileInputStream,FileOutputStream ,RandomAccessFile的构造器声明抛出,即使被操作的文件存在,但是由于某些原因不可访问,比如打开一个只有只读权限的文件并向其中写入数据,以上构造方法依然会引发异常

10java.lang.ArrayStoreException(数组存储异常)

当试图将类型为不兼容类型的对象存入一个 Object[] 数组时将引发异常

11java.lang.NoSuchMethodException(方法不存在异常)

当程序试图通过反射来创建对象,访问 ( 修改或读取 ) 某个方法,但是该方法不存在就会引发异常。

12java.lang.EOFException(文件已结束异常)

当程序在输入的过程中遇到文件或流的结尾时,引发异常。因此该异常用于检查是否达到文件或流的结尾

13java.lang.InstantiationException(实例化异常)

当试图通过 Class newInstance () 方法创建某个类的实例 , 但程序无法通过该构造器来创建该对象时引发。
Class 对象表示一个抽象类,接口,数组类,基本类型 。该 Class 表示的类没有对应的构造器。

14java.lang.InterruptedException(被中止异常)

当某个线程处于长时间的等待、休眠或其他暂停状态,
而此时其他的线程通过 Thread interrupt 方法终止该线程时抛出该异常。

15java.lang.CloneNotSupportedException (不支持克隆异常)

当没有实现 Cloneable 接口或者不支持克隆方法时 , 调用其 clone() 方法则抛出该异常

16java.lang.OutOfMemoryException (内存不足错误)

当可用内存不足以让 Java 虚拟机分配给一个对象时抛出该错误

17java.lang.NoClassDefFoundException (未找到类定义错误)

当Java虚拟机或者类装载器试图实例化某个类,而找不到该类的定义时抛出该错误

package exception;

import org.junit.Test;

import java.util.ArrayList;
import java.util.List;
import java.util.stream.Stream;

public class JunitDemo {

    @Test
    public void testException1(){

//        空指针异常
       /* String str  = null;
        System.out.println(str.length());*/
        String str  = null;
        if (str!=null) {
            System.out.println(str.length());
        }
    }


    /**
     * 数组下标越界异常:
     * java.lang.ArrayIndexOutOfBoundsException: 4
     */
    @Test
    public void testException2(){
        Integer[] arr = {1,4,5,6};
//        System.out.println(arr[4]);
        int index = 3;
        if(index list = new ArrayList();
//        list.add("hello");
        list.add(10);
        list.add(20);
        for (Object ele:list) {
            int num = (int)ele;
        }*/

        List list = new ArrayList();
        list.add("hello");
        list.add(10);
        list.add(20);
        for (Object ele:list) {
            if (ele instanceof  Integer){
                int num = (int)ele;
                System.out.println("num:"+num);
            }else{
                System.out.println("不可转换"+ele);
            }


        }



    }


    /**
     * 并发修改异常:java.util.ConcurrentModificationException
     */
    @Test
    public void testException5(){
        List list = new ArrayList();
        list.add(10);
        list.add(20);
        list.add(5);

        /*Iterator its = list.iterator();
        while (its.hasNext()) {
            Integer element = its.next();
            if (element==10){
                list.remove(element);
            }
        }*/

        for (int i = 0; i < list.size(); i++) {
            Integer element = list.get(i);
            if (element==10){
                list.remove(element);
            }
        }
    }

    @Test
    public void testException6(){
        List list = new ArrayList();
        list.add(10);
        list.add(20);
        list.add(5);
//        java.lang.IllegalStateException: stream has already been operated upon or closed
        Stream stream = list.stream();
        stream.forEach(t-> System.out.println(t));

//        流只能被消费一次 再用时需要重新获取流对象
        stream = list.stream();
        long count = stream.distinct().count();
    }
}

 

package exception;

public class StringIndexOutOf {
    public static void main(String args[]) {
        System.out.println("字符串索引越界异常");

        try{
            String str = args[0];
            System.out.println("第四个字符为 " + str.charAt(3));
            int aa = Integer.parseInt(args[0]);
            System.out.println("平方为" + aa * aa);
        }catch (ArrayIndexOutOfBoundsException e){
            System.out.println("ArrayIndexOutOfBoundsException。。。。。。。");
        }catch (StringIndexOutOfBoundsException e){
            System.out.println("StringIndexOutOfBoundsException.....");
        }catch (NumberFormatException e){
            System.out.println("NumberFormatException");
        }

    }
} 

 Error

Error类表示Java运行时产生的系统内部错误或资源耗尽等严重错误

         这种错误通常是程序无法控制和解决的,如果发生这种错误,通常的做法是通知用户并中止程序的执行

 常见的错误类

NoClassDefFoundError
OutOfMemoryError
VirtualMachineError

 检查异常与非检查异常

JAVA实训第四天_第7张图片

 异常处理的一般步骤

异常抛出

JAVA实训第四天_第8张图片 JAVA实训第四天_第9张图片

JAVA实训第四天_第10张图片

 JAVA实训第四天_第11张图片

 

package exceptiondemo.part1;

import javax.imageio.IIOException;
import java.io.EOFException;
import java.io.IOException;

/**
 * @date : 2022/11/24 10:30
 */
public class ExceptionDemo3_1 {

//    public static void main(String[] args) throws Exception {
    public static void main(String[] args) throws EOFException, IIOException {

//        调用method方法 、此时method方法中抛出了必检异常 当前调用method方法地方必须进行处理
//        继续往上抛---main -- jvm虚拟机
        method();
    }


//    因为当前方法通过throw抛出异常   ---》必检异常 不处理不能执行:当前这个method方法不进行处理 必须继续让方法网上抛  方法声明上通过throws
//   throws:写在方法声明上 抛出多个异常 中间用逗号隔开
    public static void  method() throws EOFException, IIOException {

//        java.lang.NumberFormatException: For input string: "abc"
//        Integer.parseInt("abc");

        String password = "12345";
        if (password.length()<6){
//            throw:抛出异常----必检异常
            throw new EOFException("密码长度至少要为6位...");
        }

        throw new IIOException("test.IIOException");

    }
}

 ThrowThrows的区别

JAVA实训第四天_第12张图片

 

异常捕获

JAVA实训第四天_第13张图片

 JAVA实训第四天_第14张图片

JAVA实训第四天_第15张图片

package exceptiondemo.part2;

/**
 * @date : 2022/11/24 15:14
 */
public class ExceptionDemo {

    public static void main(String[] args) {

        System.out.println("1111");


//        针对于可能发生异常代码进行捕获
//        执行流程:一旦try块中发生异常  将会匹配对应catch块:
//                                            1)如果匹配上就会走进对应catch块
//                                            2)如果没有匹配上 等于没有对这个异常进行处理  直接抛出

//        注意事项:
//          1)如果try中没有发生异常 不匹配代码块
//          2)catch语句的排列顺序应该是从子类到父类
        try{
//            Integer.parseInt("abc");
            Integer.parseInt("123");
            System.out.println("-------------");
            System.out.println(5/1);

            String str = null;
            System.out.println(str.length());

        }catch (NumberFormatException e){
//            e.printStackTrace();
            System.out.println("数据类型转换异常"+e.getMessage());
        }catch (ArithmeticException e){
            System.out.println("除数不能为0");
        }catch (NullPointerException e){
            System.out.println("发生空指针异常");
        }catch (Exception e){
            System.out.println("发生异常。。。。。。。。。。。");
        }




    }
}

 

 finally

        当一个方法的某条语句抛出异常后,该方法剩余的语句将无法继续执行。这种情况下,方法往往无法将其 占用的资源进行释放
 解决方法:
在每个 catch 子句的异常处理代码中也加上资源释放的代码,但这种方法非常麻烦;
Java 语言的异常处理机制中提供了一个更好的方案-程序员可以 使用 finally 子句来统一进行资源释放之类的工作。

JAVA实训第四天_第16张图片 

不论 try 块中的代码是否抛出异常及异常是否被捕获, finally 子句 中的代码 一定会被执行
如果 try 块中没有抛出任何异常,当 try 块中的代码执行结束后, finally 中的代码将会被执行;
如果 try 块中抛出了一个异常且该异常被 catch 正常捕获,那么 try 块中自抛出异常的代码之后的所有代码将会被跳过,程序接着执行与抛出异常类型匹配的 catch 子句中的代码,最后执行 finally 子句中的代码。

如果try块中抛出了一个不能被任何catch子句捕获(匹配)的异常,try块中剩下的代码将会被跳过,程序接着执行finally

package exceptiondemo.part2;

import java.sql.SQLException;

/**
 * @date : 2022/11/24 15:41
 */
public class FinallyDemo {


    public static void main(String[] args) {


//        连接数据库时  比较耗费资源   最终想到数据资源释放
        try{
            System.out.println("连接数据库操作。。。。。。。。");
            if(1==2){
                throw new SQLException();
            }

        }catch (SQLException e){
            System.out.println("数据库断开。。。。");

//       finally作用:主要用于释放资源。
        }finally {
            System.out.println("资源释放。。。。。。。。。。");
        }


    }
}

 

package exceptiondemo.part2;

/**
 * @date : 2022/11/24 15:48
 */
public class FinallyDemo2 {

    public static void main(String[] args) {
        int result = method(); // 3
        System.out.println(result);
    }


    public static int method() {
        try {
            System.out.println(111111111);
//            强制中断程序
//            System.exit(0);
            return 1;
        } catch (NullPointerException e) {
            return 2;
        } finally {
            return 3;
        }
    }
}

 Finallyfinal以及finalize的区别

JAVA实训第四天_第17张图片

package exceptiondemo.part1;

import javax.imageio.IIOException;
import java.io.EOFException;

/**
 *
 *
 * Throw和Throws的区别
 *    throw:手动抛出异常  写在方法内部  如果当前方法中没有处理 可以通过throws往上抛
 *    throws:写在方法声明上 向上抛 ,  throws后面可以抛出多个异常  中间需要用逗号隔开
 *
 *
 * @date : 2022/11/24 10:30
 */
public class ExceptionDemo3_2 {

//    public static void main(String[] args) throws Exception {
    public static void main(String[] args) throws Exception {

//        调用method方法 、此时method方法中抛出了必检异常 当前调用method方法地方必须进行处理
//        继续往上抛---main -- jvm虚拟机
        method();
    }


//    因为当前方法通过throw抛出异常   ---》必检异常 不处理不能执行:当前这个method方法不进行处理 必须继续让方法网上抛  方法声明上通过throws
//   throws:写在方法声明上 抛出多个异常 中间用逗号隔开
//          方法声明上抛出异常时:  如果抛出的异常有父子关系时  直接写最大异常就可以了。(实际工作中  异常处理尽可能具体化)

//    public static void  method() throws EOFException, Exception {
    public static void  method() throws Exception {

//        java.lang.NumberFormatException: For input string: "abc"
//        Integer.parseInt("abc");

        String password = "12345";
        if (password.length()<6){
//            throw:抛出异常----必检异常
            throw new EOFException("密码长度至少要为6位...");
        }

        throw new Exception("test.IIOException");

    }


//    如果在子类中覆盖了父类的某一方法,那么该子类方法不可以比被其覆盖的父类方法抛出更多检查异常(但可以更少)。所以,如果被覆盖父类的方法没有抛出任何的“检查异常”,那么子类方法绝不可能抛出“必检异常”

}

 

 创建自己的异常类

JAVA实训第四天_第18张图片

 JAVA实训第四天_第19张图片

JAVA实训第四天_第20张图片

 JAVA实训第四天_第21张图片

异常处理

        方法也可以不对异常进行捕获而直接将其抛出,并在方法声明中进行说明,那么对方法产生的异常到底是应该直接进行捕获还是应该将其进行传递呢?
        一般来说,对于方法的 最终调用者 而言,他必须捕获并处理该方法抛出的异常。而对于 抛出异常的方法 而言,应该对方法可能产生的异常进行区分,尽量避免一些异常的产生,捕获并处理那些你知道如何处理的异常,而对那些你不知道方法的调用者会如何处理的异常,最好将它们留给方法的调用者进行处理,这样会增加程序的灵活性。

         需要特别指出的是,虽然异常处理机制为程序员提供了非常大的方便,但是作为一个好的程序员要尽量避免异常的过度使用这是因为:异常对象的实例化和其后续处理工作是非常消耗资源的,过度的使用异常会明显影响程序的执行速度。所以,在使用异常处理时应该仔细考虑,只对有必要的异常情况使用异常,而不可以将异常泛化。

package exceptiondemo.part1;

import java.io.IOException;
import java.sql.SQLException;

/**
 * @date : 2022/11/24 10:30
 */
public class ExceptionDemo3 {

//    public static void main(String[] args) throws Exception {
    public static void main(String[] args) throws IOException {

//        调用method方法 、此时method方法中抛出了必检异常 当前调用method方法地方必须进行处理
//        继续往上抛---main -- jvm虚拟机
        method();
    }


//    因为当前方法通过throw抛出异常   ---》必检异常 不处理不能执行:当前这个method方法不进行处理 必须继续让方法网上抛  方法声明上通过throws
    public static void  method() throws IOException {

//        java.lang.NumberFormatException: For input string: "abc"
//        Integer.parseInt("abc");

        String password = "12345";
        if (password.length()<6){
//            throw:抛出异常----必检异常
            throw new IOException("密码长度至少要为6位...");
        }


    }
}

 作业

造异常

package housework;

public class test241 {
    public static void main(String[] args) {
//        1、空指针异常
//        NullPointerException

        try{
            String str = null;
            System.out.println(str.length());
        }catch (NullPointerException e){
            System.out.println("空指针异常");
        }

//        2、数学运算异常
//        ArithmeticException
        try{
            System.out.println(5/0);
        }catch (ArithmeticException e){
            System.out.println("数学运算异常");
        }

//        3、数组下标越界异常
//        ArrayIndexOutOfBoundsException
        try{
            String[] arr = {"1", "hello"};
            System.out.println(arr[arr.length]);
        }catch (ArrayIndexOutOfBoundsException e){
            System.out.println("数组下标越界异常");
        }
//        4.字符串转换数字异常
//        NumberFormatException
        try {
            String s = "123*";
            int f = Integer.parseInt(s);
            System.out.println(f);
        }catch (NumberFormatException e){
            System.out.println("字符串转换数字异常");
        }




//        5.类强制转换异常
//        ClassCastException
        try{
            Object a = new Integer(0);
            System.out.println((String)a);
        }catch (ClassCastException e){
            System.out.println("类强制转换异常");
        }

    }
}

你可能感兴趣的:(java,JAVA实训,java)