How do I access the instance of an enclosing class? [duplicate] - java

This question already has answers here:
Calling outer class function from inner class [duplicate]
(2 answers)
Closed 7 years ago.
My question, in abstract terms, is:
How can a non-static inner class access the instance of the enclosing class? This is required for purposes of using the instance as a parameter in method calls and accessing methods and variables with identical names between the inner and enclosing class.
Like the keywords this and super allow you to access specific versions of methods and variables with identical names in the class and the parent, are there keywords to access versions of methods and variables in enclosing classes and enclosed classes?
If you are confused, continue reading:
Consider the following code example, with two classes and an inner class. Main and Outer are two classes in the package "myPackage" (on a side note, I could not get the following code to work without a package/in the default package, for unknown reasons). Inner is an inner, non-static class of Outer.
package myPackage;
public class Outer {
public void activate() {
System.out.println("Outer.activate");
}
public class Inner {
public void go() {
activate();
}
}
}
package myPackage;
import myPackage.Outer.Inner;
public class Main {
public static void main(String[] args) {
Outer myOuter = new Outer();
Inner myInner = myOuter.new Inner();
myInner.go();
}
}
Note that I construct an Inner with myOuter.new Inner(). Since Inner is non-static, it has to be constructed on top of an existing instance of its enclosing class: in this case, myOuter. Therefore, when I call myInner.go(), myInner calls activate(), which calls activate() on its linked instance of the enclosing class. So myInner calls myOuter.activate(), and the output is:
Outer.activate
Now, consider the following changes:
package myPackage;
public class Outer {
public void activate() {
System.out.println("Outer.activate");
}
public class Inner {
public void activate() {
System.out.println("Inner.activate");
activate();
}
}
}
package myPackage;
import myPackage.Outer.Inner;
public class Main {
public static void main(String[] args) {
Outer myOuter = new Outer();
Inner myInner = myOuter.new Inner();
myInner.activate();
}
}
Now when I call myInner.activate(), myInner outputs, then calls activate(). However, since Inner now has a method called activate(), myInner uses that version instead of the version in the instance of the enclosing class. So myInner calls myInner.activate(), and the output is:
Inner.activate
Inner.activate
Inner.activate
Inner.activate
Inner.activate
Inner.activate
...
Over and over, and ends in a stack overflow error. So my question in this context is how to change Inner.activate() such that it outputs, then calls its enclosing instance version's of activate() instead of its own. The output would then be:
Inner.activate
Outer.activate
Thanks in advance for your assistance.

You access this of the outer class by pre-pending the name of the class to this keyword, as follows:
Outer.this.activate();
This resolves the scope of this to reference the object of the outer class, which is implicitly stored inside objects of non-static inner classes.
Demo.

Related

Static Nested class can be extended by not non-static [duplicate]

This question already has answers here:
no enclosing instance of type... in scope
(2 answers)
Closed 5 years ago.
My code is as following :-
A class T can extend ClassO.Four. Four is a static class inside ClassO but cannot extend ClassO.Two Two is an inner class inside ClassO. I am getting error
No enclosing instance of type ClassO is available due to some intermediate constructor invocation
What is the reason of difference in behaviour?
class ClassO
{
interface inner
{
void msg();
}
class Two implements inner
{
public void msg()
{
System.out.println("Class Two");
}
}
static class Four
{
public void msg()
{
System.out.println("Class Four");
}
}
public void m()
{
}
}
class T extends ClassO.Two **// can extend ClassO.Four but not ClassO.Three**
{
public void msg()
{
System.out.println("Class Two");
}
}
Recall that a static inner class is a "normal" class with the name nested inside its owner class, and additional access privileges to private static members of its owner class. As a result, static inner classes have no restrictions as to the location from which they could be instantiated.
In contrast, a non-static inner class has access to both static and non-static members of its owner class. To make this possible, Java compiler embeds a hidden pointer to the owner into the nested class, and passes an instance of the owner to that constructor.
This behavior relies on the availability of owner's this at the point of instantiation of the non-static inner class. If compiler were to allow you to inherit from a non-static member outside its owner, it wouldn't be able to instantiate your derived class, in effect forcing it to behave as if it were an inner class. That is why the compiler prohibits such inheritance.

Why we can not make an instance of inner class inside the main method of outer class in regular way?

