Newsletter sign-up
View all newsletters

Enterprise Java Newsletter
Stay up to date on the latest tutorials and Java community news posted on JavaWorld

Sponsored Links

Optimize with a SATA RAID Storage Solution
Range of capacities as low as $1250 per TB. Ideal if you currently rely on servers/disks/JBODs

Java Tip 124: Trace your steps in Java 1.4

Locate runtime code with getStackTrace()

  • Print
  • Feedback

Page 3 of 4

Here are the nested classes:

    public class FirstNested 
        {
        public FirstNested()
            {
            StackTrace.displayStackTraceInformation (new Throwable());
            StackTrace.FirstNested.SecondNested yan =
                new StackTrace.FirstNested.SecondNested();
            
            System.out.println ("Dumping from inside hogwash():");
            yan.hogwash();
            }
        public class SecondNested
            {
            public SecondNested()
                {
                StackTrace.displayStackTraceInformation (new Throwable());
                }
            public void hogwash()
                {
                StackTrace.displayStackTraceInformation (new Throwable());
                Whackable whacked = new Whackable()
                        {
                        public void whack()
                            {
                            StackTrace.displayStackTraceInformation
                                (new Throwable());
                            }
                        };      // End of anonymous member class.
                whacked.whack();
                }       // End of hogwash().
            }   // End of FirstNested.SecondNexted member class.
        }       // End of FirstNested member class.


The topmost stack element for SecondNested's constructor looks like this:

Filename: StackTrace.java
Line number: 267
Package name: boo.hoo
Full class name: boo.hoo.StackTrace$FirstNested$SecondNested
Simple class name: StackTrace$FirstNested$SecondNested
Unmunged class name: StackTrace.FirstNested.SecondNested
Direct class name: SecondNested
Method name: <init>
Native method?: false
toString():
boo.hoo.StackTrace$FirstNested$SecondNested.<init>(StackTrace.java:267)


You can see that the simple class name isn't quite so simple in this case. The nested classes are distinguished from the higher-level nested classes and from the top-level class by using the dollar sign character ($). So, technically, the "simple" name of the second nested class is StackTrace$FirstNested$SecondNested.

I have provided the unmungeSimpleClassName() method to replace the dollar signs with periods for completeness.

Since I'm stubborn, I still wanted to get the truly simple class name, so I created extractDirectClassName():

    public static String extractDirectClassName (String simpleClassName)
        {
        if ((null == simpleClassName) || ("".equals (simpleClassName)))
            return "";
        int lastSign = simpleClassName.lastIndexOf ('$');
        if (0 >s lastSign)
            return simpleClassName;
        return simpleClassName.substring (++lastSign);
        }


The extractDirectClassName() method takes a simple class name and extracts everything after the last dollar sign character, if it exists. If the class isn't nested, then the direct class name is the simple class name. For example, from the multiply nested class example above, you can see that the StackTrace$FirstNested$SecondNested's direct class name is just SecondNested.

Some interesting warts

Constructors are not explicitly named in Java. All constructor methods are implicitly given the name <init>. This is shown in the previous example.

Anonymous inner classes are actually constructed as children of the top-level class in which they are nested, regardless of nesting level. From the multiply nested example above, note that the anonymous inner class is nested inside SecondNested. However, here is the topmost stack element:

Filename: StackTrace.java
Line number: 282
Package name: boo.hoo
Full class name: boo.hoo.StackTrace
Simple class name: StackTrace
Unmunged class name: StackTrace.1
Direct class name: 1
Method name: whack
Native method?: false
toString(): boo.hoo.StackTrace.whack(StackTrace.java:282)


See how the compiler gave the anonymous inner class a numeric direct class name immediately under the top-level class StackTrace? However, note that the array of stack trace elements shows all the nesting; if you want to know the nesting of an anonymous class relative to its actual nesting in the source code, then you must step through the stack elements above it and figure it out yourself. This is left as an exercise for the reader.

  • Print
  • Feedback

Resources