Protect ArrayList from write access - 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.

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.

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.

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.

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...

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.

Related

Avoid returning writable references

I have a submission to do for software development and my professor urges us to not use return statements, that return object references.
The task is about a to-do list application, and I wonder if there is any easy way to not implement the todo-list as a object with such writable return references.
I managed to do this but since I use JDBC its just writing my tasks to the DB and the re-loading it into my list from the DB, which for me sounds like the same as just writing it directly in the list.
I have the lecture again next Thursday and will ask then, but maybe some of you has a clue.
In my opinion its completely justifiable to return a reference to the list, especially since the application changes a lot in scenes and windows.
Edit: Code attached.
Since I have not yet implemented it here is how I would do it.
public class TaskList {
private static ArrayList<Task> taskList = new ArrayList<>();
public ArrayList<Task> getTaskList() {
return taskList;
}
}
Then I can get my TaskList in the different scenes like the calendar or overview by simply using the getter and modify the list.
Currently I have this code like that:
public class Calendar {
private ArrayList<Task> usersTasks = new ArrayList<>();
//Bunch of methods to draw my calendar
private createTask(){
Task createdTask = new Task(title,content,prio,color,duedate,today);
//write task in mySQL db
DatabaseHandler databaseHandler = new DatabaseHandler();
databaseHandler.createTask(createdTask,user);
}
private getTasks(){
usersTasks.clear();
//new dbHandler to fetch as ResultSet and write in ArrayList userTasks
}
}
I hope the snippets are explaining since I left a lot out. The example is for my calendar view.
So currently, when I create a task, I would write it in the DB, then clear my ArrayList and then re-fetch it.
no getters return writable references to members
Your professor is right.
Suppose you have a class SoccerTeam with a List<Person> members field with the team members in it, and a getter to get the team.
class SoccerTeam {
private List<Person> members;
public List<Person> getMembers() {
return members;
}
}
Now a caller wants so do something with all of the members, except the goalkeeper:
SoccerTeam team = ... // Get soccer team from somewhere
List<Person> members = team.getMembers();
members.remove(0); // Example where we agree that the goalkeeper is always element #0
doSomethingWithMembers(members);
Now the team lost its goalkeeper! A team with its members should not expose a mutable reference to the lists of members itself. We want to be able to provide a list with team members, without allowing some caller to modify the list of team members.
However,
not use return statements, that return object references
is a little bit poorly worded, since this would allow you to use primitives (or void) only.
A fix would be to return a fresh list with the members: a defensive copy:
public List<Person> getPersons() {
return new ArrayList<>(this.members);
}
Calling remove() on the list would not affect the members field of our team instance.
Alternatively, you could make an immutable (or more accurately: unmodifiable) list of members during construction of the team. Then the getter could just return the list, because it is guaranteed that the caller cannot modify the list. Trying to do so would result in an UnsupportedOperationException to be thrown.
public SoccerTeam(List<Person> members) {
this.members = Collections.unmodifiableList(members);
}
public List<Person> getMembers() {
return this.members;
}
A third option would be to return a Stream instead of a list. A Stream does not provide a way to modify the underlying source itself. (The elements contained in the source can, however.)
public Stream<Person> members() {
return this.members.stream();
}
This will postpone actual traversal until a terminal operation is called on the stream.

Access safety of getters in Java