I know how to make an instance of an inner class. But I want to know why we can not do that in the following way:
class outerclass{
public static void main(String[] args){
innerclass in=new innerclass();
}
class innerclass{
}
}
If I do this then I get the following error:
No enclosing instance of type outerclass is accessible. Must qualify the allocation with an enclosing instance of type outerclass (e.g. x.new A() where x is an instance of outerclass).
Why?
class Demo{
public static void main(String[] args){
System.out.println(innerclass.a);
}
static class innerclass{
static int a=1;
}
}
Gives the output 1.
See here while making the inner class as static You can easily access in your outer class,In order to create an instance of the Nested class you must reference it by prefixing it with the Outer class name, like this:
Outer.Nested instance = new Outer.Nested();
Non-static Nested Classes (Inner Classes)
Non-static nested classes in Java are also called inner classes. Inner classes are associated with an instance of the enclosing class. Thus, you must first create an instance of the enclosing class to create an instance of an inner class. Here is an example inner class definition:
public class Outer {
public class Inner {
}
}
Here is how you create an instance of the Inner class:
Outer outer = new Outer();
Outer.Inner inner = outer.new Inner();
Notice how you put new after the reference to the outer class in order to create an instance of the inner class.
Non-static nested classes (inner classes) have access to the fields of the enclosing class, even if they are declared private. Here is an example of that:
public class Outer {
private String text = "I am private!";
public class Inner {
public void printText() {
System.out.println(text);
}
}
}
Your innerclass is not static. This means it must have a reference to the outerclass. main is static and has no implicit outerclass.
The simple solution is to make your inner class a static nested class.
You must either make your inner class static (as already mentioned) or create your inner class from a non-static context, e.g. from a non-static method.
I.e. either this:
class outerclass{
void myMethod() {
innerclass in = new innerclass();
}
class innerclass{
}
}
or this
class outerclass{
public static void main(String[] args){
innerclass in=new innerclass();
}
static class innerclass{
}
}
outerclass thats encapsulates innerclass is not instantiated, hence, calling innerclass directly would throw an error since there is no outerclass to attach innerclass.
Therefore as suggested by the previous answers, making innerclass static would resolve the problem, allowing access to the innerclass without instantiation.
There are lot of existing answers with regards to this topic. A quick google brings this up.
Java - No enclosing instance of type Foo is accessible

Access methods within local inner classes in Java

Is there any way to access the methods of local inner classes in Java. Following code is the sample code that I tried before. According to that what is the mechanism to access the mInner() method?
class Outer{
int a=100;
Object mOuter(){
class Inner{
void mInner(){
int y=200;
System.out.println("mInner..");
System.out.println("y : "+y);
}
}
Inner iob=new Inner();
return iob;
}
}
class Demo{
public static void main(String args[]){
Outer t=new Outer();
Object ob=t.mOuter();
ob.mInner(); // ?need a solution..
}
}
As ILikeTau's comment says, you can't access a class that you define in a method. You could define it outside the method, but another possibility is to define an interface (or abstract class). Then the code would still be inside your method, and could access final variables and parameters defined in the method (which you couldn't do if you moved the whole class outside). Something like:
class Outer {
int a = 100;
public interface AnInterface {
void mInner(); // automatically "public"
}
AnInterface mOuter() { // note that the return type is no longer Object
class Inner implements AnInterface {
#Override
public void mInner() { // must be public
int y = 200;
System.out.println("mInner..");
System.out.println("y : " + y);
}
}
Inner iob = new Inner();
return iob;
}
}
class Demo {
public static void main(String[] args) { // the preferred syntax
Outer t = new Outer();
Outer.AnInterface ob = t.mOuter();
ob.mInner();
}
}
Note: not tested
Note that the return type, and the type of ob, have been changed from Object. That's because in Java, if you declare something to be an Object, you can only access the methods defined for Object. The compiler has to know, at compile time (not at run time) that your object ob has an mInner method, and it can't tell that if the only thing it knows is that it's an Object. By changing it to AnInterface, the compiler now knows that it has an mInner() method.
The scoping rules of a local class are pretty much the same as the scoping rules of a variable, that is, it is confined to the enclosing block.
The same way you cannot access variable iob from main, you cannot access local class Inner from main.
Outside the enclosing block, there's no difference between a local class and an anonymous class. Neither can be accessed. The difference is that within the enclosing block, the local class can be accessed by name, especially useful if you need to access it repeatedly, e.g. to create multiple instances.
The only way to interact with a local/anonymous class outside the enclosing block, is through any superclass or interface implemented by the class in question.
To access the inner class create an object of inner class..
OuterClass.InnerClass innerObject = outerObject.new InnerClass();
from your example
outer t=new outer();
outer.inner inner1=t.new inner();
Hope this helps you...

Inner classes inherited from the enclosing class in Java

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?
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.
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()

Must the inner class be static in Java?

I created a non-static inner class like this:
class Sample {
public void sam() {
System.out.println("hi");
}
}
I called it in main method like this:
Sample obj = new Sample();
obj.sam();
It gave a compilation error: non-static cannot be referenced from a static context When I declared the non-static inner class as static, it works. Why is that so?
For a non-static inner class, the compiler automatically adds a hidden reference to the "owner" object instance. When you try to create it from a static method (say, the main method), there is no owning instance. It is like trying to call an instance method from a static method - the compiler won't allow it, because you don't actually have an instance to call.
So the inner class must either itself be static (in which case no owning instance is required), or you only create the inner class instance from within a non-static context.
A non-static inner class has the outer class as an instance variable, which means it can only be instantiated from such an instance of the outer class:
public class Outer{
public class Inner{
}
public void doValidStuff(){
Inner inner = new Inner();
// no problem, I created it from the context of *this*
}
public static void doInvalidStuff(){
Inner inner = new Inner();
// this will fail, as there is no *this* in a static context
}
}
An inner class needs an instance of the outer class, because there is an implicit constructor generated by compiler. However you can get around it like the following:
public class A {
public static void main(String[] args) {
new A(). new B().a();
}
class B {
public void a() {
System.err.println("AAA");
}
}
}
Maybe this will help : http://java.sun.com/docs/books/tutorial/java/javaOO/nested.html
the non-static inner class cannot be called in a static context (in your example there is no instance of the outer class).

Categories

Resources