Reputation: 6448
An instance of Class A has a private ArrayList. The instance is responsible for maintaining data stored in the arrayList.
private ArrayList<SomeDataStructure> myPrivateArrayList;
However, when other module ask for the data, this instance of Class A will have to pass the data the whoever asks for it, therefore, there is public function in Class A:
public ArrayList<SomeDataStructure> getMyPrivateArrayList ();
My question, how should I implement this function so that I could guarantee that those who get the arrayList through this public function won't be able to modify it (i.e., the return value is read-only)?
Thanks in advance!
Upvotes: 4
Views: 145
Reputation: 13062
Do you need to get the list? Or can you simply forward some accessors to the list? You could define some public functions like get(index)
which simply call the equivalent methods on your list and return the result. This is most likely what you want to do because it gives people access only to the methods you choose, and you dont have to give them the list itself or waste CPU cycles copying the data into "read-only" structures.
Upvotes: 0
Reputation: 25156
In your getMyPrivateArrayList ()
function do the following :
public List<SomeDataStructure> getMyPrivateArrayList(){
return Collections.unmodifiableList(myPrivateArrayList);
}
Collections.unmodifiableList(someList)
returns read-only list.
If you do the following
List<SomeDataStructure> readOnlyList=getMyPrivateArrayList();
readOnlyList.add(new SomeDataStructure());
You'll get following error :
Exception in thread "main" java.lang.UnsupportedOperationException
at java.util.Collections$UnmodifiableList.add(Collections.java:1160)
at MainClass.main(MainClass.java:14)
Upvotes: 0
Reputation: 19349
I would suggest doing this instead (if you're allowed to in your situation):
private ArrayList<SomeDataStructure> myPrivateArrayList;
public List<SomeDataStructure> getMyPrivateList () {
return Collections.unmodifiableList(myPrivateArrayList)
}
Note that the exposed data structure is of type List
instead of ArrayList
. I think (generally speaking) the public interface of a class should not return concrete types, but rather should return interfaces. It simplifies tasks such as this one, and also reduces the amount of dependancy that one class has on the implementation of another class.
Upvotes: 6
Reputation: 183321
Instead of return-type ArrayList<SomeDataStructure>
, use List<SomeDataStructure>
. Then you can use the java.util.Collections.unmodifiableList(...)
utility-method to create a read-only view of your list:
public List<SomeDataStructure> getMyPrivateArrayList()
{
return Collections.unmodifiableList(myPrivateArrayList);
}
Another option is to return a copy of your list:
public ArrayList<SomeDataStructure> getMyPrivateArrayList()
{
return new ArrayList<SomeDataStructure>(myPrivateArrayList);
}
(There are some other options as well, but those are the most common approaches.)
But keep in mind that, if SomeDataStructure
is mutable, then callers of either of the above can still mutate any of the objects in your list. (That is, they can do something like obj.getMyPrivateArrayList().get(0).setProp(null)
.)
Upvotes: 0