2

I have an implementation of toString() that relies on some code that could throw an exception.

In that case, I want to fail over to the default toString() method.

To that end, is it safe to use

catch (Exception e){
    return ((Object)(this)).toString();
}

as the handler for that exception? In order words, will that cast force the use of the Object toString() method.

It appears to work in my case but I'm worried it's not standard and could cause recursion.

GhostCat
  • 137,827
  • 25
  • 176
  • 248
Dom Alvarez
  • 228
  • 2
  • 7
  • Nope, this will just invoke the toString() method, the "cast" is just a chatty no-op. The only valid way is to use `super.toString()` – Gyro Gearless Sep 03 '18 at 14:20
  • BTW: Do not catch the base class exception. Catch only exeption which can thrown in the try block – Jens Sep 03 '18 at 14:21
  • Possible duplicate of [Can java call parent overridden method in other objects but not subtype?](https://stackoverflow.com/questions/1032847/can-java-call-parent-overridden-method-in-other-objects-but-not-subtype) – Michael A. Schaffrath Sep 03 '18 at 14:22
  • @GhostCat: My colleagues virtually have Stack Overflow etiquette instilled as part of the learning here. – Dom Alvarez Sep 03 '18 at 14:37
  • 1
    Well, it is always fair to wait a day or two, in case other answers come in. But well, the important things have all been covered here ;-) – GhostCat Sep 03 '18 at 14:50

2 Answers2

4

Not at all. The JVM determines at runtime, based on the exact type of an object which method to invoke.

Your nice little casting does achieve nothing. Because you can't change the runtime type of a reference by casting!

One solution would be to have something like:

public String superToString() {
  return super.toString();
} 

inside such classes, and to invoke that method explicitly. Alternatively, the line that currently does that cast could be replaced with return super.toString() of course.

But then, especially option 1 would only add "worse to bad". As in: the contract of toString() is to return a string.

Simply never ever write toString() methods that

  • requires a lot of intensive work to happen or
  • can throw an exception!

See How to use toString method in Java for some further thoughts.

Seriously: in any larger project, you have zero control when/how often/in which ways toString() is called on your objects. You better make sure these calls return quickly, return reasonable information and never ever throw an exception.

GhostCat
  • 137,827
  • 25
  • 176
  • 248
3

No. If it did, that would defeat runtime polymorphism, which is one of Java's fundamental features (for methods). The method selected depends on the actual object you call it on, not on the type of reference you have to the object (which is what casting modifies).

You could use super.toString(), which would use your superclass's version (which may or may not be Object's version, but seems sufficient for your listed use case).

I have an implementation of toString() that relies on some code that could throw an exception.

If that's the case, I'd recommend changing it if possible. If it's not possible to change that, then I'd suggest storing the string version of the object on the object once you've generated it in toString so that subsequent calls are not expensive (raising an exception is expensive). Clear the stored string version if the object is mutable and something affecting toString is modified (so it gets rebuilt next time). In general, toString should be simple and fast.

Calling super's version probably isn't ideal. Instead, perhaps generate a string incorporating the sense of the exception.

T.J. Crowder
  • 1,031,962
  • 187
  • 1,923
  • 1,875
  • Thank you very much for this. Yes, the superclass' version is exactly what I need. – Dom Alvarez Sep 03 '18 at 14:27
  • Good, but I wouldn't advise to call super, there is probably a conceptual design issue whe one need it. "super.toString" purpose is to call the general toString ins the specialized toString imho. – pdem Sep 03 '18 at 14:30
  • 1
    @pdem - Yeah, responding to a failure to build the standard `toString` for the object by using the superclass's `toString` feels wrong. I've suggested doing something else instead. – T.J. Crowder Sep 03 '18 at 14:50