packageexceptions;//: exceptions/DynamicFields.java//A Class that dynamically adds fields to itself.//Demonstrates exception chaining.
import static net.mindview.util.Print.*;class DynamicFieldsException extendsException {}public classDynamicFields {privateObject[][] fields;public DynamicFields(intinitialSize) {
fields= new Object[initialSize][2];for(int i = 0; i < initialSize; i++)
fields[i]= new Object[] { null, null};
}publicString toString() {
StringBuilder result= newStringBuilder();for(Object[] obj : fields) {
result.append(obj[0]);
result.append(": ");
result.append(obj[1]);
result.append("\n");
}returnresult.toString();
}private inthasField(String id) {for(int i = 0; i < fields.length; i++)if(id.equals(fields[i][0]))returni;return -1;
}private intgetFieldNumber(String id)throwsNoSuchFieldException {int fieldNum =hasField(id);if(fieldNum == -1)throw newNoSuchFieldException();returnfieldNum;
}private intmakeField(String id) {for(int i = 0; i < fields.length; i++)if(fields[i][0] == null) {
fields[i][0] =id;returni;
}//No empty fields. Add one:
Object[][] tmp = new Object[fields.length + 1][2];for(int i = 0; i < fields.length; i++)
tmp[i]=fields[i];for(int i = fields.length; i < tmp.length; i++)
tmp[i]= new Object[] { null, null};
fields=tmp;//Recursive call with expanded fields:
returnmakeField(id);
}publicObject
getField(String id)throwsNoSuchFieldException {return fields[getFieldNumber(id)][1];
}publicObject setField(String id, Object value)throwsDynamicFieldsException {if(value == null) {//Most exceptions don't have a "cause" constructor.//In these cases you must use initCause(),//available in all Throwable subclasses.
DynamicFieldsException dfe =
newDynamicFieldsException();
dfe.initCause(new NullPointerException());//除了三种基本异常类,其它类型的异常应该使用initCause()方法
throwdfe;
}int fieldNumber =hasField(id);if(fieldNumber == -1)
fieldNumber=makeField(id);
Object result= null;try{
result= getField(id); //Get old value
} catch(NoSuchFieldException e) {//Use constructor that takes "cause":
throw new RuntimeException(e);//原始异常传递给了新的异常
}
fields[fieldNumber][1] =value;returnresult;
}public static voidmain(String[] args) {
DynamicFields df= new DynamicFields(3);
print(df);try{
df.setField("d", "A value for d");
df.setField("number", 47);
df.setField("number2", 48);
print(df);
df.setField("d", "A new value for d");
df.setField("number3", 11);
print("df: " +df);
print("df.getField(\"d\") : " + df.getField("d"));
Object field= df.setField("d", null); //Exception
} catch(NoSuchFieldException e) {
e.printStackTrace(System.out);
}catch(DynamicFieldsException e) {
e.printStackTrace(System.out);
}
}
}/*Output:
null: null
null: null
null: null
d: A value for d
number: 47
number2: 48
df: d: A new value for d
number: 47
number2: 48
number3: 11
df.getField("d") : A new value for d
DynamicFieldsException
at DynamicFields.setField(DynamicFields.java:64)
at DynamicFields.main(DynamicFields.java:94)
Caused by: java.lang.NullPointerException //这里通过异常链显示了前一个异常
at DynamicFields.setField(DynamicFields.java:66)
... 1 more*///:~