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.
Related
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.
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)
I have a question about using getter methods in java.
Suppose I had this class:
class Test {
private ArrayList<String> array = new ArrayList<String>();
public ArrayList getArray() {
return this.array;
}
public void initArray() {
array.add("Test 1");
array.add("Test 2");
}
}
class Start {
public static void main(String args[]) {
initArray();
getArray().remove(0);
}
}
My question is:
Would the actual arraylist object be modified ("Test 1" removed from it)? I think I have seen this in places, but I thought that getters were simply providing a copy of that object. Not a reference to it. If it did work that way (as a reference), then would this work as well (Would the arraylist object of the class Test be altered by this as well)?:
class Start {
public static void main(String args[]) {
initArray();
ArrayList aVar = getArray();
aVar.remove(0);
}
}
Java returns references to the Array, so it won't be a copy and it will modify the List. In general, unless its a primitive type (int,float,etc) you will be getting a reference to the object.
You have to explicitly copy the array yourself if you want a duplicate to be returned.
The way I understand it, Object reference variables are little more than memory addresses of the objects themselves. So what is returned from getArray() is a reference variable to that ArrayList. An object may have many reference variables, but it is still the same object that gets modified.
Java does everything pass by value. So anytime you pass an object reference variable as a parameter or return it's value, you are passing or returning the value of the object reference variable.
As others said, unless it's a primitive type, you get a reference to the object. It is similar to a pointer in C++, it allows you to access the object, but unlike C++ reference (pointer to the memory address of a variable) it doesn't allow you to replace it with another object. Only setter can do that.
I see two variants in your question, test.getArray().remove(0) and aVar.remove(0). There is no difference in the results of those, it's still just some pointer-like reference and it modifies the original.
You never get a clone by just calling a getter, so unless the object is immutable, you can modify the object that the getter gave you access to. For example, String is immutable, any basic Collection (including ArrayList) is mutable. You can call Collections.unmodifiable*(...) to make a collection unmodifiable. However, if the items of collection are mutable, they can still be changed.
In some cases, getting a clone is a good idea, in most cases it's not. A getter shouldn't clone anything at all, it shouldn't even modify data unless it initializes a possibly null collection or something like that. If you want an unmodifiable collection containing immutable objects, try to do it this way. In this example we have a class FooImpl that implements interface Foo, the reasons to be explained later.
public interface Foo {
int getBar();
}
public class FooImpl Foo {
private int bar;
#Override
public int getBar() {
return bar;
}
public void setBar(int newValue) {
this.bar = newValue;
}
}
As you see, Foo has no setter. If you create some ArrayList<Foo> and pass it from some getter as Collections.unmodifiableList(myArrayList), it almost seems you did it. But the work is not done yet. If the class FooImpl is public (which it is in this case), someone might try if that foo he found in the list is an instanceof FooImpl and then cast it as (FooImpl) foo making it mutable. However, we can wrap any Foo into a wrapper called FooWrapper. It implements Foo as well:
public class FooWrapper implements Foo {
private Foo foo;
public FooWrapper(Foo foo) {
this.foo = foo;
}
public int getBar() {
return foo.getBar();
}
// No setter included.
}
Then we can put a new FooWrapper(myFoo) into a Collection<FooWrapper>. This wrapper doesn't have any public setter and the foo inside is private. You cannot modify the underlying data. Now about that Foo interface. Both FooImpl and FooWrapper implement it, if any method doesn't intend to modify the data, it can ask for Foo on input. It doesn't matter which Foo you get.
So, if you want unmodifiable collection containing unmodifiable data, make a new Collection<Foo>, feed it with FooWrapper objects and then call Collections.unmodifiable*(theCollection). Or make a custom collection that wraps the whole collection of Foo, returning FooWrappers, for example this list:
public MyUnmodifiableArrayList implements List<Foo> {
ArrayList<Foo> innerList;
public get(int index) {
Foo result = innerList.get(index);
if (!(result instanceof FooWrapper)) {
return new FooWrapper(result);
}
return result; // already wrapped
}
// ... some more List interface's methods to be implemented
}
With wrapped collection, you don't have to iterate through the original collection and make its clone with wrappers of data. This solution is much better when you don't read it whole, but it creates a new FooWrapper every time you call get() on it, unless the Foo on that index is already a FooWrapper. In a long running thread with millions of calls to get(), this could become an unnecessary benchmark for the garbage collector, making you use some inner array or map containing already existing FooWrappers.
Now you can return the new, custom List<Foo>. But again, not from a plain getter. Make it something like getUnmodifiableFooList() for your private ArrayList<FooImpl> fooList field.
As pointed out, your getter does not modify the list, it returns an modifiable reference to the list. Tools like Findbugs will warn you about that... you may either live with that and trust the users of your class to not clobber your list, or use this to return an unmodifiable reference to your list:
public static List<String> getArray() {
return Collections.unmodifiableList(array);
}
To answer your question, with a getter you get direct access to a variable.
Run this code and you can see that the String in the ArrayList is removed. But don't use a static ArraList like in this example in your code.
public class Test {
private static ArrayList<String> array = new ArrayList<String>();
public static ArrayList<String> getArray() {
return array;
}
public static void initArray() {
array.add("Test 1");
array.add("Test 2");
}
public static void main(String[] args) {
initArray();
ArrayList aVar = getArray();
aVar.remove(0);
System.out.println(aVar.size());
}
}
That a getter does not modify the object you call it upon is purely a matter of convention. It certainly does not change the target's identity, but it can change its internal state. Here's a useful example, if a bit sketchy:
public class Fibonacci {
private static ConcurrentMap<Integer, BigInteger> cache =
new ConcurrentHashMap<>();
public BigInteger fibonacci(int i) {
if (cache.containsKey(i)) {
return cache.get(i);
} else {
BigInteger fib = compute(i); // not included here.
cache.putIfAbsent(i, fib);
return fib;
}
}
So, calling Fibonacci.fibonacci(1000) may change the internal state of the target, but it's still the same target.
Now, here's a possible security violation:
public class DateRange {
private Date start;
private Date end;
public DateRange(final Date start, final Date end) {
if (start.after(end)) {
throw new IllegalArgumentException("Range out of order");
}
this.start = start;
this.end = end;
}
public Date getStart() {
return start;
}
// similar for setStart, getEnd, setEnd.
}
The problem is that java.lang.Date is mutable. Someone can write code like:
DateRange range = new DateRange(today, tomorrow);
// In another routine.
Date start = range.getStart();
start.setYear(2088); // Deprecated, I know. So?
Now range is out of order. It's like handing the cashier your wallet.
This is why it is best to do one of these, the earlier ones being preferable.
Have as many objects as possible be immutable. This is why Joda-Time was written, and why dates will chnage yet again in Java 8.
Make defensive copies of items one sets or gets.
Return an immutable wrapper of an item.
Return collections as iterables, not as themselves. Of course, someone might cast it back.
Return a proxy to access the item, that can't be cast to its type.
I know, I know. if I want C or C++, I know where to find them.
1. Return
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>());
How to create immutable objects in Java?
Which objects should be called immutable?
If I have class with all static members is it immutable?
Below are the hard requirements of an immutable object.
Make the class final
make all members final, set them
explicitly, in a static block, or in the constructor
Make all members private
No Methods that modify state
Be extremely careful to limit access to mutable members(remember the field may be final but the object can still be mutable. ie private final Date imStillMutable). You should make defensive copies in these cases.
The reasoning behind making the class final is very subtle and often overlooked. If its not final people can freely extend your class, override public or protected behavior, add mutable properties, then supply their subclass as a substitute. By declaring the class final you can ensure this won't happen.
To see the problem in action consider the example below:
public class MyApp{
/**
* #param args
*/
public static void main(String[] args){
System.out.println("Hello World!");
OhNoMutable mutable = new OhNoMutable(1, 2);
ImSoImmutable immutable = mutable;
/*
* Ahhhh Prints out 3 just like I always wanted
* and I can rely on this super immutable class
* never changing. So its thread safe and perfect
*/
System.out.println(immutable.add());
/* Some sneak programmer changes a mutable field on the subclass */
mutable.field3=4;
/*
* Ahhh let me just print my immutable
* reference again because I can trust it
* so much.
*
*/
System.out.println(immutable.add());
/* Why is this buggy piece of crap printing 7 and not 3
It couldn't have changed its IMMUTABLE!!!!
*/
}
}
/* This class adheres to all the principles of
* good immutable classes. All the members are private final
* the add() method doesn't modify any state. This class is
* just a thing of beauty. Its only missing one thing
* I didn't declare the class final. Let the chaos ensue
*/
public class ImSoImmutable{
private final int field1;
private final int field2;
public ImSoImmutable(int field1, int field2){
this.field1 = field1;
this.field2 = field2;
}
public int add(){
return field1+field2;
}
}
/*
This class is the problem. The problem is the
overridden method add(). Because it uses a mutable
member it means that I can't guarantee that all instances
of ImSoImmutable are actually immutable.
*/
public class OhNoMutable extends ImSoImmutable{
public int field3 = 0;
public OhNoMutable(int field1, int field2){
super(field1, field2);
}
public int add(){
return super.add()+field3;
}
}
In practice it is very common to encounter the above problem in Dependency Injection environments. You are not explicitly instantiating things and the super class reference you are given may actually be a subclass.
The take away is that to make hard guarantees about immutability you have to mark the class as final. This is covered in depth in Joshua Bloch's Effective Java and referenced explicitly in the specification for the Java memory model.
Just don't add public mutator (setter) methods to the class.
Classes are not immutable, objects are.
Immutable means: my public visible state cannot change after initialization.
Fields do not have to be declared final, though it can help tremendously to ensure thread safety
If you class has only static members, then objects of this class are immutable, because you cannot change the state of that object ( you probably cannot create it either :) )
To make a class immutable in Java , you can keep note of the following points :
1. Do not provide setter methods to modify values of any of the instance variables of the class.
2. Declare the class as 'final' . This would prevent any other class from extending it and hence from overriding any method from it which could modify instance variable values.
3. Declare the instance variables as private and final.
4. You can also declare the constructor of the class as private and add a factory method to create an instance of the class when required.
These points should help!!
From oracle site, how to create immutable objects in Java.
Don't provide "setter" methods — methods that modify fields or objects referred to by fields.
Make all fields final and private.
Don't allow subclasses to override methods. The simplest way to do this is to declare the class as final. A more sophisticated approach is to make the constructor private and construct instances in factory methods.
If the instance fields include references to mutable objects, don't allow those objects to be changed:
I. Don't provide methods that modify the mutable objects.
II. Don't share references to the mutable objects. Never store references to external, mutable objects passed to the constructor; if necessary, create copies, and store references to the copies. Similarly, create copies of your internal mutable objects when necessary to avoid returning the originals in your methods.
An immutable object is an object that will not change its internal state after creation. They are very useful in multithreaded applications because they can be shared between threads without synchronization.
To create an immutable object you need to follow some simple rules:
1. Don't add any setter method
If you are building an immutable object its internal state will never change. Task of a setter method is to change the internal value of a field, so you can't add it.
2. Declare all fields final and private
A private field is not visible from outside the class so no manual changes can't be applied to it.
Declaring a field final will guarantee that if it references a primitive value the value will never change if it references an object the reference can't be changed. This is not enough to ensure that an object with only private final fields is not mutable.
3. If a field is a mutable object create defensive copies of it for
getter methods
We have seen before that defining a field final and private is not enough because it is possible to change its internal state. To solve this problem we need to create a defensive copy of that field and return that field every time it is requested.
4. If a mutable object passed to the constructor must be assigned to a
field create a defensive copy of it
The same problem happens if you hold a reference passed to the constructor because it is possible to change it. So holding a reference to an object passed to the constructor can create mutable objects. To solve this problem it is necessary to create a defensive copy of the parameter if they are mutable objects.
Note that if a field is a reference to an immutable object is not necessary to create defensive copies of it in the constructor and in the getter methods it is enough to define the field as final and private.
5. Don't allow subclasses to override methods
If a subclass override a method it can return the original value of a mutable field instead of a defensive copy of it.
To solve this problem it is possible to do one of the following:
Declare the immutable class as final so it can't be extended
Declare all methods of the immutable class final so they can't be overriden
Create a private constructor and a factory to create instances of the immutable class because a class with private constructors can't be extended
If you follow those simple rules you can freely share your immutable objects between threads because they are thread safe!
Below are few notable points:
Immutable objects do indeed make life simpler in many cases. They are especially applicable for value types, where objects don't have an identity so they can be easily replaced and they can make concurrent programming way safer and cleaner (most of the notoriously hard to find concurrency bugs are ultimately caused by mutable state shared between threads).
However, for large and/or complex objects, creating a new copy of the object for every single change can be very costly and/or tedious. And for objects with a distinct identity, changing an existing objects is much more simple and intuitive than creating a new, modified copy of it.
There are some things you simply can't do with immutable objects, like have bidirectional relationships. Once you set an association value on one object, it's identity changes. So, you set the new value on the other object and it changes as well. The problem is the first object's reference is no longer valid, because a new instance has been created to represent the object with the reference. Continuing this would just result in infinite regressions.
To implement a binary search tree, you have to return a new tree every time: Your new tree will have had to make a copy of each node that has been modified (the un-modified branches are shared). For your insert function this isn't too bad, but for me, things got fairly inefficient quickly when I started to work on delete and re-balance.
Hibernate and JPA essentially dictate that your system uses mutable objects, because the whole premise of them is that they detect and save changes to your data objects.
Depending on the language a compiler can make a bunch of optimizations when dealing with immutable data because it knows the data will never change. All sorts of stuff is skipped over, which gives you tremendous performance benefits.
If you look at other known JVM languages (Scala, Clojure), mutable objects are seen rarely in the code and that's why people start using them in scenarios where single threading is not enough.
There's no right or wrong, it just depends what you prefer. It just depends on your preference, and on what you want to achieve (and being able to easily use both approaches without alienating die-hard fans of one side or another is a holy grail some languages are seeking after).
Don't provide "setter" methods — methods that modify fields or
objects referred to by fields.
Make all fields final and private.
Don't allow subclasses to override methods. The simplest way to do this is to declare the class as final. A more sophisticated approach is to make the constructor private and construct instances in factory methods.
If the instance fields include references to mutable objects, don't allow those objects to be changed:
Don't provide methods that modify the mutable objects.
Don't share references to the mutable objects. Never store references to external, mutable objects passed to the constructor; if necessary, create copies, and store references to the copies. Similarly, create copies of your internal mutable objects when necessary to avoid returning the originals in your methods.
First of all, you know why you need to create immutable object, and what are the advantages of immutable object.
Advantages of an Immutable object
Concurrency and multithreading
It automatically Thread-safe so synchronization issue....etc
Don't need to copy constructor
Don't need to implementation of clone.
Class cannot be override
Make the field as a private and final
Force callers to construct an object completely in a single step, instead of using a no-Argument constructor
Immutable objects are simply objects whose state means object's data can't change after the
immutable object are constructed.
please see the below code.
public final class ImmutableReminder{
private final Date remindingDate;
public ImmutableReminder (Date remindingDate) {
if(remindingDate.getTime() < System.currentTimeMillis()){
throw new IllegalArgumentException("Can not set reminder" +
" for past time: " + remindingDate);
}
this.remindingDate = new Date(remindingDate.getTime());
}
public Date getRemindingDate() {
return (Date) remindingDate.clone();
}
}
Minimize mutability
An immutable class is simply a class whose instances cannot be modified. All of the information contained in each instance is provided when it is created and is fixed for the lifetime of the object.
JDK immutable classes: String, the boxed primitive classes(wrapper classes), BigInteger and BigDecimal etc.
How to make a class immutable?
Don’t provide any methods that modify the object’s state (known as mutators).
Ensure that the class can’t be extended.
Make all fields final.
Make all fields private.
This prevents clients from obtaining access to mutable objects referred to by fields and modifying these objects directly.
Make defensive copies.
Ensure exclusive access to any mutable components.
public List getList() {
return Collections.unmodifiableList(list); <=== defensive copy of the mutable
field before returning it to caller
}
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 or return the object reference from an accessor.
import java.util.Date;
public final class ImmutableClass {
public ImmutableClass(int id, String name, Date doj) {
this.id = id;
this.name = name;
this.doj = doj;
}
private final int id;
private final String name;
private final Date doj;
public int getId() {
return id;
}
public String getName() {
return name;
}
/**
* Date class is mutable so we need a little care here.
* We should not return the reference of original instance variable.
* Instead a new Date object, with content copied to it, should be returned.
* */
public Date getDoj() {
return new Date(doj.getTime()); // For mutable fields
}
}
import java.util.Date;
public class TestImmutable {
public static void main(String[] args) {
String name = "raj";
int id = 1;
Date doj = new Date();
ImmutableClass class1 = new ImmutableClass(id, name, doj);
ImmutableClass class2 = new ImmutableClass(id, name, doj);
// every time will get a new reference for same object. Modification in reference will not affect the immutability because it is temporary reference.
Date date = class1.getDoj();
date.setTime(date.getTime()+122435);
System.out.println(class1.getDoj()==class2.getDoj());
}
}
For more information, see my blog:
http://javaexplorer03.blogspot.in/2015/07/minimize-mutability.html
an object is called immutable if its state can not be changed once created. One of the most simple way of creating immutable class in Java is by setting all of it’s fields are final.If you need to write immutable class which includes mutable classes like "java.util.Date". In order to preserve immutability in such cases, its advised to return copy of original object,
Immutable Objects are those objects whose state can not be changed once they are created, for example the String class is an immutable class. Immutable objects can not be modified so they are also thread safe in concurrent execution.
Features of immutable classes:
simple to construct
automatically thread safe
good candidate for Map keys and Set as their internal state would not change while processing
don't need implementation of clone as they always represent same state
Keys to write immutable class:
make sure class can not be overridden
make all member variable private & final
do not give their setter methods
object reference should not be leaked during construction phase
The following few steps must be considered, when you want any class as an immutable class.
Class should be marked as final
All fields must be private and final
Replace setters with constructor(for assigning a value to a
variable).
Lets have a glance what we have typed above:
//ImmutableClass
package younus.attari;
public final class ImmutableExample {
private final String name;
private final String address;
public ImmutableExample(String name,String address){
this.name=name;
this.address=address;
}
public String getName() {
return name;
}
public String getAddress() {
return address;
}
}
//MainClass from where an ImmutableClass will be called
package younus.attari;
public class MainClass {
public static void main(String[] args) {
ImmutableExample example=new ImmutableExample("Muhammed", "Hyderabad");
System.out.println(example.getName());
}
}
Commonly ignored but important properties on immutable objects
Adding over to the answer provided by #nsfyn55, the following aspects also need to be considered for object immutability, which are of prime importance
Consider the following classes:
public final class ImmutableClass {
private final MutableClass mc;
public ImmutableClass(MutableClass mc) {
this.mc = mc;
}
public MutableClass getMutClass() {
return this.mc;
}
}
public class MutableClass {
private String name;
public String getName() {
return this.name;
}
public void setName(String name) {
this.name = name;
}
}
public class MutabilityCheck {
public static void main(String[] args) {
MutableClass mc = new MutableClass();
mc.setName("Foo");
ImmutableClass iMC = new ImmutableClass(mc);
System.out.println(iMC.getMutClass().getName());
mc.setName("Bar");
System.out.println(iMC.getMutClass().getName());
}
}
Following will be the output from MutabilityCheck :
Foo
Bar
It is important to note that,
Constructing mutable objects on an immutable object ( through the constructor ), either by 'copying' or 'cloing' to instance variables of the immutable described by the following changes:
public final class ImmutableClass {
private final MutableClass mc;
public ImmutableClass(MutableClass mc) {
this.mc = new MutableClass(mc);
}
public MutableClass getMutClass() {
return this.mc;
}
}
public class MutableClass {
private String name;
public MutableClass() {
}
//copy constructor
public MutableClass(MutableClass mc) {
this.name = mc.getName();
}
public String getName() {
return this.name;
}
public void setName(String name) {
this.name = name;
}
}
still does not ensure complete immutability since the following is still valid from the class MutabilityCheck:
iMC.getMutClass().setName("Blaa");
However, running MutabilityCheck with the changes made in 1. will result in the output being:
Foo
Foo
In order to achieve complete immutability on an object, all its dependent objects must also be immutable
From JDK 14+ which has JEP 359, we can use "records". It is the simplest and hustle free way of creating Immutable class.
A record class is a shallowly immutable, transparent carrier for a fixed set of fields known as the record components that provides a state description for the record. Each component gives rise to a final field that holds the provided value and an accessor method to retrieve the value. The field name and the accessor name match the name of the component.
Let consider the example of creating an immutable rectangle
record Rectangle(double length, double width) {}
No need to declare any constructor, no need to implement equals & hashCode methods. Just any Records need a name and a state description.
var rectangle = new Rectangle(7.1, 8.9);
System.out.print(rectangle.length()); // prints 7.1
If you want to validate the value during object creation, we have to explicitly declare the constructor.
public Rectangle {
if (length <= 0.0) {
throw new IllegalArgumentException();
}
}
The record's body may declare static methods, static fields, static initializers, constructors, instance methods, and nested types.
Instance Methods
record Rectangle(double length, double width) {
public double area() {
return this.length * this.width;
}
}
static fields, methods
Since state should be part of the components we cannot add instance fields to records. But, we can add static fields and methods:
record Rectangle(double length, double width) {
static double aStaticField;
static void aStaticMethod() {
System.out.println("Hello Static");
}
}