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

后端 未结 6 1202
抹茶落季
抹茶落季 2020-12-20 17:53

I have run into an issue where I have to override Object\'s toString() method, but the original method doesn\'t throw any exceptions. However, I am using some generic code t

相关标签:
6条回答
  • 2020-12-20 18:29

    So, There is a purpose for RuntimeException. Runtime exceptions are either Fatal errors, which cannot let users to continue, or those are very frequent operations like Arithmetic operation or say equals or hashcode. Consider a case if hashcode started throwing an exception called HashCalculationException. What will be the impact of it on the users of HashMap, every time they call get or put on Map they have to catch an exception. Moreover, the implementations of these functions that are provided with JDK are exception proof, in order to maintain the integrity with other JDK components, and JDK expects developer to maintain the same. Here it comes the answer to your first question.

    Now, Should you throw an unchecked exception? This is my take on it. As per the guideline, using toString for serialization of a Java object itself a bad idea. toString is supposed to be used by loggers, or any other one-way handlers, where what you print doesn't make any difference from the point of integrity. Imagine you started using output generated by toString instead of serialization, and wrote your own method for create a new object out of it. Your object is holding huge data. and you entered in a situation where your caller accidentally started printing the object in logs... Imagine the amount of String concatenations it would do, and performance hit you get.

    So my suggestion in such scenario would be Get rid of toString if it's used to serialization. Its not the purpose of that method. Create a separate method for the same. Its fairly easy to do the same, just like adding a new exception in the method signature, and then use it.

    You can always throw Unchecked exception and catch it later, but it's strongly discouraged. it defeat's the purpose. Unchecked exceptions are meant for avoiding, not catching

    More reference, please read our discussion about RuntimeException here - https://stackoverflow.com/a/58455577/4675277

    0 讨论(0)
  • 2020-12-20 18:31

    Judging by the exceptions, I take it this is the offending line which might throw?:

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

    If that's the case, you can handle that exception. I don't know precisely what fList is and I'm not familiar enough with Java to know if the compiler will be smart enough to know you've checked for it, but logically if the fList could be empty then I would check for that first:

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

    If the compiler still doesn't like that, you can take the pretty much the same approach with another try/catch. Something like:

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

    At that point the method really shouldn't be able to throw, since any exception would result in simply returning an empty string. So the header shouldn't need the exception types listed.

    As a matter of personal preference I would recommend doing something with the exception when it's caught. At least logging it somewhere, even as a debug log and not necessarily an error. A blanket ignore on all possible exceptions isn't often the best of ideas in the long run.

    0 讨论(0)
  • 2020-12-20 18:34

    You can put your try block outside the for loop. On order to catch the exception thrown in 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();
    }
    

    Edit: logging the exception.

    0 讨论(0)
  • 2020-12-20 18:37

    If you really need to throw an exception without surrounding your code with a try and catch

    @override
    public String toString(){
         if(...)throw new IllegalStateException("list is empty");
         else if(...)throw new IllegalStateException("position is invalid"); 
         return ...;
    }
    
    0 讨论(0)
  • 2020-12-20 18:53

    First, throwing exceptions from toString() is a really bad idea. toString() is used in a lot of system software (e.g. debugger) to generate the representation of the object.

    The first preference would be to do something else, maybe create a different method that may throw, and in toString() call that method, catch the exception and produce replacement output such as

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

    If you feel that you really must throw, you can do this:

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

    This wraps a checked exception (derived from java.lang.Exception) in an unchecked exception (derived from java.lang.RuntimeException). No need to add a throws clause.

    0 讨论(0)
  • 2020-12-20 18:53

    There is a reason jdk doesn't throws CheckedException from toString(). This method is used at runtime, to populate the object. They doesn't wanted any such code or business logic to be implemented in this method which can throw exception. No matter checked or unchecked.

    Referring to Single Responsibility Principle, toString() single responsibility is to iterate over object's attribute and populate them.

    If any business logic you need to write then, it should be segregated in other method. If you are needing to throw exception and specially checked exception from toString(), then you need to consider refactoring your code.

    Checked exception can't be thrown from toString() if you are overriding it. Create a method that throws that exception and invoke that method from toString() and catch that exception and wrap it in unchecked exception,

    throw new IllegalStateException() or throw new RuntimeException().

    0 讨论(0)
提交回复
热议问题