-1

while i was looking for something else i came across the below post in stackoverflow - How to convert int[] to Integer[] in Java?

here there is a code snippet as mentioned below,

int[] mInt = new int[10];
Integer[] mInteger = new Integer[mInt.length];

List<Integer> wrapper = new AbstractList<Integer>() {
    @Override
    public int size() {
        return mInt.length;
    }

    @Override
    public Integer get(int i) {
        return mInt[i];
    }
};

wrapper.toArray(mInteger);

Can someone please explain the above code for me? am i missing something very fundamental in java language?

when i run through debugger, i see that get and size method gets called automatically, i.e without them being called explicitly from anywhere within or outside of the class !! how so?!

Mark Bramnik
  • 39,963
  • 4
  • 57
  • 97
forkdbloke
  • 1,505
  • 2
  • 12
  • 29

2 Answers2

2

You created an anonymous inner class that extends AbstractList and inherits all the methods from that class.

https://docs.oracle.com/javase/tutorial/java/javaOO/anonymousclasses.html

It just overrides the size() and the get() method and everything else you can find in the class hierarchy.

So it is a good idea to look at the source code of AbstractList.

https://github.com/openjdk-mirror/jdk7u-jdk/blob/master/src/share/classes/java/util/AbstractList.java

As you can see, this class does not imlement a toArray() method. So you have to look at the next class in the hierarchy:

https://github.com/openjdk-mirror/jdk7u-jdk/blob/master/src/share/classes/java/util/AbstractCollection.java

And this class has an implementation of toArray() and inside this method the size() method is called.

public <T> T[] toArray(T[] a) {
        // Estimate size of array; be prepared to see more or fewer elements
        int size = size(); 

But there is no get() call in the method. So you have to dig a little deeper. Receiving elements in the method is done through an iterator. AbstractCollection does not implement the method iterator() to receive one. This is an abstract method. It is implemented in the AbstractList class.

private class Itr implements Iterator<E> {
...
public E next() {
    checkForComodification();
    try {
        int i = cursor;
        E next = get(i);
        lastRet = i;
        cursor = i + 1;
        return next;
    } catch (IndexOutOfBoundsException e) {
        checkForComodification();
        throw new NoSuchElementException();
    }
}

This is the place where get(i) is called.

When I debug the code and set breakpoints in my IDE, I get the following stacktraces:

size:14, CopyToArray$1
toArray:180, AbstractCollection (java.util)
main:23, CopyToArray

and

size:14, CopyToArray$1
hasNext:364, AbstractList$Itr (java.util)
toArray:187, AbstractCollection (java.util)
main:23, CopyToArray

Where CopyToArray is my class with main method to call from the IDE. As you can see there is a class with the name CopyToArray$1 which is the anonymous class that extends AbstractList.

1

Ok, here you deal with something called anonymous class: You create a class "on-the-fly" that extends from AbstractList and override two methods : size and get

when i run through debugger, i see that get and size method gets called automatically, i.e without them being called explicitly from anywhere within or outside of the class !! how so?!

I don't really know what do you mean by "automatically" by its possible that IDE calls these methods to show the content and size of that list in a debugger "variables" window or something. For example if you run them (not debugging) and place some System.out.println inside the overriden methods you won't see any prints on console unless you really call this array.

Now as for the referred question. This approach is not really a good idea to convert things, the answer with streams or with loops are much better.

Mark Bramnik
  • 39,963
  • 4
  • 57
  • 97