jdk中动态代理异常处理分析:UndeclaredThrowableException

当使用 JDK 动态代理时,如果目标方法抛出一个未在代理接口上声明的异常时,会发生 UndeclaredThrowableException 异常。这个异常用于包装仅在运行时可知的受检查异常或 “错误”(Error)类型的异常(例如 java.io.IOExceptionjava.lang.OutOfMemoryError),从而响应于在虚拟机集线器(InvocationHandler)中调用目标方法的异常。下面给出详细的攻略:

JDK中动态代理异常处理分析:UndeclaredThrowableException

当我们使用 JDK 动态代理进行方法调用时,如果目标方法抛出一个未在代理接口上声明的异常,就会发生 UndeclaredThrowableException 异常,如下所示:

interface Foo {
    void foo() throws Exception;
}

class FooImpl implements Foo {
    public void foo() throws Exception {
        throw new Exception();
    }
}

class Main {
    public static void main(String[] args) {
        Handler handler = new Handler(new FooImpl());
        Foo foo = (Foo) Proxy.newProxyInstance(Foo.class.getClassLoader(), new Class<?>[] { Foo.class }, handler);

        try {
            foo.foo();
        } catch (UndeclaredThrowableException e) {
            System.out.println(e.getCause());
        }
    }
}

class Handler implements InvocationHandler {
    private final Object target;

    public Handler(Object target) {
        this.target = target;
    }

    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
        return method.invoke(target, args);
    }
}

输出结果是:java.lang.Exception

JDK 动态代理在执行方法调用时,是通过 InvocationHandler#invoke 方法进行拦截并进行处理的,但是 method.invoke() 抛出的异常类型只有两种:受检查异常和未经检查的异常。受检查异常需要在接口中声明,而未经检查的异常则不需要。我们可以通过在调用 invoke 方法时设置异常处理程序来处理受检查异常和未经检查的异常。

如果目标方法抛出一个未在代理接口上声明的受检查异常,那么运行时系统将使用 UndeclaredThrowableException 异常,该异常的 getCause() 方法返回由 method.invoke() 抛出的实际异常。

例如,如果上面的 Foo 接口从 Exception 中继承 Throwable,那么上面的代码将打印 java.lang.Exception,而不是 UndeclaredThrowableException

下面再给出一个例子:

interface Bar {
    void bar() throws Exception;
}

class BarImpl implements Bar {
    public void bar() {
        throw new RuntimeException();
    }
}

class Main {
    public static void main(String[] args) {
        Handler handler = new Handler(new BarImpl());
        Bar bar = (Bar) Proxy.newProxyInstance(Bar.class.getClassLoader(), new Class<?>[] { Bar.class }, handler);

        try {
            bar.bar();
        } catch (UndeclaredThrowableException e) {
            System.out.println(e.getCause());
        }
    }
}

class Handler implements InvocationHandler {
    private final Object target;

    public Handler(Object target) {
        this.target = target;
    }

    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
        try {
            return method.invoke(target, args);
        } catch (UndeclaredThrowableException e) {
            throw e.getCause();
        }
    }
}

在这个例子中,BarImpl#bar() 抛出一个未经检查的异常。由于未经检查的异常不需要在接口中声明,因此我们无法使用检查异常来处理它们。我们需要在 InvocationHandler#invoke 方法中捕获并重新抛出 UndeclaredThrowableException 异常。此时 UndeclaredThrowableException 异常的 getCause() 方法返回实际抛出的异常,这个例子中就是 RuntimeException

本站文章如无特殊说明,均为本站原创,如若转载,请注明出处:jdk中动态代理异常处理分析:UndeclaredThrowableException - Python技术站

(0)
上一篇 2023年5月27日
下一篇 2023年5月27日

相关文章

  • Spring和Hibernate的整合操作示例

    下面是关于Spring和Hibernate整合的完整攻略。 攻略概述 Spring和Hibernate整合的主要目的是为了将Spring的控制反转(IoC)和依赖注入(DI)与Hibernate的ORM框架结合起来,使开发变得更为高效且有组织。通过整合,Spring可以管理Hibernate的Session和事务,并使得对数据库进行操作更为方便。 整合步骤:…

    Java 2023年5月19日
    00
  • SpringBoot 的 web 类型推断详解

    下面我就为你详细讲解 “SpringBoot 的 web 类型推断详解” 的完整攻略。首先我们要了解什么是 SpringBoot 的 web 类型推断。 什么是 SpringBoot 的 web 类型推断 SpringBoot 的 web 类型推断是指在开发过程中,SpringBoot 会根据项目依赖自动推断使用哪种 Web 服务。在 SpringBoot …

    Java 2023年5月19日
    00
  • 深入了解java.util.Arrays的使用技巧

    深入了解 java.util.Arrays 的使用技巧 java.util.Arrays 类包含了很多用于数组的方法,学会了这些方法,可以大大提高我们的开发效率。本篇攻略将深入了解 java.util.Arrays 的使用技巧。 基本方法 arraysEquals arraysEquals 方法用于比较两个数组是否相等,即数组中的元素是否相等,而不仅是比较数…

    Java 2023年5月26日
    00
  • Java对象的创建过程是什么?

    Java对象的创建过程是Java程序中非常基础、也非常重要的一部分。在Java编程中开发者需要清楚理解Java对象创建的整个流程,本文将为读者详细讲解Java对象的创建过程。 Java对象的创建过程 在Java编程中,创建一个Java对象涉及到了三个步骤: 1、类的加载与加载机制 类的加载与加载机制是Java程序启动时的第一步,Java类需要在Java虚拟机…

    Java 2023年5月11日
    00
  • 颜值与实用性并存的数据库建模工具Chiner教程

    颜值与实用性并存的数据库建模工具Chiner教程 Chiner是一款同时具有出色颜值与实用性的数据库建模工具,支持多种数据库平台。以下是使用Chiner进行数据库建模的完整攻略。 步骤一:安装Chiner 首先,需要前往Chiner的官方网站下载Chiner安装包,并按照提示进行安装。也可以使用以下命令安装: npm install -g chiner 步骤…

    Java 2023年5月19日
    00
  • JAVA基于静态数组实现栈的基本原理与用法详解

    JAVA基于静态数组实现栈的基本原理与用法详解 1.概述 在计算机科学中,栈是一种常见的数据结构。栈数据结构可以看作是一个后进先出(LIFO)的数据容器。元素进入栈的顺序是后进先出,也就是说,最新的元素插入的位置在所有其他元素的顶部,而删除并返回的元素始终是当前元素中的“顶部”元素。本文主要介绍基于静态数组实现栈的基本原理与用法。 2.静态数组 静态数组就是…

    Java 2023年5月26日
    00
  • Spring Boot ActiveMQ如何设置访问密码

    下面是详细讲解 Spring Boot ActiveMQ 如何设置访问密码的攻略: 1. 安装 ActiveMQ 首先需要安装 ActiveMQ。可以从官网下载二进制包,然后进行解压。假设解压后的目录为 activemq。 2. 配置 ActiveMQ 访问账号和密码 2.1 访问控制文件 在 ActiveMQ 的安装目录下,找到 conf 目录中的 act…

    Java 2023年5月20日
    00
  • 深入学习java8 中的CompletableFuture

    深入学习Java8中的CompletableFuture攻略 什么是CompletableFuture CompletableFuture是Java8中新增加的一个类,实现了Future的所有特性,并提供了强大的异步编程能力。CompletableFuture可以让你像写同步代码一样写异步代码,大幅度提高代码的可读性和可维护性。 CompletableFut…

    Java 2023年5月26日
    00
合作推广
合作推广
分享本页
返回顶部