3

We have the code:

Iterator<Object> it = new Collection<Object>(){/*...implementation...*/}.iterator();

Q: will the garbage collector remove the object that I created to express the collection? Formally, we have no references to this object, but it (Iterator <Object>) is still connected with the interior of our object of anonymous class.

In other words, consider the code:

Iterator<Object> it = new Collection<Object>(){             // String (1)

    private Object[] array;

    public Iterator<Object> iterator(){
        /*Here, an iterator that references this.array is returned
        + Performing its tasks*/
    } 

    /* + other implementation...*/ 

}.iterator();

Then will GC remove the object created in the first line, which we objectively do not have a link to? //String (1)

For those who are particularly fond of writing pseudo-answers, here is the code for how my iterator looks like:

Iterator<Object> it = new Collection<Object>() { // String (1)

        private Object[] array2;

        @Override
        public Iterator<Object> iterator() {
            return new Iterator<Object>() {
                Object[] array;
                {
                    array = array2;
                }
                @Override
                public boolean hasNext() {
                    // We do what is necessary
                    return false;
                }
                @Override
                public Object next() {
                    // We do what is necessary
                    return null;
                }
            };
        }

        /* + other implementation... */
}.iterator();

Small additional Q:

Can I rename "array2", which is in the implementation of Collection, to "array"? Then How can I use this in the implementation of Iterator?

return new Iterator<Object>() {
    Object[] array;
    {
        array = array2;   // array = array ? It doesn't work. How refer to array above
    }
    // and so on...

About duplication... It's not this question. Maybe it looks like, but I want to receive the answer to my question about DELETING. Will this happen or no, and why? + It's important to receive the answer for additional question. That question can help someone to understand the answer to mine question, but not me.

Direct
  • 133
  • 4
  • Possible duplicate of [Do anonymous classes \*always\* maintain a reference to their enclosing instance?](https://stackoverflow.com/questions/5054360/do-anonymous-classes-always-maintain-a-reference-to-their-enclosing-instance) – the8472 Jun 17 '17 at 16:49
  • 1
    The garbage collector should never delete any object that your program still needs. – Solomon Slow Jun 17 '17 at 20:59

1 Answers1

0

You cannot access the outer class’ field if you give it the same name array, as long as the outer class is an anonymous inner class. However, the whole maintenance of the second array field is obsolete, as it doesn’t prevent the inner(most) class from maintaining a reference to its outer instance, as already explained in Do anonymous classes always maintain a reference to their enclosing instance?.

The solution to both issues is the same, either, don’t use an anonymous inner class, but a named nested class, or move it into a factory method not having the outer instance in scope:

    Iterator<Object> it = new AbstractCollection<Object>() {
        private Object[] array;
        @Override
        public Iterator<Object> iterator() {
            return getIterator(array);
        }
        @Override
        public int size() {
            throw new AssertionError("no-one's gonna call this here");
        }
    }.iterator();
…

static Iterator<Object> getIterator(final Object[] array) {
    return new Iterator<Object>() {
        @Override
        public boolean hasNext() {
            // We do what is necessary
            return false;
        }
        @Override
        public Object next() {
            // We do what is necessary
            return null;
        }
    };
}

Of course, this still leaves two questions

  1. What’s the point of the Collection implementation when we already know that all we’re gonna do is to call the iterator() method? Why not call getIterator method in the first place?

  2. If we are at this point, why not just call Arrays.asList(array).iterator() (keeping in mind that this does not copy the array)?

That said, having a reference does not necessarily prevent garbage collection. Consider The Java® Language Specification, §12.6.1:

A reachable object is any object that can be accessed in any potential continuing computation from any live thread.

Optimizing transformations of a program can be designed that reduce the number of objects that are reachable to be less than those which would naively be considered reachable. For example, a Java compiler or code generator may choose to set a variable or parameter that will no longer be used to null to cause the storage for such an object to be potentially reclaimable sooner.

Note that this even applies to the Iterator instance whose storage may be reclaimed after inlining its code into the caller, i.e. loop, so that it just works on the array. But you won’t notice this, as, of course, the optimizer will ensure that the behavior of the program will not change.

Community
  • 1
  • 1
Holger
  • 285,553
  • 42
  • 434
  • 765