Thking in java(第四版)-查缺补漏(第12章)

背景

继续查缺补漏

1.异常与记录日志

例如:

import java.io.*;
import java.util.logging.*;
class LoggingException extends Exception{
	private static Logger logger=
			Logger.getLogger("LoggingException");
	public LoggingException(){
		StringWriter trace=new StringWriter();
		printStackTrace(new PrintWriter(trace));
		logger.severe(trace.toString());
	}
}
public class LoggingExceptions {
	public static void main(String[] args){
		try{
			throw new LoggingException();
		}catch(LoggingException e){
			System.err.println("Caught"+e);
		}
	}
	
}

这里用了 java.util.logging 工具将输出记录到日志中。 Logger.getLogger()方法创建了一个String参数相关联

的Logger对象(通常与错误相关的包名和类名),这个Logger对象会将输出发送到System.err。向Logger写

入的最简单方式就是直接调用与日志记录消息级别想关联的方法,这里使用了severe()。

还可以自己写一个方法来记录其他人编写的异常,例如:

static void logException(Exception e){
		StringWriter trace=new StringWriter();
		e.printStackTrace(new PrintWriter(trace));
		logger.severe(trace.toString());
	}

2.printStackTrace()

printStackTrace()方法所提供的信息可以通过getStackTrace()方法来直接访问,返回一个由栈轨迹中的元素

构成的数组,元素0是栈顶元素,并且是调用序列中的最后一个方法调用。

3.重新抛出异常

重抛异常会把异常抛给上一级环境中的异常处理程序,同一个try快的后续catch子句将被忽略。

4.异常链

捕获一个异常后抛出另一个异常,并且希望把原始异常的信息保存下来,这被称为异常链。

Throwable的子类在构造器中都可以接受一个cause对象作为参数。cause用来表示原始异常,

通过把原始异常传递给新的异常,就可以保留原始的异常数据。

在Throwable的子类中,只有Error、Exception、RuntimeException提供了带cause参数的构造器。

如果要把其他类型的异常链接起来,就要使用initCause()方法。例如:

catch(NoSuchFieldException e){
			throw new RuntimeException(e);
		}

DynamicFieldsException dfe=new DynamicFieldsException();		
dfe.initCause(new NullPointerException());	
throw dfe;

5.异常

异常的基本概念是用名称代表发生的问题。

Throwable对象可分为两种类型,Error和Exception

Error:用来表示编译时和系统错误

Exception:是可以被抛出的基本类型,我们通常关心这个类型。

特例RuntimeException:如果RuntimeException没有被捕获而直达main(),那么在程序退出前将调用异常

printStackTrace()方法。

6.在return中使用finally

例如:

import static tools.Print.*;
public class MultipleReturns {
	public static void f(int i){
		print("Initialization that requires cleanup");
		try{
			print("Point 1");
			if(i==1) return;
			print("Point 2");
			if(i==2) return ;
			print("Point 3");
			if(i==3) return;
			print("End");
			return;
		}finally{
			print("Performing cleanup");
		}
	}
	public static void main(String[] args){
		for(int i=1;i<=4;i++)
			f(i);
	}
}

在f()方法中,可以从多个点返回,并且可以保证finally中的语句仍然得到执行。

7.构造器

(1)在构造阶段可能对抛出异常,并且要求清理的类,最安全的使用方式是使用嵌套的try语句。例如:

        try{
			InputFile in=new InputFile("Cleanup.java");
			try{
				String s;
				int i=1;
				while((s=in.getLine())!=null)
					;
			}catch(Exception e){
				System.out.println("Caught Exception in main");
				e.printStackTrace(System.out);
			}finally{
				in.dispose();
			}
		}catch(Exception e){
			System.out.println("InputFile construction failed");
		}

如果构造出现异常就不会执行in.dispose()。构造成功后就一定会执行in.dispose()。

(2)在创建需要清理的对象之后,立即进入一个try-finally语句块。

NeedsCleanup nc1=new NeedsCleanup();
try{
   //...
}finally{
    nc1.dispose();
}

8.把“被检查的异常”转换为“不检查的异常”

直接把“被检查的异常”包装进RuntimeException里面

try{
    ///...
}catch(Exception e){
    throw new RuntimeException(e);
}

用getCause()捕获并处理特定异常,例如:

catch(RuntimeException re){
    try{
        throw re.getCause();  
    }catch(FileNotFoundException e){
    }catch(IOException e){
    }catch(Throwable e){
    }
}

猜你喜欢

转载自blog.csdn.net/a614528195/article/details/81604127