Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Protect ArrayList from write access

Tags:

java

Consider the following class:

public class Cars extends Observable{

    private ArrayList<String> carList = new ArrayList<String>();

    public void addToCarList(String car){
        // ...
        hasChanged();
        notifyObservers();
    }

    public void removeFromCarList(String car){
        // ...
        hasChanged();
        notifyObservers();
    }

    public ArrayList<String> getCarList() {
        return carList;
    }    
}

As you can see, every time the carList is changed, I want to notify the Observers. If someone does getCarList().add(...);, this is circumvented.

How can I give read access to the carList (for iterating over it etc.) but prevent write access to it except for the special methods addToCarList and removeFromCarList?

I thought about this:

public ArrayList<String> getCarList() {
    return (ArrayList<String>)carList.clone();
}

but someone using my class would, when adding something to the clone of carList, not be informed that that's not the way it's meant to be done.

like image 402
fweigl Avatar asked Jul 08 '14 08:07

fweigl


People also ask

How do you protect a list in Java?

use Collections. unmodifiableList(list) as it provides a new List object which cannot be modified , it would throw an UnsupportedOperationException while trying to update/add/delete objects list.

How do you make an array list thread safe?

A thread-safe variant of ArrayList in which all mutative operations (e.g., add, set, remove..) are implemented by creating a separate copy of an underlying array. It achieves thread safety by creating a separate copy of the List which is different than vector or other collections used to provide thread-safety.

Is array list thread safe?

Any method that touches the Vector 's contents is thread safe. ArrayList , on the other hand, is unsynchronized, making them, therefore, not thread safe. With that difference in mind, using synchronization will incur a performance hit. So if you don't need a thread-safe collection, use the ArrayList .

Which of the following is thread safe version of ArrayList class?

CopyOnWriteArrayList class – It is a thread-safe variant of ArrayList.

How to access ArrayList in Java?

There are two ways to access ArrayList in java, we can access the elements randomly and sequentially. As we know ArrayList maintains the insertion order by use of index value so we can get element by a particular index. Here is the table content of the article will we will cover this topic.

How to pass an ArrayList as an argument to a function?

If we want to pass an ArrayList as an argument to a function then we can easily do it using the syntax mentioned below. Example: ArrayList<Integer> list = new ArrayList<>(); modifyList(list); public static void modifyList(ArrayList<Integer> list){ list.add(69); list.add(98); }

How can I access the methods declared as protected?

The methods or data members declared as protected can be accessed from: Within the same class. Subclasses of same packages. Different classes of same packages. Subclasses of different packages. The access of various modifiers can be seen from the following table.

How to understand protected keyword in JavaScript?

Let’s understand protected keyword with the help of an example: Example: In this example, we will create two packages p1 and p2. Class A in p1 is made public, to access it in p2. The method display in class A is protected and class B is inherited from class A and this protected method is then accessed by creating an object of class B. Package p1


4 Answers

You can return an unmodifiable view of it, changing the return type to List<String> instead of ArrayList<String>:

public List<String> getCars() {
    return Collections.unmodifiableList(carList);
}

Note that as Collections.unmodifiableList does only provide a view, the caller will still see any other changes that are made via addToCarList and removeFromCarList (which I'd rename to addCar and removeCar, probably). Is that what you want?

Any mutating operations on the returned view will result in an UnsupportedOperationException.

like image 167
Jon Skeet Avatar answered Oct 24 '22 18:10

Jon Skeet


First, always avoid using concrete class at the left side of assignment and as a return value of method. So, fix your class as

public class Cars extends Observable{

    private List<String> carList = new ArrayList<String>();
    ........................

   public List<String> getCarList() {
        return carList;
   }
}    

Now you can use Collections.unmodifiableList() to make you list read-only:

   public List<String> getCarList() {
        return Collections.unmodifiableList(carList);
   }

BTW, if you do not really have to return List you can probably return Collection or even Iterable. This will make increase the encapsulation level of your code and make future modifications easier.

like image 13
AlexR Avatar answered Oct 24 '22 17:10

AlexR


Jon Skeet's answer is excellent (as always) but the one thing it doesn't touch on is concurrency issues.

Returning an unmodifiable collection will still leave you with issues if multiple threads are accessing this object at the same time. For example if one thread is iterating over the list of cars and then at the same time another thread adds a new card.

You will still need to synchronize access to that list somehow, and this is one reason why you might consider returning a clone() of the list as well as or instead of just wrapping it in the unmodifiableList wrapper. You would still need to synchronize around the clone() but once the clone is completed and the list returned to the querying code it no longer needs to be synchronized.

like image 9
Tim B Avatar answered Oct 24 '22 17:10

Tim B


I think you could probably make your Object implement the Collection-Interface, if it is in fact an ObservableList. It is a List and it should be Observable - so it should implement both interfaces.

You could even Extend List<..> because you just want to add extra functionality (observers) to the current functionality and your List can be used everywhere where a normal List could be used...

like image 2
Falco Avatar answered Oct 24 '22 17:10

Falco