不同类对象的异常类

时间:2013-06-14 20:11:03

标签: java exception constructor

我想编写一个可用于不同类和特定行为的异常类。它适用于更改对象 - 比如

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);
    }
    }

有人知道更好的解决方法,而不是在我的异常类参数中插入带有类名的字符串吗?

4 个答案:

答案 0 :(得分:3)

  • 在要使用此类例外的类中实现接口。
  • 接口有一个定义消息的方法,另一个可以提供属性。
  • 或者,提供一系列属性并使用String.format构建消息。
  • 使用该接口定义传入异常ctor的对象参数。
  • 在异常中调用该方法以获取消息。

就个人而言,我发现这是一个反模式,除非您想要与异常一起使用的类非常紧密相关。否则,您将放弃具有语义意义的异常属性名称。

我宁愿看到一个特定于应用程序的超类,它的子类具有语义含义。

答案 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");