Question

I'm trying to set a List unmodifiable.

In my code, I have a method which returns a list.

This list shouldn't be modified, but I don't want to catch the exception returned by the unmodifiableList.

private List<T> listeReferenceSelectAll = null;
List<T> oListeRet = new ArrayList<T>();
oListeRet = listeReferenceSelectAll;
return new ArrayList<T>(oListeRet);

It is an existing code and I have to transform it to return an unmodifiable list, but if an "add" method has been called, no exception has to be caught.

First I have create a class which implements List to override "add" method to log the exception and not to catch it.

But I don't know how to correctly instantiate it...

Was it helpful?

Solution 5

If you absolutely must do this, try to follow the contract specified by java.util.List in the list you are creating.

Your code would look something like

public class UnmodifiableArrayList<E>  extends ArrayList<E> {

    public UnmodifiableArrayList(Collection<? extends E> c) {
        super(c);
    }

    public boolean add(int index) {
        return false;//Returning false as the element cannot be added 
    }

    public boolean addAll(Collection<? extends E> c) {
        return false;//Returning false as the element cannot be added 
    }

    public E remove(int index) {
        return null;//Returning null as the element cannot be removed
    }
}

Add any more methods you need on the same lines. Just ensure that all the constructors and methods that might by used to modify in your code are overriden, so as to ensure the list is unmodifiable.

Using the Collections API is the cleaner and better way to do it, so use this way only if using Collections.UnmodifiableList does not satisfy your need.

And keep in mind this will be a nightmare while debugging so log as much as possible.

OTHER TIPS

You need java.util.Collections:

return Collections.unmodifiableList(oListeRet);

If you have to write your own, have that class implement the List interface and throw exceptions for the methods that modify contents.

Collections.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. Similarly, the returned list will implement RandomAccess if the specified list does.

Java-9 provides a new methods to create unmodifiable/immutable List:

jshell> List<Integer> list = List.of(1,2,3);
list ==> [1, 2, 3]

jshell> list.add(10);
|  java.lang.UnsupportedOperationException thrown: 
|        at ImmutableCollections.uoe (ImmutableCollections.java:70)
|        at ImmutableCollections$AbstractImmutableList.add (ImmutableCollections.java:76)
|        at (#6:1)

List.of creates an immutable list containing an arbitrary number of elements.

Although the accepted answer addresses the request of omitting / swallowing the UnsupportedOperationException, there should be an explanation of why it's an undesirable practice.

1) The overall intent to swallow an exception is a contradiction of the "fail-fast" principle. Instead of finding and catching defects early they are just allowed to go "under the carpet" turning into time bombs.

2) Not throwing UnsupportedOperationException is a direct violation of List's contract which says:

Throws:
    UnsupportedOperationException - if the add method is not supported by this list.

So the proper answer to what is written in the question's title: "Unmodifiable List in java" should still be:

return Collections.unmodifiableList(oListeRet);

1) These lines make no sense

List<T> oListeRet = new ArrayList<T>();
oListeRet = listeReferenceSelectAll;

2) Use Collections.unmodifiableList.

return Collections.unmodifiableList(oListeRet);

You dont need to catch exception it may throw, they are all UnsupportedOperationException - RuntimeExceptions

The comments about unmodifiable list are correct. Make a method accessor that calls Collections.unmodifiableList. However, you may want to just use an array like so, and use a list internally.

 public MyObject[] getObjects() {
    return (MyObject[]) mList.toArray();
 }
Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top