1

The following Java program just calculates the area of a circle. It uses the concept of inner classes available in Java. One of the inner classes (FirstInner) inherits it's enclosing class named Outer and the SecondInner class derives the FirstInner in turn. The program is working just fine. There is no problem at all. Let's have look at it.

package innerclass;

import innerclass.Outer.SecondInner;   // Need to be inherited.
import java.util.Scanner;

class Outer
{
    protected double r;

    public Outer()
    {

    }

    public Outer(double r)
    {
        this.r=r;
    }

    public class FirstInner extends Outer
    {
        public FirstInner(double r)
        {
            super(r);
        }
    }

    final public class SecondInner extends FirstInner
    {
        public SecondInner(double r)
        {
            Outer.this.super(r);       //<-------------
        }

        public void showSum()
        {
            System.out.print("\nArea of circle = "+(Math.pow(r, 2)*Math.PI)+"\n\n");
        }
    }
}

final public class Main
{
    public static void main(String[] args)
    {
        Scanner s=new Scanner(System.in);
        System.out.print("\nEnter radius:->");
        double r=s.nextDouble();

        Outer o=new Outer();
        SecondInner secondInner = o.new SecondInner(r);
        secondInner.showSum();
    }
}

Now in the SecondInner class, I'm qualifying it's super class which is the FirstInner class first with this and again with Outer like Outer.this.super(r); which simply looks like just super(r);.


The use of only super(r) rather than Outer.this.super(r); causes a compiler-time error indicating that "cannot reference this before supertype constructor has been called". Why is it so? I mean why I have to use Outer.this.super(r); rather than just super(r)?


One more point when I make the FirstInner class static, the program issues no compile-time error and allows to use just super(r) in place of Outer.this.super(r);. Why?

Ravi Bhatt
  • 3,147
  • 19
  • 21
Lion
  • 18,729
  • 22
  • 80
  • 110
  • http://stackoverflow.com/questions/3383460/odd-situation-for-cannot-reference-this-before-supertype-constructor-has-been-c – Stefan Nov 15 '11 at 22:23
  • The call to super(r) should work just fine. That will call the constructor of FirstInner. Can you post the non-working code? – Mihir Mathuria Nov 15 '11 at 22:31
  • The non-working code is only the one where the statement Outer.this.super(r); is replaced just with super(r) in the SecondInner class and this does not work causing a compile-time error as indicated above in the question itself. – Lion Nov 15 '11 at 22:36
  • That's right but I just want to make my concept about inner classes in Java more sophisticated and in some specific situations maybe a very few, such a concept is many a times involved. – Lion Nov 15 '11 at 22:52
  • Ok, I take back my comment. This post: http://stackoverflow.com/questions/7125179/java-inner-class-extends-outer-class has some good discussion going on. – Mihir Mathuria Nov 15 '11 at 23:00
  • Normally you always use static inner classes. Instances of non-static inner classes are bound to instances of the enclosing class. This can be very useful, but you should make a solid design decission before using them (they are especially useful when handling events, for instance). – Maarten Bodewes Nov 15 '11 at 23:30

2 Answers2

2

I get a different error from my Eclipse environment:

"No enclosing instance of type Outer is available due to some intermediate constructor"

This one is clearer and can be linked to the fact that you cannot instantiate a non-static inner class before the outer class has been instantiated.

Maarten Bodewes
  • 90,524
  • 13
  • 150
  • 263
1

Please see the example that is described here.

15.11.2 Accessing Superclass Members using super

From the java tut

http://download.oracle.com/javase/tutorial/java/javaOO/nested.html

An instance of InnerClass can exist only within an instance of OuterClass and has direct access to the methods and fields of its enclosing instance.

Going by that statement, the following approach makes sense. You are accessing the instance using "this" by resolving with the help of the class name, which is defined here in primary expressions .

http://java.sun.com/docs/books/jls/third_edition/html/expressions.html#20860

class SecondInner extends FirstInner
        {

            public SecondInner(double r)
            {
                Outer.this.super(r);       //<-------------
            }

            public void showSum()
            {
                System.out.print("\nArea of circle = "
                  +(Math.pow(r, 2)*Math.PI)+"\n\n");
                }
            }
}

For example if your SecondInner were to be declared within FirstInner it has to be accessed using FirstInner.this.super()

r0ast3d
  • 2,639
  • 1
  • 14
  • 18