1

I'm running into a strange result here and am not sure if it is a bug in Java or it is expected behaviour. I have an inner class on which I've used reflection to get the declared fields (class.getDeclaredFields()). However, when I loop over the list of fields and check the individual types, the "this" field returns the outerclass and not the inner class.

Is this expected behaviour? It seems quite odd to me.

Ex:

import java.lang.reflect.Field;

public class OuterClass {

    public class InnerClass{
        public String innerClassString;
            public InnerClass innerClass;

    }


    public static void main(String[] args) {

        // print the fields of the inner class
        for( Field field : OuterClass.InnerClass.class.getDeclaredFields())
            System.out.println( field.getName() + "   :::   " + field.getType());
    }
}

Output:

innerClassString   :::   class java.lang.String
innerClass   :::   class OuterClass$InnerClass
this$0   :::   class OuterClass

I expected this$0 to be of type OuterClass.InnerClass.

Is this a Java bug? Is there anyway to workaround this unexpected behaviour?

Thanks,

Eric

Eric B.
  • 23,425
  • 50
  • 169
  • 316
  • 4
    99.99% of the time you see unexpected behavior, you can pretty much assume that it's not a bug with a framework that is used by millions of developers around the world. – StriplingWarrior Sep 01 '11 at 03:16
  • I concur. However, I saw a similar-ish post on SO earlier that indicated a bug with the this pointer that was fixed in Java7, so that made me wonder. (http://stackoverflow.com/questions/4823278/inner-class-type-parameter-bound-by-enclosing-class-type-variable) – Eric B. Sep 01 '11 at 03:28
  • `this$0` is a reference to the outer class object. It doesn't need a reference to the Inner class object as that is itself. i.e. `this` – Peter Lawrey Sep 01 '11 at 06:26

2 Answers2

9

Every non-static inner class maintains an invisible ivar that holds a reference to the outer class that it was instantiated for. That's what this$0 is.

Change InnerClass to public static class and see the difference.

For clarity, Oracle recommends this terminology:

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

Terminology: 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.

...

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.InnerClass innerObject = outerObject.new InnerClass();

===

Is there any access to the this$0 variable then from within the inner class if you want?

In a method of the inner class, you can say:

OuterClass outer = OuterClass.this;

or

System.out.println(OuterClass.this.toString());

This special variant of this - OuterClass.this - is accessing the this$0 ivar - it will return the OuterClass instance. Note that this is different than using the regular this inside an InnerClass method, which will return the current InnerClass instance.

===

Furthermore, how can I determine if I am processing the "this$0" field without using a string compare?

I'm unclear what you are trying to do, so I can't recommend how to achieve what you want.

Community
  • 1
  • 1
Bert F
  • 85,407
  • 12
  • 106
  • 123
  • Is there any access to the this$0 variable then from within the inner class if you want? Or is it a hidden, only available via reflection variable? Furthermore, how can I determine if I am processing the "this$0" field without using a string compare? Was hoping to do something like if( field.getType() == classBeingProcessed.getClass() ) continue in my code, but that is obviously not feasible any longer. Is my only choice a string compare then? – Eric B. Sep 01 '11 at 03:26
  • the tutorial got it wrong. you can have an inner class in a static context (say static method), then it doesn't have an enclosing instance. the categorization of classes is pretty confusing. – irreputable Sep 01 '11 at 03:56
0

this$0 is reference in Inner class which tells which instance of Outer class was used to create current instance of Inner class.
The more detail can see this question.

What does it mean if a variable has the name "this$0" in IntelliJ IDEA while debugging Java?

beehuang
  • 339
  • 2
  • 18