Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Eclipse showing two THIS$0 fields for a nested class (Java)

I have been facing an odd phenomena that I don't quite understand. I have an abstract class that is extended by several other classes. the abstract class is a type of special collection and it has a nested abstract iterator class that fits it. Every class that extends the abstract collection class, also has a nester iterator class that extends the orginal abstract iterator.

The abstract class is something like this:

public abstract class AbstractMultiCollection<T> {

    public AbstractMultiCollection() {
    ...
    }

    MultiIterator<T> iterator();

    public abstract class AbstractMultiIterator {
        public AbstractMultiIterator() {
        ...
        }

The extending classes are something like this:

public class MajorityMultiCollection<T> extends AbstractMultiCollection<T> {
...
    public MultiIterator<T> iterator() {
        return new MajorityIterator();
    }
    ...     

    public class MajorityIterator extends AbstractMultiIterator {

        public MajorityIterator() {
        super();
        ...
        }

        public T next() {
        ...
        }

Simply put, the collections extend the abstract collection and their nested iterators extend the nested abstract iterator.

I have two problems that I don't understand and would appreciate clarification on:

  1. When I debug my code, the "return new MajorityIterator();" lines raise a "Source Not Found" error and "ClassNotFound" exception in the eclipse debugger and a bunch of "ClassLoaderExt" exceptions that I don't understand.
  2. I noticed that every "MajorityIterator" has two "This$0" fields, containing the collection he belongs to. one is null at first, but receives the collection once I invoke the "super();" builder.

I failed to find the reason for this, can anyone clarify? Thanks in advance!

like image 778
user1939304 Avatar asked Oct 23 '25 10:10

user1939304


1 Answers

Actually having two this references makes sense. One thing most people do not realize is how the Java compiler implements non-static nested classes:

  • It implicitly adds a new field with the type of the outer class, lets call it outer$object.

  • It implicitly adds a new argument for the outer class object to all constructors to fill in that field. Incidentally, that means that the default constructor of the inner class actually has a parameter, which makes using it via reflection significantly more complex.

  • It implicitly creates constructors and methods with wider visibility to get around any accessibility issues if e.g. the inner class is declared private.

Since the outer$object field needs to have the same type as the outer class, one will be added each time a nested class inherits from a class that is not nested within the same outer class.

Personally, I tend to avoid non-static non-anonymous inner classes, in order to keep everything explicitly on the surface, rather than let the compiler make a mess out of things...

like image 58
thkala Avatar answered Oct 25 '25 22:10

thkala