黑马程序员 关于程序异常,黑马程序员程序
黑马程序员 关于程序异常,黑马程序员程序
----------android培训、java培训、java学习型技术博客、期待与您交流!----------
异常:
根据错误的性质,Java将错误分为两类:错误(Error)和异常(Exception)。error是致命的,程序本身不能处理,只能依靠外界干预来改正;Exception是非致命的,能够被捕获处理,从而调整程序运行方向,使程序仍然可以继续运行。
而对于异常,又分为运行时异常和非运行时异常。运行异常是指由程序本身错误引发的异常,这类异常在程序设计时大多是可以避免的(如输入的除数不能为零),运行期间若出现该类异常,则一般终止程序,提示用户进行运行前的预处理改正(如除数改为非零);非运行异常是指由程序运行环境错误引发的异常,该类异常必须捕获并处理。
异常分类:(Java提供了Throwable类,只有Throwable类或其子类的对象,才能被虚拟机或throw语句抛出,并被catch语句捕获;Throwable类有两个子类:Error和Exception刻画了不同程度的异常)
-
Error:比较严重的灾难性错误(不可捕获,任其报错)。如:OutOfMemoryError(内存不足)、ThreadDeath、IOError、LinkageError(库链接错误)等。这些异常发生时,JVM一般会选择线程终止。
-
Exception:程序本身可以处理的异常(可捕获)。分为以下两种
-
运行时异常:RuntimeException类及其子类异常,JVM正常操作期间抛出的异常,不需要事先声明。可不捕获,JVM会接管(
RuntimeException
and its subclasses areuncheckedexceptions.Unchecked exceptions donotneed to be declared in a method or constructor'sthrows
clause if they can be thrown by the execution of the method orconstructor and propagate outside the method or constructorboundary.)如:ArithmeticException(算术异常)、BufferOverflowException(缓冲区上益)、BufferUnderflowException、NullPointerException(空指针)。 -
非运行时异常:RuntimeException以外的异常。必须用catch子句或throws子句指明可能抛出何种异常,否则编译不通过。如:IOException(IO异常)、AWTException(AWT异常)、InterruptedException(中断异常)、TimeoutException(超市异常)
-
这是别人博客上写的,感觉很好:(出现运行时异常后,系统会把异常一直往上层抛,一直遇到处理代码。如果没有处理块,到最上层,如果是多线程就由Thread.run()抛出,如果是单线程就被main()抛出。抛出之后,如果是线程,这个线程也就退出了。如果是主程序抛出的异常,那么这整个程序也就退出了。运行时异常是Exception的子类,也有一般异常的特点,是可以被Catch块处理的。只不过往往我们不对他处理罢了。也就是说,你如果不对运行时异常进行处理,那么出现运行时异常之后,要么是线程中止,要么是主程序终止。如果不想终止,则必须扑捉所有的运行时异常,决不让这个处理线程退出。队列里面出现异常数据了,正常的处理应该是把异常数据舍弃,然后记录日志。不应该由于异常数据而影响下面对正常数据的处理。在这个场景这样处理可能是一个比较好的应用,但并不代表在所有的场景你都应该如此。如果在其它场景,遇到了一些错误,如果退出程序比较好,这时你就可以不太理会运行时异常,或者是通过对异常的处理显式的控制程序退出。)
Java异常处理机制
-
java将程序中运行时出现的各种错误统一处理成“异常对象”,冰箱外抛出;
-
捕获并处理这个异常对象,处理策略是:处理或 声明
-
处理:用try-catch机制实现;用try监控可能出现异常的代码段,用catch捕获和处理异常;
-
声明:就是声明自己不处理,将异常对象抛给它的调用者,用throws机制实现(在方法声明部分用throws指明本方法可能抛出的异常,以提醒调用者务必采取相应的措施)
-
(借助JVM的支持,java的异常处理与传统处理方式有很大不同。由于字节码在执行前需要由虚拟机将其翻译成二进制代码,然后执行。JVM可以在执行前根据当时状况对执行效果进行预测。若是发生异常,则由虚拟机创建异常对象并抛出)
JVM的工作模式:监控模式和 正常模式
JVM对执行结果预测将会一定程度上影响代码执行效率,因此JVM只对try-catch-finally语句和throws标记的代码段实施监控预测模式。正常模式下,发生的错误只能被Java虚拟机捕获和处理(比如Error和没有捕获的运行时异常哦,将会终止JVM运行)
异常的声明(throws)和外抛(throw)
格式
返回类型 方法名(参数列表) throws 异常列表 {方法体}
throw异常对象的引用
实例
import java.io.IOException;
import java.util.Scanner;
public class Test {
/**
* @param args
*/
public static void main(String[] args) {
// TODO Auto-generated method stub
try {
f();
} catch (ArrayIndexOutOfBoundsException e) {
// TODO Auto-generated catch block
System.out.println("数组下标越界异常");
}catch (ArithmeticException e) {
// TODO: handle exception
System.out.println("算术异常");
}catch (Exception e) {
// TODO: handle exception
System.out.println(e.getMessage()+"异常");
}
}
public static void f() throws ArithmeticException,ArrayIndexOutOfBoundsException,Exception{
int[] x={1,2};
int y,z;
while(true){
System.out.print("请输入一个整数,-1表示结束:");
Scanner in=new Scanner(System.in);
y=in.nextInt();
if(y==-1) break;
if(y==2) throw new IOException(); // 假如没有声明Exception的话,这里就会编译错误
z=x[y]/y;
}
}
}
异常传播
来看段代码:
public class Test {
public static void main(String[] args) {
a();
}
static void a(){
b();
}
static void b(){
c();
}
static void c(){
int i=5/0;
}
}
运行结果:
Exception in thread "main" java.lang.ArithmeticException: / by zero
at test.Test.c(Test.java:36)
at test.Test.b(Test.java:33)
at test.Test.a(Test.java:30)
at test.Test.main(Test.java:27)
方法调用顺序:
main → a → b → c
异常传递顺序:
c → b → a → main → JVM(JVM终止)
由于ArithmeticException是运行时异常不需要捕获。
注意点
1. 当try语句块中有return语句,finally也将执行
int f(){
try{
return 5;
}finally{
return 10;
}
}//此方法返回的是10
2.throw有类似return的强力转向功能,即throw后的语句不执行,并且导致编译无法通过。
3. 重写方法中
class A{ // 假如这两个异常调换,会报B类中的异常不能跟A类中的兼容
void f() throws Exception{
}
}
class B extends A{ // 也就是说这个方法中的异常必须和上面方法中的相同或是其子类
void f() throws IOException{
}
}
总结:异常处理机制的有什么好处呢?通过学习,我们可以这样理解,从编程的角度看,异常处理语句将程序正常代码与错误处理代码分开,使程序结构清晰,可读性强;从程序运行的结果看,该机制能使异常处理语句动态监控程序的运行状况,捕获异常能够及时处理,使程序恢复继续执行,从而避免终止。
----------android培训、java培训、java学习型技术博客、期待与您交流!----------
相关文章
- 暂无相关文章
用户点评