我想编写一个可用于不同类和特定行为的异常类。它适用于更改对象 - 比如
a.setWeight(500)
- 但它在我的构造函数中不起作用 - 比如
Cheese b = new Cheese(500);
因为没有生成对象而且在我的WeightException中插入了null。
public class WeightException extends Exception {
private int attribute;
private Object object;
public WeightException(Object o, int a) throws WeightException {
object = o;
attribute = a;
}
public String getMessage() {
if(object instanceof Cheese)
return "Cheese is overweight.";
if(object instanceof Baggage)
return "Baggage is "+String.valueOf(attribute)+" kilos overweight.";
}
}
public class Cheese {
private int weight;
public Cheese(int weight) {
setWeight(weight);
}
public void setWeight(int weight) throws WeightException {
if(weight<200)
this.weight = weight;
else
throw new WeightException(this, weight);
}
}
有人知道更好的解决方法,而不是在我的异常类参数中插入带有类名的字符串吗?
答案 0 :(得分:3)
String.format
构建消息。就个人而言,我发现这是一个反模式,除非您想要与异常一起使用的类非常紧密相关。否则,您将放弃具有语义意义的异常属性名称。
我宁愿看到一个特定于应用程序的超类,它的子类具有语义含义。
答案 1 :(得分:0)
您是否真的尝试过运行此代码? this
变量在构造函数中有效(非null)。即使构造函数抛出异常,也会创建一个新对象并可以引用它。请参阅JLS。
答案 2 :(得分:0)
这是一个需要你使用a "toy" project of mine的解决方案(好吧,我已经在其他项目中使用它了):
制作一个这样的基础抽象类:
public abstract class WeightedItem
{
protected static final MessageBundle BUNDLE;
static {
// The day when you get serious, replace with a properties bundle
final MessageSource source = MapMessageSource.newBuilder()
.put(Cheese.class.getCanonicalName(), "cheese is overweight")
.put(Baggage.class.getCanonicalName(), "baggage is %d kilos overweight")
.build();
BUNDLE = MessageBundle.newBuilder().appendSource(source).freeze();
}
protected int weight;
protected final WeightException doException(final Object... params)
{
return new WeightException(BUNDLE.printf(getClass().getCanonicalName(),
params));
}
}
Baggage
的实现将会:
public class Baggage
extends WeightedItem
{
// ....
public void setWeight(int weight)
throws WeightException
{
if (overweight)
throw doException(weight);
}
}
由于实现既是密钥抵抗的(如果丢失则返回密钥)和格式抵抗(如果格式参数不匹配则返回格式字符串本身),您可以保证参数化消息或快速查看消息错误的位置。 ..
答案 3 :(得分:0)
如果使用消息所需的所有内容参数化异常,则可以避免使用instanceof
,并使异常可用于任何类:
此外,保持对导致异常的对象的引用并不是一个好主意 - 它是不必要的,是一种内存泄漏形式,但重要的是,如果从构造函数抛出异常,将允许this
从构造函数中“逃避”(总是很糟糕)。
public class WeightException extends Exception {
private final int attribute;
private final String className;
private final String units;
public WeightException(Object o, int a) {
this(o, a, null);
}
public WeightException(Object o, int a, String u) {
classname = o.getClass().getSimpleName(); // eg "Cheese"
attribute = a;
units = u == null ? "" : u + " ";
}
public String getMessage() {
return className " is " + attribute + " " + units + "overweight.";
}
}
现在,您可以将此异常用于任何类,而无需进一步修改异常或客户端类,除了提供可选单元:
来自Cheese
:
throw new WeightException(this, weight);
来自Baggage
:
throw new WeightException(this, weight, "kilos");