27

In the java.util.ArrayList class, the object array for the list's elements is defined as package-private:

transient Object[] elementData; // non-private to simplify nested class access

The comment states that the reason why this field is not private is easier access in nested classes. However, nested classes can access private data of the enclosing class just fine. So why is elementData not private? Is there something happening in the background (e.g., at compilation time)?

3 Answers 3

23

When you access a private field from a nested class, the compiler actually generates a synthetic accessor method that is package-visible, and then uses that for the access. It can't access the private member directly, so to avoid that indirection you can make the member package-visible instead.

Here's an answer with more details.

Sign up to request clarification or add additional context in comments.

1 Comment

13

That comment is outdated. With the introduction of this JEP, there will be no syntactic method created by the compiler anymore; and that was introduced in jdk-11.

Before that change, the problem for such a highly used structure like ArrayList, was that another method in the call-stack (for accessing that private field) could potentially have a high cost in critical paths. To get aways from calling one more method, you could declare the field without private.

1 Comment

The code of ArrayList and other classes doesn't seem to be updated to take advantage of the nest-mate functionality. This mail to a JDK mailing list suggests making such updates.
-1

However, nested classes can access private data of the enclosing class just fine

This is not true for nested classes that are static.

And at least the class ArrayList.SubList is static and accesses elementData.

also see here: https://docs.oracle.com/javase/tutorial/java/javaOO/nested.html

What I claimed here is plain wrong as @tevemadar made clear to me. This is a working example that @tevemadar provided:

public class Test
{
    private int a = 0;

    public static void main(String[] args)
    {
        new Inner().doTest(new Test());
    }

    static class Inner
    {
        void doTest(Test t)
        {
            System.out.println(t.a);
        }
    }
}

4 Comments

That's a constraint/feature of static what you probably mean. A static inner class can't access fields of the outer object directly because there is no outer object (as for static things in general). That's why the article writes about the need of an object reference.
Yes, that is a feature of static. But ArrayList.Sublist can't access dataElement, since it is a static class. So it acccesses it via a reference of ArrrayList, called root. And that does only work if elementData is package private. And the original question was, why that field is package protected and not private.
And that does only work if elementData is package private. - Nope, it would work with an explicit private too. Try this: public class Test {private int a=0;public static void main(String[] args){new Inner().doTest(new Test());}static class Inner{void doTest(Test t){System.out.println(t.a);}};}
You are right. Thanks for beeing so tenacious. That helped me to get rid of my false assumption.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.