繁体   English   中英

Java - 覆盖对象的 toString() 方法,但我必须抛出异常

[英]Java - overriding Object's toString() method, but I have to throw exceptions

我遇到了一个问题,我必须覆盖 Object 的 toString() 方法,但原始方法不会引发任何异常。 但是,我正在使用一些需要抛出异常的通用代码。

public String toString() throws EmptyListException, InvalidPositionException
{
    Position<Entry<E>> current = fList.first();
    StringBuilder str = new StringBuilder();
    for(int i = 0; i < size(); i++)
    {
        try
        {
            str.insert(str.length(), current.element().toString() + " ");
            current = fList.next(current);
        }
        catch(Exception e){}
    }
    return str.toString();
}

这是FavoriteList.java 的一部分。 必须抛出这些异常。 如果有任何方法可以以某种方式抑制这些异常或在方法中捕获它们,那将很有帮助。

最后,我的方法标题必须如下所示:

public String toString()
{ content }

我不在乎方法的结束内容。 只要它编译我就很好。 我只需要修复标题,但我找不到修复它的方法。 非常感谢您提前。

首先,从toString()抛出异常是一个非常糟糕的主意。 toString()用于很多系统软件(例如调试器)来生成对象的表示。

第一个优先选择是做其他事情,可能创建一个可能抛出的不同方法,并在toString()调用该方法,捕获异常并产生替换输出,例如

super().toString() + " threw " + exception.toString();

如果你觉得你真的必须扔,你可以这样做:

    try
    {
        str.insert(str.length(), current.element().toString() + " ");
        current = fList.next(current);
    }
    catch(Exception e){
       throw new IllegalStateExcception(super.toString(), e);
    }

这将受检异常(派生自 java.lang.Exception)包装在未经检查的异常(派生自 java.lang.RuntimeException)中。 无需添加throws子句。

从例外情况来看,我认为这是可能抛出的违规行?:

Position<Entry<E>> current = fList.first();

如果是这种情况,您可以处理该异常。 fList地知道fList是什么,我对 Java 不够熟悉,无法知道编译器是否足够聪明以知道您已经检查过它,但从逻辑fList ,如果fList可能为空,那么我会检查它第一的:

if (/* check for an empty or null fList */) {
    return "";
}
// the rest of your code

如果编译器仍然不喜欢那样,您可以对另一个 try/catch 采取几乎相同的方法。 就像是:

try {
    // the rest of your code
} catch (Exception e) {
    return "";
}

那时该方法真的不应该抛出,因为任何异常都会导致简单地返回一个空字符串。 所以标题应该不需要列出的异常类型。

根据个人喜好,我建议在被捕获时做一些例外的事情 至少在某处记录它,即使是调试日志,也不一定是错误。 从长远来看,全面忽略所有可能的例外通常不是最好的想法。

jdk 不会从 toString() 中抛出 CheckedException 是有原因的。 此方法在运行时用于填充对象。 他们不希望在此方法中实现任何此类可能引发异常的代码或业务逻辑。 无论选中或未选中。

参考单一职责原则, toString() 单一职责是迭代对象的属性并填充它们。

如果您需要编写任何业务逻辑,则应将其隔离在其他方法中。 如果您需要从 toString() 抛出异常和特别检查的异常,那么您需要考虑重构您的代码。

如果您要覆盖它,则不能从 toString() 抛出已检查的异常。 创建一个抛出该异常的方法并从 toString() 调用该方法并捕获该异常并将其包装在未经检查的异常中,

throw new IllegalStateException()throw new RuntimeException()

因此, RuntimeException是有目的的。 运行时异常要么是致命错误,无法让用户继续,要么是非常频繁的操作,例如Arithmetic operation或者说equalshashcode 考虑一种情况,如果hashcode开始抛出一个名为HashCalculationException的异常。 它对HashMap的用户有什么影响,每次在Map上调用getput都必须捕获一个异常。 而且,JDK 提供的这些功能的实现都是异常证明的,以保持与其他 JDK 组件的完整性,并且 JDK 期望开发人员保持相同。 这里是你的第一个问题的答案。

现在,你应该抛出一个未经检查的异常吗? 这是我的看法。 根据指南,使用toString序列化 Java 对象本身是一个坏主意。 toString应该由记录器或任何其他单向处理程序使用,您打印的内容与完整性没有任何区别。 想象一下,您开始使用由toString生成的输出而不是序列化,并编写了自己的方法来从中创建一个新对象。 您的对象正在保存大量数据。 并且您进入了一种情况,您的调用者不小心开始在日志中打印对象......想象一下它会执行多少字符串连接,并且性能会受到影响。

所以我在这种情况下的建议是去掉toString如果它用于序列化。 它不是该方法的目的。 为其创建一个单独的方法。 做同样的事情相当容易,就像在方法签名中添加一个新的异常,然后使用它一样。

您始终可以抛出 Unchecked 异常并稍后捕获它,但强烈建议不要这样做。 它失败的目的。 未经检查的异常是为了避免,而不是捕捉

更多参考,请在此处阅读我们关于 RuntimeException 的讨论 - https://stackoverflow.com/a/58455577/4675277

捕获异常EmptyListException,InvalidPositionException,并在控制台中输出消息。

    public String toString() throws EmptyListException, InvalidPositionException
    {
    Position<Entry<E>> current = fList.first();
    StringBuilder str = new StringBuilder();
    for(int i = 0; i < size(); i++)
    {
    try
    {
        str.insert(str.length(), current.element().toString() + " ");
        current = fList.next(current);
    }

     //here
     catch(EmptyListException, InvalidPositionException e){
       System.out.println(e.getMessage());}
    }
    return str.toString();
   }

EmptyListException异常是由first();引起的。 和InvalidPositionException通过Position>; 因为您是班级客户,所以必须捕获异常。

如果你真的需要抛出异常而不用trycatch包围你的代码

@override
public String toString(){
     if(...)throw new IllegalStateException("list is empty");
     else if(...)throw new IllegalStateException("position is invalid"); 
     return ...;
}

您可以将try块放在for循环之外。 为了捕获fList.first()抛出的异常。

public String toString() throws EmptyListException, InvalidPositionException
{
   try
     {
       Position<Entry<E>> current = fList.first();
       StringBuilder str = new StringBuilder();
       for(int i = 0; i < size(); i++)
       {
            str.insert(str.length(), current.element().toString() + " ");
            current = fList.next(current);
       }
    }
    catch(Exception e){
       e.printStackTrace()
    }
    return str.toString();
}

编辑:记录异常。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM