import java.io.PrintWriter;
import java.io.StringWriter;
import java.util.logging.Logger;
/**
* Created by 2017 on 2017/11/10.
*/
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);
}
}
}
结果如下
十一月 10, 2017 9:34:31 上午 LoggingException <init>
严重: LoggingException
at LoggingExceptions.main(LoggingExceptions.java:20)
CaughtLoggingException
静态的Logger方法创建了一个string参数的logger对象,这个logger对象会将输出发送到system.err(也就是发送到logger对象初始化的字符串到缓冲区中),执行到构造器新建对象trace的时候,trace就已经拿到了这个logger对象输出到流缓冲区的字符,但是由于我们只是获得了字符,所以我们调用 printStackTrace(new PrintWriter(trace))获取到了其中的异常信息,并通过trace获取错误信息到缓冲区中,然后我们要输出缓冲区重的字符串,调用 logger.severe(trace.toString()); 方法对字符串进行打印,并把结果写入到logger中,最后在main方法里执行try语句的时候会加载LoggingException的构造器,从而通过logger.severe(trace.toString());来打印出logger里的信息到控制台
12.6.3异常链
/**
* Created by 2017 on 2017/11/12.
*/
public class Test {
public static void main(String[] args) {
DynamicFields df = new DynamicFields(3);
System.out.println(df);
try {
df.setField("d", "a value of d");
df.setField("killer47", 47);
df.setField("fatkiller48", 48);
System.out.println(df);
df.setField("d", "a new value of d");
df.setField("thinkiller", 11);
System.out.println("df:" + df);
System.out.println("df.getField(\"d\")" + df.getField("d"));
Object field = df.setField("d", null);
} catch (NoSuchFieldException e) {
e.printStackTrace();
} catch (DynamicFieldException e) {
e.printStackTrace();
}
}
}
class DynamicFieldException extends Exception {}
class DynamicFields {
private Object[][] fields;
public DynamicFields(int initialSize) {
this.fields = new Object[initialSize][2];
// 这里的长度是由用户指定的,里面存储的是initialsize个一唯数组,每一个一唯数组的长度是2
for (int i = 0; i < initialSize; i++) {
// 这里开始遍历1唯数组,然后给1唯数组里的每个元素进行赋值
fields[i] = new Object[]{null, null};
}
}
public String toString() {
StringBuilder result = new StringBuilder();
for (Object[] object : fields) {
// object遍历的数组是1唯数组的个数,1唯数组有几个就遍历几次,
// 由于object取出的是每一个一唯数组,所以object[0]取出的是每一个一唯数组里每一个元素的值,由于上面指定1唯数组的长度是2,所以取0,和1两个下标进行遍历,添加到缓冲区然后返回数组里的所有内容
// object[0]取出的是每一个1唯数组,
result.append(object[0] + ": " + object[1] + "\n");
}
return result.toString();
}
private int hasField(String id) {
for (int i = 0; i < fields.length; i++) {
if (id.equals(fields[i][0]))
return i;
}
return -1;
}
private int getFieldNumber(String id) throws NoSuchFieldException {
int fieldNum = hasField(id);
if (fieldNum == -1) {
throw new NoSuchFieldException();
}
return fieldNum;
}
private int makeField(String id) {
for (int i = 0; i < fields.length; i++) {
if (fields[i][0] == null) {
fields[i][0] = id;
return i;
}
}
// 如果空间满了,那就在造一个空间
Object[][] temp = new Object[fields.length + 1][2];
for (int i = 0; i < fields.length; i++) {
temp[i] = fields[i];
}
temp[fields.length] = new Object[]{null, null};
fields = temp;
return makeField(id);
}
public Object getField(String id) throws NoSuchFieldException {
return fields[getFieldNumber(id)][1];
}
public Object setField(String id, Object value)
throws DynamicFieldException {
if (value == null) {
DynamicFieldException dfe = new DynamicFieldException();
dfe.initCause(new NullPointerException());
throw dfe;
}
int fieldNumber = hasField(id);
if (fieldNumber == -1) {
fieldNumber = makeField(id);
}
Object result = null;
try {
result = getField(id);
} catch (NoSuchFieldException e) {
throw new RuntimeException(e);
// e.printStackTrace();
}
fields[fieldNumber][1] = value;
return result;
}
}
底层类似于一个MAP的容器,我们通过调用DynamicFieldException的initcause方法来把其他的异常链接起来,也可以通过exception的构造器来传入一个异常,这样我们可以追踪到异常最初发生的位置,不过需要注意的是,在调用setfiled的时候,如果跑出文件找不到异常(属于查找才有的异常类型,而不是设置字段应该抛出的异常类型),所以我们需要用接受cause参数的构造器把文件找不到异常转换成运行时异常