简体   繁体   中英

How to invoke inner-class constructor?

I've the following classes:

package org.gradle;

public class Supcl {

    public class Inner extends Supsupcl {
        public Inner(int a) {
            System.out.println(a);
        }
    }
}

and

package org.gradle;

public class Subcl extends Supcl.Inner {

    public Subcl() {
        Supcl.Inner.super(34); //error: No enclosing instance of type Supcl is 
                               //available due to some 
                               //intermediate constructor invocation

    }
}

And class Supsupcl :

package org.gradle;

public class Supsupcl {}

If I try to replace Supcl.Inner.super(34); with super(34); the same error will occur. How do it do?

You are referencing an inner class nested to the instance of Supcl , so the right idiom to initialize the inner class is:

new Supcl().new Inner(int i)
(assuming  has a 0-argument constructor or the default constructor)

You cannot invoke super outside the constructor, so you'll have to invoke it as the first line of your Inner(int i) constructor code.

■ From inside the outer class instance code, use the inner class name in the normal way:

MyInner mi = new MyInner();

■ From outside the outer class instance code (including static method code within the outer class), the inner class name must now include the outer class's name:

   MyOuter.MyInner

To instantiate it, you must use a reference to the outer class:

  new MyOuter().new MyInner(); or outerObjRef.new MyInner();

if you already have an instance of the outer class.

Since non-static inner classes have a special relationship with their outer class you always need an instance of the outer class to create an instance of the inner class.

In your case, where a non-inner class extends an inner class, you'll need to either create an instance of the outer class or pass it:

public class Subcl extends Supcl.Inner {
  public Subcl() {
    //assuming there is a no-argument constructor Supcl()
    //this only works in one statement so the call to super is still 
    //part of the first statment in this constructor
    new Supcl().super(34); //will call Inner(34)
  }

  public Subcl( Supcl sup) {
    sup.super(34);  //will call Inner(34)
  }
}

Note that you'd have to do this even if Inner had a no-argument constructor, since you need to somehow get the instance of Supcl and the compiler can't deduce this.

Finally a word of advise (although it is primarily my opinion): as you can see the syntax for inner classes is not always straight forward and it might be hard to grasp what's going on in some cases, thus I'd suggest using inner classes only in simple cases and only if you really need them. It will make your life a lot easier :)

Make the inner static

public static class InnerClass {

} 

and access it like

ParentClass.InnerClass innerClass = new ParentClass.InnerClass(args); 

where args is your custom parameters if you have any

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM