1

Possible duplicate: why-is-java-lang-throwable-a-class

Hi! I doesn't understand why Throwable isn't abstract class. I see only one use case for these: in logging systems for figure out call hierarchy. But it can be some static method for this or other class. So, why?)

Thanks.

upd

from java.util.logging.LogRecord

// Get the stack trace.
StackTraceElement stack[] = (new Throwable()).getStackTrace();

Why it can't be Throwable.getStackTrace(); or as in java.lang.Thread

(new Exception()).getStackTrace();

In this way we can avoid throw new Throwable();

upd2 from javadoc

The Throwable class is the superclass of all errors and exceptions in the Java language.

So, as a superclass it should be abstract, imho. Using it for getting stacktrace isn't good case by this definition.

Community
  • 1
  • 1
Stan Kurilin
  • 15,614
  • 21
  • 81
  • 132
  • Where does it ever "throw new Throwable();" ? Not sure you need to avoid something which never happens. ;) – Peter Lawrey Nov 29 '10 at 18:04
  • @Peter Lawrey : Somebody can write it. API should avoid bad using (not only my IMHO). – Stan Kurilin Nov 29 '10 at 18:11
  • @Stas, It is highly unlikely to compile accidently as it is checked exception. You have to handle it or add it to the throws clause. I think that is avoidance enough. Not convinced there is a serious problem which needs another solution. – Peter Lawrey Nov 29 '10 at 18:14
  • @Stas, My IDE also has a warning "Prohibited Exception thrown" This can be changed to a compiler error level. – Peter Lawrey Nov 29 '10 at 18:16
  • possible duplicate of [why is java.lang.Throwable a class?](http://stackoverflow.com/questions/2890311/why-is-java-lang-throwable-a-class) – user207421 Nov 30 '10 at 00:39
  • Still doesn't answer the question. Being a superclass isn't a sufficient reason to want it to be abstract. – user207421 Nov 30 '10 at 05:53
  • @EJP, If we use class only as superclass, we can use only protected constructor. If we doesn't create its instances - why it shouldn't be abstract? – Stan Kurilin Nov 30 '10 at 06:11
  • Still doesn't answer the question. Why *should* it be abstract? Who said that classes used only as superclasses should be abstract? This is not a hard and fast principle. The only Java language rule about abstract classes is that classes with abstract methods must be declared as abstract. You're trying to create a new rule, and you haven't given anything that approaches a justification. And who said we only use it as a superclass in the first place? – user207421 Nov 30 '10 at 06:47
  • @EJP, to get answer for your first question I start new topic: http://stackoverflow.com/questions/4311271/. About second. I think we should use classes only in use cases that docs gives as. In other hand, API should avoid using classes in wrong ways. – Stan Kurilin Nov 30 '10 at 07:00
  • You're still begging the question. You are defining something as a 'wrong way' without any actual justification, and then using that as the basis for your conclustion. It doesn't follow, and your premiss is invalid. There is nothing in the Javadoc that prevents using Throwable directly. – user207421 Nov 30 '10 at 09:32
  • @EJP, ok. I give up) You are right. But if It was I why develop this API, I've made it in other way. – Stan Kurilin Nov 30 '10 at 13:44

2 Answers2

3

I doesn't understand why Throwable isn't abstract class.

The answer is clearly stated here.

Why it can't be Throwable.getStackTrace(); or as in java.lang.Thread

Quite simply, the getStackTrace() calls the getOurStackTrace() method which is non-static. If getStackTrace() was static, so should getOurStackTrace(). This won't happen as printStackTrace() method uses the getOurStackTrace(). This is elaborated in the JavaDoc:

Provides programmatic access to the stack trace information printed by printStackTrace().

Source for java.lang.Throwable:

 public StackTraceElement[] getStackTrace() {
        return (StackTraceElement[]) getOurStackTrace().clone();
    }

Also, if you read the code of getOurStackTrace() method, you'll see it calls the following method:

private native int getStackTraceDepth();

As far as I know, native cannot be static (I may be wrong).

Community
  • 1
  • 1
