1.异常
异常分类
异常类和其他类一样继承Object,第二层次是Throwable类,第三个层次分为Exception(异常)和Error(错误)。
Exception
需要程序进行捕获和进行处理的。分为受编译器检测的checked异常(受检异常)和不受编译器检测的unchecked异常(非受检异常)。
Checked exception
非运行时异常 (编译异常)
调用抛出这种异常代码必须要处理导常,否则不能通过编译的,该异常要么被catch子句捕获要么通过throws子句继续抛出。
如:IOException,SQLException等
Unchecked exceptions
运行时异常,RuntimeException 类及其子类异常
测试时程序终止,控制台出现异常
如:NullPointerException、ArrayIndexOutOfBoundException等
Error
错误,不是程序需要捕获和进行处理的,发生时,程序将会停止
由Java虚拟机生成并抛出
如:VirtualMachineError,ThreadDeath等
StackOverflowError
栈溢出错误,虚拟机栈或本地栈空间被耗尽,没有足够资源分配给新创建的栈帧
原因
递归调用过深
执行了大量方法,导致线程栈空间耗尽
不断创建线程
解决
减少递归层数或调用方法层次
手动修改栈大小
OutOfMemoryError
内存溢出
原因
内存泄漏
创建对象过多
解决
减小内存申请空间
手动修改内存空间(栈或堆)大小参数,调整虚拟机启动参数
异常处理
声明抛出处理:
对异常不做处理,抛出由调用方法的地方处理异常
隐式声明抛出:
异常类型是RuntimeException或其子类,直接交给调用方法的地方处理,编译通过,不会对可能产生异常的代码行给出提示.
public class Test {
private static int[] x;
public static void main(String[] args){
System.out.println(x[0]);
}
}
/*
Exception in thread "main" java.lang.NullPointerException
at Test.main(Test.java:4)
*/
显示声明抛出
throws语句
public class Test {
public static void main(String[] args) throws ArithmeticException{
int a,b,c;
a=67; b=0;
c=a/b;
System.out.println(a+"/"+b+"="+c);
}
}
/*
Exception in thread "main" java.lang.ArithmeticException: / by zero
at ExampleException.main(ExampleException.java:6)
*/
注意:当子类覆盖父类方法的时候,子类抛出异常类应和父类相同或者为其子类.
捕获处理
try-catch-finally语句,捕获并处理异常
public class Test {
public static int method() {
int a,b,c;
a=67; b=0;
c=a/b;
return c;
}
public static void main(String[] args) {
try {
System.out.println(method());
}
catch(ArithmeticException ae){
ae.printStackTrace();
System.out.println("Arithmetic Error!");
}
finally {
System.out.println( "Finally" );
}
}
}
/*
java.lang.ArithmeticException: / by zero
at Test.method(Test.java:5)
at Test.main(Test.java:10)
Arithmetic Error!
Finally
*/
多catch情况:
异常类由上到下排布规则是由子到父,由具体到抽象,或为并列关系。执行过程类似于switch case(选一个执行,其它不执行)。若无异常发生,则都不执行。
finally 子句作用:
finally是语句块的统一出口,一般用来进行一些善后清理操作,例如清理资源、释放连接、关闭文件、管道流等操作。它是可选部分,一旦选定,必定执行.
RunTimeException类的子类的异常捕获
ArithmeticException (算术异常)
public class Test {
public static void main(String[] args) {
try{
int a,b;
a=1;
b=0;
System.out.println(a/b);
}
catch(ArithmeticException ae){
ae.printStackTrace();
System.out.println("算术异常");
}
}
}
public class Test {
private static int[] a;
public static void main(String[] args) {
try {
System.out.println(a[2]);
}
catch(NullPointerException ne) {
ne.printStackTrace();
System.out.println("空指针异常");
}
}
}
ClassCastException(类型转换异常)
class Father{}
class Son extends Father{}
public class Test{
public static void main(String args[]){
try{
Father father = new Father();
Son son = (Son) father;
}
catch(ClassCastException ce){
ce.printStackTrace();
System.out.println("类型强制转换异常");
}
}
}
ArrayIndexOutOfBoundsException(数组越界异常)
public class Test {
public static void main(String[] args) {
try{
int[]a=new int[10];
int x=a[100];
System.out.println("x="+x);
}
catch(ArrayIndexOutOfBoundsException ae) {
ae.printStackTrace();
System.out.println("下标越界");
}
}
}
NegativeArraySizeException(数组下标负数异常)
public class Test {
public static void main(String[] args) {
try{
int[] a=new int[100];
a=new int[-1];
}
catch(NegativeArraySizeException ne) {
ne.printStackTrace();
System.out.println("数组下标负数异常");
}
}
}
2.throw与throws
throws
方法抛出异常,一般写在方法的头部,用来抛出一些异常,不进行解决,抛给方法的调用者进行解决(try-catch-finally)
class Example{
int a=25;
int b=0;
int c;
public int method() throws ArithmeticException{
c=a/b;
return c;
}
}
public class Test {
public static void main(String[] args){
Example ex = new Example();
try{
System.out.println(ex.method());
}
catch(ArithmeticException ae){
ae.printStackTrace();
}
}
}
/*
java.lang.ArithmeticException: / by zero
at Example.method(Test.java:6)
at Test.main(Test.java:15)
*/
throw
语句抛出异常,出现于函数内部,用来抛出一个具体异常实例,throw被执行后,直接转入异常处理阶段
class Example{
int a=25;
int b=0;
int c;
public void method(){
c=a/b;
}
}
public class Test {
public static void main(String[] args){
Example ex = new Example();
try{
ex.method();
throw new ArithmeticException();
System.out.println("Try"); //无法访问的语句
}
catch(ArithmeticException ae){
ae.printStackTrace();
}
}
}
/*
java.lang.ArithmeticException: / by zero
at Example.method(Test.java:6)
at Test.main(Test.java:14)
*/
自定义异常类
class SelfException extends Exception {
private int id;
public SelfException(String msg, int id) {
super(msg);
this.id = id;//调用Exception的构造方法
}
public int getId() {
return id;
}
}
public class Test{
public static void checkId(int id) throws SelfException{
if(id < 0){
throw new SelfException("id不能为负值", id);
}else if(id>1500){
throw new SelfException("id超出范围", id);
}else{
System.out.println("id正确");
}
}
public static void main(String args[]){
try{
checkId(10000);
}
catch(SelfException se){
se.printStackTrace();
System.out.println("id=" + se.getId() + " 不正确");
}
}
}
/*
SelfException: id超出范围
at Test.checkId(Test.java:19)
at Test.main(Test.java:27)
id=10000不正确
*/