How to Instantiate Non Static Inner Class Within a Static Method

How to instantiate non static inner class within a static method?

You have to have a reference to the other outer class as well.

Inner inner = new MyClass().new Inner();

If Inner was static then it would be

Inner inner = new MyClass.Inner();

Instantiating non-static inner class from a static method

Because an instance of a non-static inner class holds a reference to it's owner object (the instance of the outer class that created it). A static method does not have an associated outer object so it canot create an inner because there is no outer to give it.

class Outer {
Object somethingInTheOuterObject;

class Inner {
// Secretly holds a reference to its outer.

void f() {
// Can access my enclosing instance objects.
Object o = somethingInTheOuterObject;
}
}
}

static void f() {
// Cannot do this.
new Outer.Inner();
// Can do this.
Outer outer = new Outer();
// Can do this.
Outer.Inner inner = outer.new Inner();
// Can even do this.
Outer.Inner inner1 = new Outer().new Inner();
}

Java inner class and static nested class

From the Java Tutorial:

Nested classes are divided into two categories: static and non-static. Nested classes that are declared static are simply called static nested classes. Non-static nested classes are called inner classes.

Static nested classes are accessed using the enclosing class name:

OuterClass.StaticNestedClass

For example, to create an object for the static nested class, use this syntax:

OuterClass.StaticNestedClass nestedObject = new OuterClass.StaticNestedClass();

Objects that are instances of an inner class exist within an instance of the outer class. Consider the following classes:

class OuterClass {
...
class InnerClass {
...
}
}

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.

To instantiate an inner class, you must first instantiate the outer class. Then, create the inner object within the outer object with this syntax:

OuterClass outerObject = new OuterClass()
OuterClass.InnerClass innerObject = outerObject.new InnerClass();

see: Java Tutorial - Nested Classes

For completeness note that there is also such a thing as an inner class without an enclosing instance:

class A {
int t() { return 1; }
static A a = new A() { int t() { return 2; } };
}

Here, new A() { ... } is an inner class defined in a static context and does not have an enclosing instance.

Why can't we have static method in a (non-static) inner class (pre-Java 16)?

Because an instance of an inner class is implicitly associated with an instance of its outer class, it cannot define any static methods itself. Since a static nested class cannot refer directly to instance variables or methods defined in its enclosing class, it can use them only through an object reference, it's safe to declare static methods in a static nested class.

Why can't main function instantiate inner class?

From Java Tutorials:

Static Nested Classes

As with class methods and variables, a static nested class is associated with its outer class. And like static class methods, a static nested class cannot refer directly to instance variables or methods defined in its enclosing class: it can use them only through an object reference.

Inner Classes

As with instance methods and variables, an inner class is associated with an instance of its enclosing class and has direct access to that object's methods and fields. Also, because an inner class is associated with an instance, it cannot define any static members itself.

So if you want to be able to instantiate an inner class, you need to have an instance of the outer class. In instance methods you don't need it because you're always referring to 'this'

how to refer same method from (non static) inner to outer class

By applying the class name to "this":

User.this.call()

Instantiate an Inner class from within a static method of its enclosing Class

isn't it forbidden to instantiate an inner class from within a static context in it's enclosing class?

No - it's forbidden to instantiate an inner class without an instance of the enclosing class. In your case, you do have an instance of the enclosing class:

new MyOuter().new MyInner();

That's entirely fine.

The only reason you can normally get away without specifying the enclosing class from an instance method is that it's equivalent to

// Within an instance method
this.new MyInner();

See section 15.9.2 of the JLS for more details. Your constructor call is a "qualified class instance creation expression".

Can a static nested class be instantiated in Java?

You are either confusing static with abstract as kihero says, or you are muddling the concept with a class that has static methods (which is just a class that happens to have static methods).

A static nested class is just a nested class that doesn't require an instance of its enclosing class. If you are familiar with C++, all classes in C++ are "static" classes. In Java, nested classes are not static by default (this non-static variety is also called an "inner class"), which means they require an instance of their outer class, which they track behind the scenes in a hidden field -- but this lets inner classes refer to fields of their associated enclosing class.

public class Outer {

public class Inner { }

public static class StaticNested { }

public void method () {
// non-static methods can instantiate static and non-static nested classes
Inner i = new Inner(); // 'this' is the implied enclosing instance
StaticNested s = new StaticNested();
}

public static void staticMethod () {
Inner i = new Inner(); // <-- ERROR! there's no enclosing instance, so cant do this
StaticNested s = new StaticNested(); // ok: no enclosing instance needed

// but we can create an Inner if we have an Outer:
Outer o = new Outer();
Inner oi = o.new Inner(); // ok: 'o' is the enclosing instance
}

}

Lots of other examples at How to instantiate non static inner class within a static method

I actually declare all nested classes static by default unless I specifically need access to the enclosing class's fields.



Related Topics



Leave a reply



Submit