java中 方法中抛出异常处理方法
Posted
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了java中 方法中抛出异常处理方法相关的知识,希望对你有一定的参考价值。
这边 我需要在 调用到函数的地方处理异常 可是 到下面 我的变量a和b 都无法使用了 这边该怎么解决 求大神 求前辈
那这个程序的异常该怎么捕捉处理呢
Java语言提供两种异常处理机制:捕获异常和声明抛弃异常。
1、捕获异常:
(1)在Java程序运行过程中系统得到一个异常对象是,它将会沿着方法的调用栈逐层回溯,寻找处理这一异常的代码。
(2)找到能够处理这种类型异常的方法后,运行时系统把当前异常交给这个方法处理;如果找不到可以捕获异常的方法,则运行时系统将终止,相应的Java程序也将退出。
(3)捕获异常是通过try-catch-finally语句实现的。语法为:
try
...
catch(ExceptionName1 e)
...
catch(ExceptionName2 e)
...
...
finally
...
2、声明抛弃异常:
(1)当Java程序运行时系统得到一个异常对象时,如果一个方法并不知道如何处理所出现的异常,则可在方法声明时,声明抛弃异常。
(2)声明抛弃异常是在一个方法声明中的throws子句中指明的。如:
public int read() throws IOException
...
其中throws IOException就是声明抛弃异常,throws后可以跟多个异常类型。
扩展资料:
程序设计语言的异常机制:
1、多数语言的异常机制的语法是类似的:用throw或raise抛出一个异常对象(Java或C++等)或一个特殊可扩展的枚举类型的值(如Ada语言);
2、异常处理代码的作用范围用标记子句(try或begin开始的语言作用域)标示其起始,以第一个异常处理子句(catch, except, resuce等)标示其结束;可连续出现若干个异常处理子句,每个处理特定类型的异常。
3、某些语言允许else子句,用于无异常出现的情况。更多见的是finally, ensure子句,无论是否出现异常它都将执行,用于释放异常处理所需的一些资源。
(1)C++异常处理是资源获取即初始化(Resource-Acquisition-Is-Initialization)的基础。
(2)C语言一般认为是不支持异常处理的。Perl语言可选择支持结构化异常处理(structured exception handling)。
(3)Python语言对异常处理机制是非常普遍深入的,所以想写出不含try, except的程序非常困难。
参考资料来源:
百度百科-异常处理
抛出异常:当一个方法出现错误引发异常时,方法创建异常对象并交付运行时系统,异常对象中包含了异常类型和异常出现时的程序状态等异常信息。运行时系统负责寻找处置异常的代码并执行。
捕获异常:在方法抛出异常之后,运行时系统将转为寻找合适的异常处理器(exception handler)。潜在的异常处理器是异常发生时依次存留在调用栈中的方法的集合。当异常处理器所能处理的异常类型与方法抛出的异常类型相符时,即为合适 的异常处理器。运行时系统从发生异常的方法开始,依次回查调用栈中的方法,直至找到含有合适异常处理器的方法并执行。当运行时系统遍历调用栈而未找到合适 的异常处理器,则运行时系统终止。同时,意味着Java程序的终止。
对于运行时异常、错误或可查异常,Java技术所要求的异常处理方式有所不同。
由于运行时异常的不可查性,为了更合理、更容易地实现应用程序,Java规定,运行时异常将由Java运行时系统自动抛出,允许应用程序忽略运行时异常。
对于方法运行中可能出现的Error,当运行方法不欲捕捉时,Java允许该方法不做任何抛出声明。因为,大多数Error异常属于永远不能被允许发生的状况,也属于合理的应用程序不该捕捉的异常。
对于所有的可查异常,Java规定:一个方法必须捕捉,或者声明抛出方法之外。也就是说,当一个方法选择不捕捉可查异常时,它必须声明将抛出异常。
能够捕捉异常的方法,需要提供相符类型的异常处理器。所捕捉的异常,可能是由于自身语句所引发并抛出的异常,也可能是由某个调用的方法或者Java运行时 系统等抛出的异常。也就是说,一个方法所能捕捉的异常,一定是Java代码在某处所抛出的异常。简单地说,异常总是先被抛出,后被捕捉的。
任何Java代码都可以抛出异常,如:自己编写的代码、来自Java开发环境包中代码,或者Java运行时系统。无论是谁,都可以通过Java的throw语句抛出异常。
从方法中抛出的任何异常都必须使用throws子句。
捕捉异常通过try-catch语句或者try-catch-finally语句实现。
总体来说,Java规定:对于可查异常必须捕捉、或者声明抛出。允许忽略不可查的RuntimeException和Error。
4.1 捕获异常:try、catch 和 finally
1.try-catch语句
在Java中,异常通过try-catch语句捕获。其一般语法形式为:
try
// 可能会发生异常的程序代码
catch (Type1 id1)
// 捕获并处置try抛出的异常类型Type1
catch (Type2 id2)
//捕获并处置try抛出的异常类型Type2
关键词try后的一对大括号将一块可能发生异常的代码包起来,称为监控区域。Java方法在运行过程中出现异常,则创建异常对象。将异常抛出监控区域之 外,由Java运行时系统试图寻找匹配的catch子句以捕获异常。若有匹配的catch子句,则运行其异常处理代码,try-catch语句结束。
匹配的原则是:如果抛出的异常对象属于catch子句的异常类,或者属于该异常类的子类,则认为生成的异常对象与catch块捕获的异常类型相匹配。
例1 捕捉throw语句抛出的“除数为0”异常。
public class TestException
public static void main(String[] args)
int a = 6;
int b = 0;
try // try监控区域
if (b == 0) throw new ArithmeticException(); // 通过throw语句抛出异常
System.out.println("a/b的值是:" + a / b);
catch (ArithmeticException e) // catch捕捉异常
System.out.println("程序出现异常,变量b不能为0。");
System.out.println("程序正常结束。");
运行结果:程序出现异常,变量b不能为0。
程序正常结束。
例1 在try监控区域通过if语句进行判断,当“除数为0”的错误条件成立时引发ArithmeticException异常,创建 ArithmeticException异常对象,并由throw语句将异常抛给Java运行时系统,由系统寻找匹配的异常处理器catch并运行相应异 常处理代码,打印输出“程序出现异常,变量b不能为0。”try-catch语句结束,继续程序流程。
事实上,“除数为0”等ArithmeticException,是RuntimException的子类。而运行时异常将由运行时系统自动抛出,不需要使用throw语句。
例2 捕捉运行时系统自动抛出“除数为0”引发的ArithmeticException异常。
public static void main(String[] args)
int a = 6;
int b = 0;
try
System.out.println("a/b的值是:" + a / b);
catch (ArithmeticException e)
System.out.println("程序出现异常,变量b不能为0。");
System.out.println("程序正常结束。");
运行结果:程序出现异常,变量b不能为0。
程序正常结束。
例2 中的语句:
System.out.println("a/b的值是:" + a/b);
在运行中出现“除数为0”错误,引发ArithmeticException异常。运行时系统创建异常对象并抛出监控区域,转而匹配合适的异常处理器catch,并执行相应的异常处理代码。
由于检查运行时异常的代价远大于捕捉异常所带来的益处,运行时异常不可查。Java编译器允许忽略运行时异常,一个方法可以既不捕捉,也不声明抛出运行时异常。
例3 不捕捉、也不声明抛出运行时异常。
public class TestException
public static void main(String[] args)
int a, b;
a = 6;
b = 0; // 除数b 的值为0
System.out.println(a / b);
运行结果:
Exception in thread "main" java.lang.ArithmeticException: / by zero
at Test.TestException.main(TestException.java:8)
例4 程序可能存在除数为0异常和数组下标越界异常。
public class TestException
public static void main(String[] args)
int[] intArray = new int[3];
try
for (int i = 0; i <= intArray.length; i++)
intArray[i] = i;
System.out.println("intArray[" + i + "] = " + intArray[i]);
System.out.println("intArray[" + i + "]模 " + (i - 2) + "的值: "
+ intArray[i] % (i - 2));
catch (ArrayIndexOutOfBoundsException e)
System.out.println("intArray数组下标越界异常。");
catch (ArithmeticException e)
System.out.println("除数为0异常。");
System.out.println("程序正常结束。");
运行结果:
intArray[0] = 0
intArray[0]模 -2的值: 0
intArray[1] = 1
intArray[1]模 -1的值: 0
intArray[2] = 2
除数为0异常。
程序正常结束。 参考技术B 汗,因为你这个不是在同一个类里面,调用ABC类里面的常量ab的话,你需要在在abc类里面重新定义个ab,在将ABC类里面的常量ab赋值给他们就行 参考技术C 调用的成员并不是类内部的成员,不能直接使用,通过引用的方式调用就行了 参考技术D
看了你的代码,问题感觉比较多
我提几点建议,勿恼:
明明是 a/b 除法计算, 方法名称为什么写成add?
if b==0 throw 异常的 这段代码 应该写在 上面 ABC 的 除法方法里面
然后 result.add(4,0); 这句话 要写在 try 里面
如何在 C 中抛出异常?
【中文标题】如何在 C 中抛出异常?【英文标题】:How can I throw an exception in C? 【发布时间】:2011-02-22 22:06:54 【问题描述】:我在 Google 中输入了这个,但我只找到了 C++ 中的操作方法。
如何在 C 中做到这一点?
【问题讨论】:
C 不支持异常处理。要在 C 中引发异常,您需要使用特定于平台的东西,例如 Win32 的结构化异常处理——但要提供任何帮助,我们需要知道您关心的平台。 ...并且不要使用 Win32 结构化异常处理。 使用 setjmp() 和 longjmp() 理论上应该可以工作,但我认为这不值得。 【参考方案1】:C 中没有异常。在 C 中,错误是通过函数的返回值、进程的退出值、给进程的信号(Program Error Signals (GNU libc))或 CPU 硬件中断(或其他通知错误)来通知的如果有,则形成 CPU)(How processor handles the case of division by zero)。
异常是用 C++ 和其他语言定义的。 C++ 中的异常处理在 C++ 标准“S.15 异常处理”中指定,C 标准中没有等效部分。
【讨论】:
所以在 C 中保证不会有异常,如何? @httpinterpret:在 C 中,“保证”没有例外,就像“保证”没有模板、没有反射或没有独角兽一样。语言规范根本没有定义任何这样的事情。不过,有 setjmp/longjmp,可用于退出函数而不返回。因此,程序可以根据需要构建自己的类异常机制,或者 C 实现可以定义标准的扩展。 在.c
文件中带有main
的程序可以包含一些C++,因此可能会在程序中抛出和捕获异常,但是C 代码部分将仍然不知道所有这一切除了异常抛出和捕获通常依赖于驻留在 C++ 库中的用 C 语言编写的函数之外。使用 C 是因为你不能冒险调用函数来执行 throw
需要自己抛出异常。不过,可能有一种编译器/库/目标特定的方式来抛出/捕获异常。但是抛出一个类实例会有它自己的问题。
@Steve:如果你发现一种语言有独角兽,请告诉我,我已经等了很多年了。
@BrianR.Bondy Here 是一种独角兽语言(我保证它的方式与在 C 中保证的方式相同)【参考方案2】:
在 C 中,您可以使用 setjmp.h
中定义的 setjmp()
和 longjmp()
函数的组合。 Example from Wikipedia
#include <stdio.h>
#include <setjmp.h>
static jmp_buf buf;
void second(void)
printf("second\n"); // prints
longjmp(buf,1); // jumps back to where setjmp
// was called - making setjmp now return 1
void first(void)
second();
printf("first\n"); // does not print
int main()
if ( ! setjmp(buf) )
first(); // when executed, setjmp returns 0
else // when longjmp jumps back, setjmp returns 1
printf("main"); // prints
return 0;
注意:我实际上建议您不要使用它们,因为它们在 C++ 中的工作很糟糕(不会调用本地对象的析构函数)而且真的很难了解发生了什么。而是返回某种错误。
【讨论】:
我看到 setjump/longjump 在 C++ 程序中无法正常工作,即使在使用异常时没有需要销毁的对象。我很少在 C 程序中使用它们。 这是一种使用 setjmp 的有趣方法。 on-time.com/ddj0011.htm 但是,是的,如果你想在不展开堆栈的情况下进行带外代码执行,基本上你必须自己发明它们。 当问题是关于 C 和 C++ 时,我不确定为什么在 C++ 中使用它们的警告无论如何都有例外。在任何情况下,重要的是 OP 知道,为了防止 setjmp/longjmp 实现让您的腿受伤,请始终牢记您首先需要访问错误处理程序(设置它),并且该错误处理程序需要返回两次。 顺便说一句,异常处理是我真正希望在 C11 中结束的东西。尽管普遍认为,它确实不需要 OOP 才能正常运行,并且 C 会因每个需要if()
的函数调用而无休止地遭受痛苦。我看不出有什么危险;这里还有其他人吗?
@user4229245 我有一种(轶事)印象,任何“为你做”的事情都尽可能地被排除在 c 语言规范之外,特别是为了让 c 与裸机和机器编程保持相关,甚至像 8 位字节这样的现状基本原理并不普遍,只是我的想法,我不是 c 规范作者【参考方案3】:
C 中没有内置异常机制;您需要模拟异常及其语义。这通常是依靠setjmp
和longjmp
来实现的。
周围有很多库,我正在实现另一个库。它被称为exceptions4c;它便携且免费。您可以查看一下,并将其与 other alternatives 进行比较,看看哪个最适合您。
【讨论】:
我读了你的代码示例,我用一个结构开始了类似的项目,但使用 uuid 而不是字符串来识别每个“异常”。你的项目看起来很有前途。 alternatives 链接现在应该指向github.com/guillermocalvo/exceptions4c/wiki/alternatives 您(或其他任何人)知道不同异常包之间的比较吗?【参考方案4】:普通的旧 C 实际上并不原生支持异常。
您可以使用其他错误处理策略,例如:
返回错误代码 返回FALSE
并使用 last_error
变量或函数。
见http://en.wikibooks.org/wiki/C_Programming/Error_handling。
【讨论】:
windows api也有同样的方法来处理错误。例如 Windows API 中的GetLastError()
。【参考方案5】:
C 能够抛出 C++ 异常。反正是机器码。
例如,在文件bar.c中:
#include <stdlib.h>
#include <stdint.h>
extern void *__cxa_allocate_exception(size_t thrown_size);
extern void __cxa_throw (void *thrown_exception, void* *tinfo, void (*dest) (void *) );
extern void * _ZTIl; // typeinfo of long
int bar1()
int64_t * p = (int64_t*)__cxa_allocate_exception(8);
*p = 1976;
__cxa_throw(p, &_ZTIl, 0);
return 10;
在文件a.cc中,
#include <stdint.h>
#include <cstdio>
extern "C" int bar1();
void foo()
try
bar1();
catch(int64_t x)
printf("good %ld", x);
int main(int argc, char *argv[])
foo();
return 0;
编译它:
gcc -o bar.o -c bar.c && g++ a.cc bar.o && ./a.out
输出
good 1976
https://itanium-cxx-abi.github.io/cxx-abi/abi-eh.html 有更多关于__cxa_throw
的详细信息。
我不确定它是否可移植,我在 Linux 上使用 'gcc-4.8.2' 对其进行测试。
【讨论】:
什么是“_ZTIl”???我在任何地方都找不到对它的任何引用,这完全是一个谜,C 代码如何能够访问 std::type_info。请...帮帮我!_ZTII
表示typeinfo for long
,例如echo '_ZTIl' | c++filt
。这是 g++ 修改方案。
为了更好的措施,请务必在 catch 块中调用 c 符号,以尽可能避免使用 c++ :P(P.S. 感谢您分享一个优秀的真实示例!)
链接已损坏 (404)。
谢谢@PeterMortensen,我已经修复了链接。【参考方案6】:
这个问题非常古老,但我只是偶然发现它并认为我会分享一种技术:除以零,或取消引用空指针。
问题只是“如何抛出”,而不是如何捕获,甚至是如何抛出特定类型的异常。很久以前我遇到过一种情况,我们需要从 C 触发异常以在 C++ 中捕获。具体来说,我们偶尔会报告“纯虚函数调用”错误,需要说服 C 运行时的 _purecall 函数抛出一些东西。所以我们添加了我们自己的 _purecall 函数,该函数除以零,然后,我们得到了一个可以在 C++ 上捕获的异常,甚至使用一些堆栈乐趣来查看哪里出了问题。
【讨论】:
@AreusAstarte 以防万一有人真的需要显示一个 C 除零:int div_by_nil(int x) return x/0;
【参考方案7】:
在带有 Microsoft Visual C++ (MSVC) 的 Windows 上,有 __try ... __except ...
,但它真的很可怕,如果可以避免的话,你不想使用它。最好说没有例外。
【讨论】:
实际上 C++ 异常也是建立在 SEH 之上的。 @Calmarius 什么是SEH? @MarcelWaldvogel 结构化异常处理(Windows 处理 CPU 异常的方式)。【参考方案8】:C 没有异常。
有各种 hacky 实现尝试这样做(一个示例位于:http://adomas.org/excc/)。
【讨论】:
【参考方案9】:正如许多线程中提到的,执行此操作的“标准”方式是使用 setjmp/longjmp。我向https://github.com/psevon/exceptions-and-raii-in-c 发布了另一个这样的解决方案 据我所知,这是唯一依赖于自动清理分配资源的解决方案。它实现了唯一和共享的智能指针,并允许中间函数让异常通过而不捕获,并且仍然可以正确清理它们本地分配的资源。
【讨论】:
【参考方案10】:C 不支持异常。您可以尝试使用 Visual Studio 或 G++ 将 C 代码编译为 C++,看看它是否会按原样编译。大多数 C 应用程序无需重大更改即可编译为 C++,然后您可以使用 try...catch 语法。
【讨论】:
【参考方案11】:如果您使用 happy path 设计模式编写代码(例如,对于嵌入式设备),您可以使用运算符“goto”模拟异常错误处理(AKA 延迟或最终模拟)。
int process(int port)
int rc;
int fd1;
int fd2;
fd1 = open("/dev/...", ...);
if (fd1 == -1)
rc = -1;
goto out;
fd2 = open("/dev/...", ...);
if (fd2 == -1)
rc = -1;
goto out;
// Do some with fd1 and fd2 for example write(f2, read(fd1))
rc = 0;
out:
//if (rc != 0)
(void)close(fd1);
(void)close(fd2);
//
return rc;
它实际上不是一个异常处理程序,但它为您提供了一种在函数退出时处理错误的方法。
P.S.:你应该小心只在相同或更深的范围内使用 goto,并且永远不要跳转变量声明。
【讨论】:
您能否为“延迟”或“最终仿真”添加一些参考?例如,您的意思是 deferring(而不是 "defering")?还是differing? - 也就是说,第一个是否拼写错误?无论如何,您可以添加引用,以便更清楚您的意思吗?【参考方案12】:Implementing exceptions in CEric Roberts。
C Interfaces and Implementations 的第 4 章,作者 Hanson。
A Discipline of Error Handling 道格·摩恩
Implementing Exceptions in C(详细 E. Roberts 的文章)
【讨论】:
【参考方案13】:在 C 中我们不能使用 try case 来处理错误。 但如果您可以使用 Windows.h,那么您可以:
#include <stdio.h>
#include <Windows.h>
#include <setjmp.h>
jmp_buf Buf;
NTAPI Error_Handler(struct _EXCEPTION_POINTERS *ExceptionInfo)
printf("co loi roi ban oi.!!!\r\n");
longjmp(Buf, 1);
void main()
AddVectoredExceptionHandler(1, Error_Handler);
int x = 0;
printf("start main\r\n");
if (setjmp(Buf) == 0)
int y = 1 / x;
printf("end main\r\n");
【讨论】:
以上是关于java中 方法中抛出异常处理方法的主要内容,如果未能解决你的问题,请参考以下文章