Avoid returning writable references - java

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.

Related

Best practice for getters and setters for collection properties and object properties in a java class

i have the following implementation
public class PartGroup {
private Part iPart;
private ArrayList<Part> iParttList;
public Part getPart() {
return iPart;
}
public void setPart( Part aPart ) {
iPart = aPart;
}
public ArrayList<Part> getParttList() {
return iParttList;
}
public void setParttList( ArrayList<Part> aParttList ) {
iParttList = aParttList;
}
}
Is it ok to have setters for iParttList and iPart ?
i think it is safe to have a getter only then the consumer can use getter to get the created instance of the collection and clear or add elements to the collection
should i remove the setter and add the following implementation
public ArrayList<Part> getParttList() {
if(iParttList == null)
iParttList = new ArrayList<Part>();
return iParttList;
}
public Part getPart() {
if(iPart == null)
iPart = new Part();
return iPart;
}
What is the best practice?
The second implementation guards against returning null, right? So if there's a chance this object could return null (because what constructors there are permit this or it otherwise could come to pass) and that would be a Bad Thing for your intended use case, then use the second implementation.
Your original implementation seems like the standard implementation for getters and setters. Why do you think you'd need to rearrange it to the second code block?
As we see you do not have construction to create list once you create instance of PartGroup.
I think:
If you have construction to create list of Part objects, and if you want to restrict consumer to change or create list via setter, then I think it is better not to have setter
But, if you dont have constructor to create list of Part objects, then setter is only way to create list of Part objects.
The second implementation seems better from my point of view. It ensures that the lists aren't null under any circumstances. It also helps to reduce duplicate code that checks if the list is empty or not. Finally, callingpublic void setParttList( ArrayList<Part> aParttList ) may be risky since it may set a new list even though there's one already exist.

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.

Protect ArrayList from write access

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.

Condition for creating a immutable class?

To make a immutable class , Effective Java has one last condition.
To make a class immutable, follow these five rules:
5- Ensure exclusive access to any mutable components. If your class has any fields that refer to mutable objects, ensure that clients of the class cannot obtain references to these objects. Never initialize such a field to a client-provided object reference nor return the object reference from an accessor. Make defensive copies (Item 24) in contructors, accessors, and readObject methods
public final class ImmutableClass {
private MutableObject mutableObject;
// If I should not provide getter for this object. Then what is the use of this variable after I have
//initalised in the constructor
}
Can somebody explain me this point?
It's actually reasonably simple.
Basically, it's saying to not...
1- Make available any reference to any mutable object that your object might contain.
So if your Class contained a java.util.List as one of it's fields, there should be no way for any client using your Class to gain a reference directly to the List field, either via public deceleration or getter of some kind.
For example...
public class BadImmutableExample {
public List<String> myStrings; // This can not be referenced by the client
/*...*/
}
Would be bad, because the field myStrings is accessible to any body to make modifications to...
In the case you had to return the values in the List you would either be required to return a copy of the List (not a reference to it) or return an array of the values, for example.
For example...
public class BadImmutableExample {
private List<String> myStrings; // This can not be referenced by the client
/*...*/
public List<String> getMyStrings() {
return myStrings;
}
}
Would expose the List myStrings to any clients, which would allow them to modify it.
In this case, you could also use Collections.unmodifiableList(myStrings) to make the list unmodifiable, or return new ArrayList<String>(myStrings) or return an array of String instead...
2- Never initialise such a field to a client provided object...
Basically this means that if your Class requires the client to seed it with some kind of value or values, you should never maintain a reference directly them, instead, again, make a copy for you own reference...
For example...
public class BadImmutableExample {
private List<String> myStrings; // This can not be referenced by the client
public ImmutableExample(List<String> clientStrings) {
myStrings = clientStrings;
}
}
Would break this rule, as any changes to clientStrings would be immediately reflected within you class.
Instead, you could do something like...
public class BetterImmutableExample {
private List<String> myStrings; // This can not be referenced by the client
public ImmutableExample(List<String> clientStrings) {
myStrings = new ArrayList<String>(clientStrings);
}
}
Instead, which will make a copy of the client supplied list, but which will no longer reflect changes made to it (the client supplied 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>());

Categories