Return back to the blog

Step to super()

Posted by Prashant Deva on March 21, 2011

Consider the following  piece of code:

class B extends A {  //constructor  B()  {        this.field1 = "asdf";  }}void foo(){   B b =  new B();}

Note that the constructor of class B does not contain an explicit call to super()

In a traditional debugger, if you put a breakpoint on the line

B b = new B();

and ‘stepped into’ the call to new B(), you would be taken directly inside B(), with no chance to look at the super constructor of class A. The only way out of this would be to

  1. Go back and explicitly place a breakpoint inside A()
  2. Reproduce the bug (if it is at all possible at this point).
  3. Start debugging all over again….
  4. … only to have this happen again accidentally for the constructor of another class.

Step to Super

Step-super

To deal with the issue of an explicit call to super() not being present, in Chronon we added a ‘Step to Super‘ button in the Stack view.
This button is active only when you are inside a constructor and clicking it takes you directly to the constructor of the superclass of that method.

Step-super-1Step-super-2

The screenshots above show this in action.

Tagged 3 Comments |

3 thoughts on “Step to super()

  1. Actually, you don’t need a ‘step to super’ button, though it may be nice.Eclipse will step into the super with the step Into button, just fine. It will even step through the initializers for the fields, etc.One nice aspect of the button is when it lights up, it reminds you that you can step into the superclass.

  2. Eclipse will be able to step inside super only when you have an explicit super() statement inside your constructor. If you dont, then you cant step inside, unless you explicitly place a breakpoint in the super constructor before stepping in to the constructor call from the calling method. Otherwise eclipse will step directly to the subclass constructor.

  3. That's not true, but I see how you could get faked out. Consider the following classes:<div><br></div><div><div>package com.example.stepper;</div><div><br></div><div>import java.util.Random;</div><div><br></div><div>public class Base {</div> <div><span class="Apple-tab-span" style="white-space:pre">
    </span>protected final int a;</div><div><span class="Apple-tab-span" style="white-space:pre">
    </span>protected final int b = new Random().nextInt();</div><div><span class="Apple-tab-span" style="white-space:pre">
    </span>protected Base() {</div> <div><span class="Apple-tab-span" style="white-space:pre">

    </span>a = b + 50;</div><div><span class="Apple-tab-span" style="white-space:pre">
    </span>}</div><div>}</div><div><br></div><div><div>package com.example.stepper;</div> <div><br></div><div>public class Derived extends Base{</div><div><span class="Apple-tab-span" style="white-space:pre">
    </span>private final int c;</div><div><span class="Apple-tab-span" style="white-space:pre">
    </span>public Derived() {</div> <div><span class="Apple-tab-span" style="white-space:pre">

    </span>c = a + b;</div><div><span class="Apple-tab-span" style="white-space:pre">
    </span>}</div><div><span class="Apple-tab-span" style="white-space:pre">
    </span></div> <div><span class="Apple-tab-span" style="white-space:pre">
    </span>public static void main(String…args) {</div><div><span class="Apple-tab-span" style="white-space:pre">

    </span>Derived d = new Derived();</div><div><span class="Apple-tab-span" style="white-space:pre">

    </span>System.out.println(&quot;Derived = &quot; + d);</div> <div><span class="Apple-tab-span" style="white-space:pre">
    </span>}</div><div>}</div></div><div><br></div><div>Set a breakpoint on the first line of the main() method, where the 'new Derived()' is found.</div><div> <br></div><div>Fire it up, and then do step into, and you'll see this sequence of lines:</div><div><div><span class="Apple-tab-span" style="white-space:pre">

    </span>Derived d = new Derived();</div></div><div><div><span class="Apple-tab-span" style="white-space:pre">
    </span>public Derived() { ?? // This is probably confusing you right here. But it is correct. The JVM enters the derived method first.</div> </div><div><div><span class="Apple-tab-span" style="white-space:pre">
    </span>protected Base() { // Now it enters the superclass's constructor.</div></div><div>(Line 20 of the Object class's default constructor) // Yes, even Object</div> <div><div><span class="Apple-tab-span" style="white-space:pre">
    </span>protected final int b = new Random().nextInt(); // ??Wooo! Initializers become implicit parts of the constructors, before any explicit code, and are stepped through, including in the base class!</div> </div><div><div><span class="Apple-tab-span" style="white-space:pre">

    </span>a = b + 50; // And now back to the actual superclass constructor's explicit code.</div></div><div><div><span class="Apple-tab-span" style="white-space:pre">
    </span>} // Still in super</div> </div><div><div><span class="Apple-tab-span" style="white-space:pre">

    </span>c = a + b; // Finally, back to our derived class's explicit constructor code.</div></div><div><div><span class="Apple-tab-span" style="white-space:pre">
    </span>}</div> </div><div><div><span class="Apple-tab-span" style="white-space:pre">

    </span>Derived d = new Derived(); // Back to new</div></div><div><div><span class="Apple-tab-span" style="white-space:pre">

    </span>System.out.println(&quot;Derived = &quot; + d);</div> </div><div>(inside the toString() method)</div><div>(inside String.valueOf())</div><div>(StringBuilder.append() …)</div><div><br></div><div>Etc.</div><div><br></div><div><br></div><div><br></div><div><br></div><br></div>

Comments are closed.