So, we created a simple class with some private class member and automatically generated getter for it. But getter actually returned a reference to that member, resulting in gaining full access to a private member. Is that okay?
Here's the code of a class:
public class User {
private ArrayList<String> strings = new ArrayList(){ {
add("String1");
add("String2");
} };
public User() {
}
public ArrayList<String> getStrings() {
return strings;
}
public void setStrings(ArrayList<String> strings) {
this.strings = strings;
}
}
Code of main method:
public class Main {
public static void main(String[] args){
User user = new User();
System.out.println(user.getStrings());
user.getStrings().add("String3");
System.out.println(user.getStrings());
}
}
And output:
[String1, String2]
[String1, String2, String3]
I've changed the getter to this one:
public ArrayList<String> getStrings() {
return (ArrayList<String>)strings.clone();
}
But the question remains, what getters are for if not for safety? And what is the right way to write them?
No, it isn't okay because it breaks encapsulation and thus the class can't maintain its own invariants. Same with constructors.
But the problem isn't with getters/setters, it's with the code that autogenerates them.
To cut a long story short: don't use autogenerated accessors blindly, if they're dealing with mutable structures, make defensive copies (or immutable equivalents).
As an aside, I would not have a getter with an ArrayList return type, even if it's just a copy. It's usually none of the client's business what kind of list you're returning, so my getter would look like this:
public List<String> getStrings() {
return new ArrayList<>(strings);
}
Or using an immutable view:
public List<String> getStrings() {
return Collections.unmodifiableList(strings);
}
Or using Guava's ImmutableList class:
public List<String> getStrings() {
return ImmutableList.copyOf(strings);
}
There are subtle differences between the three solutions so which one's best may vary. As a general rule I prefer returning immutable structures because that makes it clear that changes made to the structure won't be reflected, i.e. user.getStrings().add( "X" ); will fail with an exception.
Another subtle problem with the code you showed us is the double braces initialisation. Imagine a class like this:
public class Foo {
private List<String> strings = new ArrayList() {{ add("bar");}};
private Object veryLargeField; //the object stored here consumes a lot of memory
public List<String> getStrings() {
return strings;
}
}
Now imagine we're doing this:
private class Bar {
private List<String> fooStrings;
public Bar() {
this.fooStrings = new Foo().getStrings();
}
}
How much memory would Bar consume (or to use the precise term: retain)? Well, it turns out that quite a lot, because what you do with the double brace initialisation is create an anonymous inner class, which will contain a reference to its outer class (Foo), and thus while the list returned is accessible, all the other fields of Foo will be ineligible for garbage collection.
From my point of view getters usually should serve two purposes:
first they should guard the implementation details.
second they should provide a way to extend easily (e.g. validation or instrumentation)
If your example violates these principles depends on the context:
If your class should own the strings then probably everyone should interact with the container object to modify the list and not with the list itself. To expose a collection (e.g. For processing in a method that expects a collection) you can use e.g. Collections.unmodifiableList(). If on the other hand the class only owns the list of strings then it is not an implementation detail to have a list.
Using a getter instead of directly accessing the fields allows you to easily add data conversation, tracing instrumentation and other things without changing all the places where the field is used.

Should I use an adapter class to share my arraylist?

I have an arraylist that I want normal users to only be able to GET information from and then I have an administrator account that I want to be able to do SET, SORT, and other methods to the arraylist. How do I share this array list with my administrator account and normal user accounts while also having different functionality to users depending on who they are. I came across the adapter class which if I understand correctly allows you to extend it and then only use the methods that you want to use and not have to override the other ones. Please let me know if this is correct. I don't have any code right now because I am still planning my project.
You can make a list readonly by using Collections.unmodifiableList()
You don't give much details in your question, but here is an example of how it could work. Assuming that you have an object that allows you to get a hold of an array based on a UserType enum:
public List<Object> getMyArray(UserType type) {
if (type == UserType.ADMIN) {
return _myList;
}
else {
return Collections.unmodifiableList(_myList);
}
}
You can return a Collections.unmodifiableList() for the underprivileged consumers.
Or, if you want to be really restrictive and expose only certain ArrayList methods then you could consider creating your own class that has an ArrayList within. You could further subclass this with the extra methods that you want to expose to privileged consumers.
Something like this:
public class MyList<T> {
ArrayList<T> arrayList;
public T get(int index) {
return arrayList.get(index);
}
}
public class MyModifiableList extends MyList<T> {
public boolean add(T object) {
return arrayList.add(object);
}
}
Your object would no longer be a List, so it would not be able to take advantage of good stuff like Collections.sort(list).

