Di Wu
Di Wu

Reputation: 6448

Way to make my code safe? - Private vs. Public

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

Answers (4)

mtmurdock
mtmurdock

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

gtiwari333
gtiwari333

Reputation: 25156

In your getMyPrivateArrayList () function do the following :

public List<SomeDataStructure> getMyPrivateArrayList(){
    return Collections.unmodifiableList(myPrivateArrayList);
}

Collections.unmodifiableList(someList) returns read-only list.


In your calling class if you try to modify the returned list, you will get error on runtime. eg.

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

Ken Wayne VanderLinde
Ken Wayne VanderLinde

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

ruakh
ruakh

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

Related Questions