Buhake Sindi
  • 87,898
  • 29
  • 167
  • 228
  • Native methods can be static (see pretty much any method in `java.lang.StrictMath`). – Mark Peters Nov 29 '10 at 18:00
  • @Peter Lawrey, it's on the `Throwable` class in the JDK (mine is 1.6.0-21, it was introduced since JDK 4 I believe?) – Buhake Sindi Nov 29 '10 at 18:05
  • If native can be static, I think `Throwable.getStackTrace()` better idea than `new Throwable().getStackTrace()` – Stan Kurilin Nov 29 '10 at 18:07
  • @The Elite Gentleman, java.lang.Thread also has this method. It is marked @since 1.4. Not sure there was a JDK 4. ;) – Peter Lawrey Nov 29 '10 at 18:08
  • @Stas, Throwable.getStackTrace() isn't static because it gets/populates the stack trace for the throwable. (Where it was first created) Calling it more than once, in different places won't give you a different result. – Peter Lawrey Nov 29 '10 at 18:09
  • 1
    @Stas: They would have completely different semantics if it were static. `getStackTrace()` for a subclass of `Throwable` is supposed to return the stacktrace at the point that `fillInStackTrace()` was called, which is at construction of the `Throwable` typically. Calling it statically would have to return whatever the stacktrace is *at the time of the method call* which would be much less useful (e.g. it would print the stacktrace to the logging code, not to where the exception occurred). – Mark Peters Nov 29 '10 at 18:10
  • @Peter Lawrey, the `Thread.getAllStackTraces()` method effectively calls `private native static StackTraceElement[][] dumpThreads(Thread[] threads);` so it's still done natively. – Buhake Sindi Nov 29 '10 at 18:12
  • @Peter Lawrey, @Mark Peters, `Throwable` can initialize itself by calling this static method, cant it? – Stan Kurilin Nov 29 '10 at 18:17
  • @Stas, This method isn't used for good reasons. It initializes the stack trace lazily to improve performance. Most of the time, this array isn't needed, e.g. catch(Exception e) but taking the stack trace when it is used isn't very useful either. – Peter Lawrey Nov 29 '10 at 18:20
  • @The Elite Gentleman, Not sure how your point relates to what I said. – Peter Lawrey Nov 29 '10 at 18:21
  • @Stas: A static method has no reference to an "instance", so no instance can be initialized from a static method unless you pass the instance in. If you're wondering if the data could be stored statically, the answer is yes, but that is absolutely horrible. It would prevent Throwable from being used from multiple threads (without jumping through dozens of hoops), for starters. – Mark Peters Nov 29 '10 at 18:23
  • @Peter Lawrey, sorry...I got lost somehow... :) – Buhake Sindi Nov 29 '10 at 18:24
  • @The Elite Gentleman, still a good point. Another useful method worth knowing about. – Peter Lawrey Nov 29 '10 at 18:25
  • @Mark Peters : I mean smt like `Throwable(){ stackTrace = stackTrace();} public static StackTrace stackTrace()`. Why it's bad? – Stan Kurilin Nov 29 '10 at 18:32
  • @Stas: Well, for starters it would make almost no sense to have such a static method in `Throwable`, since at this point it has nothing to do with throwing/catching, and everything to do with the state of the `Thread`. And as has been explored, Thread already *has* a method for retrieving the stack trace. – Mark Peters Nov 29 '10 at 18:37
  • @Mark Peters, I got lost too. Let's put `native getStackTrace()` into `Thread` and will use it in `abstract class Throwable`. why these solution is bad? PS : off course now API frozen. – Stan Kurilin Nov 29 '10 at 18:51
1

I use it quite often for logging, so I am glad it isn't abstract. There is a method to get the call stack, Thread.currentThread().getStackTrace() but this returns a StackTraceElement[] which isn't very useful for logging.

EDIT:

StackTraceElement[] stes = Thread.currentThread().getStackTrace();  

Note: this method also works to get a stack trace of another thread which can be handy.

Peter Lawrey
  • 525,659
  • 79
  • 751
  • 1,130
  • Can you show how do you use it? In java.util.logging it used to get StackTraceElement[] "(new Throwable()).getStackTrace();" – Stan Kurilin Nov 29 '10 at 17:30
  • 1
    I don't think making Throwable abstract would really stop you...you could either do `new Throwable(){}.printStackTrace()` for throwaway logging, or for logging that you keep you should probably be using the cleaner `Thread` solution anyway (or at least a library method that wraps it). – Mark Peters Nov 29 '10 at 18:14
  • @Mark, logging StackTraceElement[] is tedious to make readable. You don't want it to be split by other log messages for example. esp another stack trace. – Peter Lawrey Nov 29 '10 at 18:24
  • fair enough, though for non-throwaway logging I would expect one to be using a logging framework that does all this for you anyway (all logging frameworks I've seen have methods to log a Throwable directly). – Mark Peters Nov 29 '10 at 18:33