1

I have a method:

public List getDocuments(Long orgClientId, long userId) {

    // do stuff
    List list = new ArrayList();
    // do stuff to fill the list. The list will be of hashmaps.

    return list;
}

I don't want my list to be modified outside this method. How should I return it then? Cloning it? Or just returning a new instance like

return new ArrayList<>(list);

would do it?

Akeshwar Jha
  • 4,516
  • 8
  • 52
  • 91
  • [cloning shouldn´t be used in java](http://stackoverflow.com/questions/2427883/clone-vs-copy-constructor-which-is-recommended-in-java), so you are fine if you return a new `ArrayList` – SomeJavaGuy Oct 12 '15 at 08:59
  • 1
    Please don't use raw types: use `List>`, probably with more specific type bounds on the key and value types. – Andy Turner Oct 12 '15 at 09:17

2 Answers2

11

You can make it superficially unmodifiable thus:

return Collections.unmodifiableList(list)

This wraps the list in order that invoking any of the mutation methods will result in an exception.

However, does it really matter to you if somebody modifies the list? You are giving back a new list instance each time this method is invoked, so there is no issue with two callers getting the same instance and having to deal with interactions between the mutations.

Whatever step you take to attempt to make it unmodifiable, I can just copy the list into a modifiable container myself.

It's also quite inconvenient to me as a caller if you give me back something which I can't detect whether it is mutable or not - it looks like a List; the only way to see if I can mutate it is by calling a mutation method. That's a runtime failure, which makes it a PITA.


Update, to add an alternative.

An alternative to Collections.unmodifiableList is something like Guava's ImmutableList: this will likely be faster than Collections.unmodifiableList since it does not simply provide an unmodifiable view of existing list by wrapping, but rather provides a custom implementation of List which forbids mutation (there is less indirection).

The advantage of this is that you can return ImmutableList rather than just the List returned by Collections.unmodifiableList: this allows you to give the caller a bit more type information that they can't mutate it. ImmutableList (and its siblings like ImmutableSet) mark the mutation methods @Deprecated so your IDE can warn you that you might be doing something iffy.

The caller might choose to disregard that information (they assign the result to a List, rather than an ImmutableList), but that's their choice.

Andy Turner
  • 137,514
  • 11
  • 162
  • 243
  • suppose I call the method `getDocuments` and get the value of the list assigned to a new list called newList. Now if I modify the old list just by, say, `list.add()` this newList also changes - which I don't want. So, it does matter if someone modifies the list. Also, by using unmodifiableList, I guess I will also have to add exception handlers at places, right? – Akeshwar Jha Oct 12 '15 at 09:23
  • 1
    That's not what the code in your question does, though, and it isn't what your question describes. If you have specific requirements, you need to state them, so that these can be taken into account in giving an answer. – Andy Turner Oct 12 '15 at 09:27
1

The idea is that the object returned by umodifiableCollection can't directly be changed, but could change through other means (effectively by changing the internal collection directly).

List<String> list = new ArrayList<String>();
list.add("One");
list.add("Two");
list.add("Three");
List<String> unmodifiableList = Collections.unmodifiableList(list);

   // this doesn't throw an exception since it's using the add
   // method of the original List reference, which is no problem
list.add("Four");
System.out.println(unmodifiableList);

  // this, however, throws an exception
unmodifiableList.add("Five");

unmodifiableList returns an unmodifiable view of the specified list. This method allows modules to provide users with "read-only" access to internal lists. Query operations on the returned list "read through" to the specified list, and attempts to modify the returned list, whether direct or via its iterator, result in an UnsupportedOperationException. The returned list will be serializable if the specified list is serializable.

Shiladittya Chakraborty
  • 4,270
  • 8
  • 45
  • 94