Unmodifiable Vector in Java

I need to manage data in my program where Java-Vector suits the purpose as it is synchronized,provides dynamic size and fast random access through index.
But I want to make my Vector Read Only for other Program Classes and Read Write for my own Class.
I read about Collections.unmodifiableList() ,but if I make my Vector unmodifiable, it will become read-only to my class as well.
How can I solve this problem?
I read about Collections.unmodifiableList(), but if I make my Vector unmodifiable, it will become read-only to my class as well.
I think you misunderstand what that method does. In reality, it creates an unmodifiable wrapper for the existing list, leaving the original list modifiable.
So the way to handle your requirement is to do something like this1:
private Vector<?> myVector = new Vector<?>();
private List<?> readOnly = Collections.Collections.unmodifiableList((myVector);
public List<?> getList() { return readOnly; }
Anything that has access to myVector can still add and remove elements from it. The changes will be visible via the readonly object ... but "change" operations on that object won't work.
(The other approach is to create copies of the original Vector object, but I'm pretty sure that doesn't meet your requirements.)
1 - Note that the readOnly object is a List but not a Vector. This shouldn't be a problem unless you have made the mistake of declaring the getter as returning a Vector. If you've done that, and you can't correct the mistake, then you will need to create your own subclass of Vector along the line of Evgeniy Dorofeev's answer. Otherwise Collections.unmodifiableList(...) will do just fine.
Make it a private member of your class and only provide getters that return an immutable version of the vector as a public way to access it, using the function you mentioned (Collections.unmodifiableList()).
If you really want an unmodifiable Vector (not just List) create a method as
public static Vector unmodifiableVector(Vector v) {
return new Vector(v) {
#Override
public void add(int index, Object element) {
throw new UnsupportedOperationException();
}
#Override
public synchronized boolean addAll(Collection c) {
#Override
public synchronized void addElement(Object obj) {
// ... other mutators
}
}
try this:
Collections.unmodifiableList(myList);
Make vector a private member of your class. expose a public method to the callers which will get a reference to an unmodifiableCollection.
public Vector getVector(){
return Collections.unmodifiableList(yourVector) ;
}
For use in your internal class, you can either reference the vector directly or create a private method which will return a reference to collection.
private Vector getMyVector(){
return yourVector ;
}
I think if you make your Vector as private member attribute in your along with all write methods as private while read methods as public, you would be OK e.g.
private Vector<T> myVector = ...
private void setMyVector(Vector<T> vector){
myVector = vector;
}
private void addElement(T element){
myVector.add(element);
}
public T getElement(int indx){
return myVector.get(indx);
}
....
....
By making the vector instance as private and providing setter as private with getter as public would be the correct path in my opinion.
For the :
List<T> readOnlyList = Collections.unmodifiableList(myList);
it will readnoly instance, however, it will still allow the access to other classes to call add/set/remove methods but calling these methods results in UnsupportedException being raised.
Also, based on your requirement, you are looking for the updation of the vector / addition of new elements in it. So may by look for concurrent package to make it safer in doing so.
Its better to give copy of your Vector rather than giving original reference of your Vector Like following:
Vector vector = // your vector object in your class
public Vector<String> getMyVercorObject(){
return (Vector<String>)vector.clone() ;
}
The best way is to use Vector internally, only expose mutations (add, remove, etc) using methods, and only return an unmodifiable view using an interface (List). Such an implementation might look like this (for example sake let's say the elements are strings):
private final List<String> list = new Vector<String>();
/** Adds the specified element. */
public void addElement(String element) {
list.add(element);
}
/** Replaces all elements. */
public void setElements(List<String> newElements) {
list.clear();
list.addAll(newElements);
}
/** Returns all elements. */
public List<String> getElement() {
return Collections.unmodifiableList(list);
}
In this way your class has full access to the list, while external entities can only mutate using the public methods.
Note that Vector is pretty much not used. If you require a thread safe list then consider ArrayList in conjunction with synchronizedList:
private final List<String> list = Collections.synchronizedList(new ArrayList<String>());

Should I extend ArrayList to add attributes that isn't null?

I would like to add a collection of objects to an arrayList ,only if the particular attribute is not null.
I am thinking of extending the ArrayList and implementing the check inside the child class.
One alternate way is to check for the the attribute before putting it in a Arraylist, but that would mean , i will have to scatter the if checks every where if i need to add the objects to the arraylist based on the logic.
I would like to know your thoughts on it ... on a second thought is it a overkill ?
Decorator pattern
I would actually recommend wrapping ArrayList using well-documented Decorator pattern. You simply wrap your ArrayList with another List implementation that delegates most of the methods but adds validation logic:
public class ValidatingListDecorator extends AbstractList<MyBusinessObject>
{
private final List<MyBusinessObject> target;
public ValidatingListDecorator(List<MyBusinessObject> target) {
this.target = target;
}
#Override
public MyBusinessObject set(int index, MyBusinessObject element)
{
validate(element);
return target.set(index, element);
}
#Override
public boolean add(MyBusinessObject o)
{
validate(o);
return target.add(o);
}
//few more to implement
}
Advantages:
You can still access raw list without validation if you want (but you can restrict this)
Easier to stack different validations, turn them on and off selectively.
Promotes composition over inheritance as noted by #helios
Improves testability
Does not tie you to a specific List implementation, you can add validation to LinkedList or Hibernate-backed persistent lists. You can even think about generic Collection decorator to validate any collection.
Implementation notes
Despite the implementation remember there are quite a lot of methods you have to remember about while overriding: add(), addAll(), set(), subList() (?), etc.
Also your object must be immutable, otherwise the user can add/set valid object and modify it afterwards to violate the contract.
Good OO design
Finaly I wrote:
validate(element)
but consider:
element.validate()
which is a better design.
Stacking validations
As noted before if you want to stack validations, validating each proprty/apsect in a single, separate class, consider the following idiom:
public abstract class ValidatingListDecorator extends AbstractList<MyBusinessObject>
{
private final List<MyBusinessObject> target;
public ValidatingListDecorator(List<MyBusinessObject> target) {
this.target = target;
}
#Override
public MyBusinessObject set(int index, MyBusinessObject element)
{
validate(element);
return target.set(index, element);
}
protected abstract void validate(MyBusinessObject element);
}
...and few implementations:
class FooValidatingDecorator extends ValidatingListDecorator {
public FooValidatingDecorator(List<MyBusinessObject> target)
{
super(target);
}
#Override
protected void validate(MyBusinessObject element)
{
//throw if "foo" not met
}
}
class BarValidatingDecorator extends ValidatingListDecorator {
public BarValidatingDecorator(List<MyBusinessObject> target)
{
super(target);
}
#Override
protected void validate(MyBusinessObject element)
{
//throw if "bar" not met
}
}
Want to only validate foo?
List<MyBusinessObject> list = new FooValidatingDecorator(rawArrayList);
Want to validate both foo and bar?
List<MyBusinessObject> list =
new BarValidatingDecorator(new FooValidatingDecorator(rawArrayList));
If you would like to enforce this I don't see why not (although you should check the return value of the add method whenever you do add to make sure that it succeeded).
This is a good way to get rid of that redundant logic which may or may not stick around in later software iterations.
I don't think this is a good practice. Consider instead writing a Util-Method in a Util-Class taking two parameters: The array list and the object you would like to add. There you can check whatever you want and can reuse the logic all over your code.
Only issue would be if you go to reuse this code and you don't remember you've overriden the ArrayList class, make sure to comment thoroughly.

Categories