50

I am generating an ArrayList of objects. Following is the code

ArrayList someArrayList = new ArrayList();

Public ArrayList getLotOfData()
{
ArrayList someData = new ArrayList();
return someData; 
}


someArrayList = eDAO.getLotOfData();

Once I have this ArrayList object "someArrayList", I would like to declare it public and final and store it in a Constants file so that it can be accessed globally. Is there a way I can do that? If I declare an Arraylist object public and final, then I would not be able to reassign any values to it. I tried the following

public final ArrayList anotherArrayList = new ArrayList();

anotherArrayList.addAll(someArrayList);

I had hoped to store this "anotherArrayList" as a global ArrayList object and use it, but this returns a nullpointer exception. I want to use it just like a String constant "ConstantsFile.anotherArrayList". Any ideas???

Raghu
  • 1,141
  • 5
  • 20
  • 39
  • can someone please edit this? – Paul Nikonowicz Feb 14 '12 at 22:23
  • 3
    You're actually a bit confused; declaring a variable final means only that you can't set the reference to something else, not that you can't add objects to it. – Dave Newton Feb 14 '12 at 22:27
  • @Dave...I am also surprised as to why this returns a nullpointer exception – Raghu Feb 14 '12 at 22:28
  • 3
    Let me get this straight: You got a NullPointerException, and rather than looking at the stacktrace or debugging to find out what is null, you turn to stackoverflow to write your code for you. A much better question to ask would be how you can locate the cause of a NullPointerException - provided that questions hadn't been answered over and over, of course. – meriton Feb 14 '12 at 22:32
  • @Raghu Why what "returns" an NPE? – Dave Newton Feb 14 '12 at 22:32
  • @Raghu Will you accept an answer? If none of the answers are acceptable, please state what else you are seeking from an answer. – Bohemian Feb 20 '12 at 00:37

5 Answers5

100

You can easily make it public static final, but that won't stop people from changing the contents.

The best approach is to safely publish the "constant" by:

  • wrapping it in an unmodifiable list
  • using an instance block to populate it

Resulting in one neat final declaration with initialization:

public static final List<String> list = Collections.unmodifiableList(
    new ArrayList<String>() {{
        add("foo");
        add("bar");
        // etc
    }});

or, similar but different style for simple elements (that don't need code)

public static final List<String> list = 
    Collections.unmodifiableList(Arrays.asList("foo", "bar"));
Bohemian
  • 412,405
  • 93
  • 575
  • 722
37

Guava provides ImmutableList for just about this reason. (Also, it doesn't have the unnecessary space overhead that ArrayList allocates to make room for future elements which you won't be adding for your application.)

public static final ImmutableList<String> CONSTANTS = 
  ImmutableList.of("foo", "bar");
Iulian Popescu
  • 2,595
  • 4
  • 23
  • 31
Louis Wasserman
  • 191,574
  • 25
  • 345
  • 413
31

Java 1.4 compatible way:

public static final List STRINGS = Collections.unmodifiableList(
    Arrays.asList(new String[] {"foo", "bar"}));

Such List is unmodifiable, calling methods such as add(), remove() or set() will cause UnsupportedOperationException.

For less ancient Java versions:

public static final List<String> STRINGS = Collections.unmodifiableList(
    Arrays.asList("foo", "bar"));

And finally, Java 9 comes with:

public static final List<String> STRINGS = List.of("foo", "bar");
Natix
  • 14,017
  • 7
  • 54
  • 69
3

Since Java 9 the solution is super simple.

You do not even need Guava, since we have:

    public static final List<String> list = List.of("foo", "bar");
Zarremgregarrok
  • 484
  • 5
  • 8
0

Here is another way you can create a final ArrayList and then make it unmodifiable. It involves creating a class to hold the final ArrayList.

First, make your list, doing all the mutations you need to do.

Second, create a class that will create the final ArrayList in its constructor.

public class Wrapper {

    final List<T> list;
   
    // Other final variables to be set and added to the constructor.

    public Wrapper(List<T> list) {
        this.list = Collections.unmodifiableList(list);
    }

}

This is useful for when you need an immutable class with a List.

John Glen
  • 771
  • 7
  • 24
  • This is what `Collections.unmodifiableList()` does - returns a wrapper. Using this class adds no value: ie `new Wrapper(myList)` is effectively the same as `Collections.unmodifiableList(Collections.unmodifiableList(myList))`. Why would the caller use you class and not just use `Collections.unmodifiableList(myList)`? Also note that making the field `final` is not required - not providing a setter is enough. – Bohemian Aug 26 '20 at 23:27
  • When you need a immutable class with a List. Said immutable class could have any number of members. – John Glen Aug 27 '20 at 00:21
  • What if you need two lists? Or 100? The logical approach is to use multiple `Wrapper`, then we're back to just using `Collections.unmodifiableList()`. Anyway, this doesn't actually answer the question, which asks how to declare an immutable list of Strings that is a constant. – Bohemian Aug 27 '20 at 00:47
  • What if you wanted non list members in the wrapper? – John Glen Aug 27 '20 at 21:38