I have the following query , I was going through Java immutable class concept and come up with the following analysis..
All the fields must be private and preferably final
Ensure the class cannot be overridden - make the class final, or use static factories and keep constructors private
Fields must be populated from the Constructor/Factory
Don't provide any setters for the fields
Watch out for collections. Use Collections.unmodifiable*.
Also, collections should contain only immutable Objects
All the getters must provide immutable objects or use defensive copying
Don't provide any methods that change the internal state of the Object.
Now I have the following class..
public final class Bill {
private final int amount;
private final DateTime dateTime;
private final List<Integers> orders;
}
Please advise how it can be made as immutable class.
Your class as it is is immutable. Now you probably want to add a few methods:
public final class Bill {
private final int amount;
private final DateTime dateTime;
private final List<Integers> orders;
public Bill(int amount, DateTime dateTime, List<Integer> orders) {
this.amount = amount; //primitive type: ok
this.dateTime = dateTime; //joda.DateTime is immutable: ok
this.orders = new ArrayList<Integer> (orders); //make a copy as the caller could modify the list at its end
}
// no method that adds or removes from the list
public List<Integer> getOrders() {
return Collections.unmodifiableList(orders); //defensive copy
}
}
Alternatively, you can use this.orders = Collections.unmodifiableList(orders); in the constructor and return it from getOrders(): return orders;, which enforces the fact that you should not modify that list, even within your class.
Since int is a primitive and DataTime (from JodaTime, I guess) is immutable, the only thing you need to do is to ensure that you use immutable list:
public final class Bill {
...
public Bill(int amount, DateTime dateTime, List<Integer> orders) {
this.amount = amount;
this.dateTime = dateTime;
this.orders = Collections.unmodifiableList(orders);
}
...
}
Obviously, you also need a constructor to initialize final fields and some methods that would access that fields.
Since amount is a value type, datetime is unmodifiable, if you return a Collections.unmodifiable() version of your orders attribute in its getter, the class would become immutable.
Related
public enum CameraType {
CAMERA(false, false, "External lens ", ""),
CameraType{
boolean collector,
boolean hidden,
String description
) {
this.collector = collector;
this.granular = hidden;
this.description = description;
} // end ctor
public void setHide(boolean hidden) {
this.hide = hidden;
}
} // end enum
I have few Instance of CameraType.
I have a setter for "hidden" property which on certain condition is set to true or false.
Now I serialize CameraType with few other fields inside SecurityEntity.
```
#Entity
#Table
public class Security {
Few more fields...
#Enumerated(EnumType.STRING)
#Column(nullable = false)
private CameraType cameraType
And other fields...
}
```
When I deserialize the value of "hidden" field is always false. If I understand correctly, during deserialization ctor is called and default is assigned.
Is there a way I can retain the value of "hidden" field(true or false) after deserialization per instance of CameraType.
I am using Postgres DB 10.
enter code here
Please Please help. I am out of clues.
By definition, enums are immutable elements of a fixed set. Because of this, to represent an enum value you just need its name. That's exactly what JPA does during serialization/deserialization.
You are trying to violate the rules. While Java allows you to treat enums almost as plain objects, JPA treats them according to what they are supposed to be. That's why your code is not working.
You can either:
make CameraType into a class and serialize it as such, or
split CameraType into two parts, for example enum CameraType (immutable) and class CameraConfig (with all the mutable fields)
The former answer is correct : enums must be immutable and dividing parts into immutable and mutable data is a good choice.
One addition here: using the enum values for database storage is often not a good choice, because when another developer decides to refactor the enum names and you are after this reading old entries from database, you got a crashing application...
So I would suggest to use javax.persistence.AttributeConverter to deserialize/serialize an enum in a specific and rename save way.
Here a very simple example with an enum called MyDefinition:
enum MyDefinition{
ONE("def_one"),
TWO"def_two"),
THREE("def_three"),
;
private String id;
private MyDefinition(String id){
this.id=id;
}
public String getId(){
return id;
}
public static MyDefinition fromId(String id) {
for (MyDefinition definition : MyDefinition.values()) {
if (definition.id.equals(id)) {
return definition;
}
}
return null;
}
}
Here the converter:
import javax.persistence.AttributeConverter;
import javax.persistence.Converter;
#Converter(autoApply = true)
public class MyDefinitionAttributeConverter implements AttributeConverter<MyDefinition, String> {
#Override
public String convertToDatabaseColumn(MyDefinition attribute) {
if (attribute == null){
return null;}
}
return attribute.getId();
}
#Override
public MyDefinition convertToEntityAttribute(String dbData) {
return MyDefinition.fromId(dbData);
}
So we can use the ids for database. A renaming of the enum names will no longer lead to a crashing application when reading old data.
I am in a dilemma with lombok, those who know this tool know that it is very easy to declare the getters and setters but when it comes to Dates and Collections, how can we declare them immutable?
Thx & Kind regards!
Lombok provides #Wither that allows somehow to ease creation of immutable objects. However, it doesn't cover the cases that you mentioned.
You will have to manage immutability of the objects yourself, and use Lombok for all other situations.
Also, this is an example how to implement ImmutableObject with Date and Collection:
public final class ImmutableObject {
private final Collection<String> collection;
private final Date date;
public ImmutableObject(final Collection<String> options, final Date createdAt) {
this.collection = ImmutableList.copyOf(options); // guava's immutable list
this.date = new Date(date); // must be copied to prevent caller from modifying it
}
public Date getDate() {
return new Date(date); // Date is mutable
}
public Collection<String> getCollection() {
return collection; // already immutable copy
}
}
I have a java class named Transactions, with several methods. On in particular, inserts in Sqlite database all values representing a new transaction, something like this:
Date; Time; Category; Payee; Payer; Value; Tags; Description (...)
When I call the method to save a new Transaction, it looks like:
new Transactions().saveNewTransaction(String date, String time, String category, Int Payee, Int Payer, String value, String tags, String Description (...)
I think this method seems big, bad for readable code and the best way would be those fields be as variables from Transactions class and the method saveNewTransaction(), takes no parameters but instead accessing the variables inside the class.
The only problem is: how can I force to a class (In my case an Activity class) call all setters needed to save a new transaction?
The risk would be call saveNewTransaction() and several fields with values not set by the Activity class (at least the method assures all fields must be set by the caller)
Thanks!
If your requirement is that each created Transactions object should result in some database entry, you could consider dropping the saveNewtTransaction method and instead perform the save-action within some "builder" class:
public class TransactionBuilder {
private Date date;
public TransactionsBuilder with(#NonNull Date date){
this.date = date;
return this;
}
public Transaction build(){
validateFields();
Transaction transaction = new Transaction();
transaction.set(date);
createADatabaseEntry(transaction);
return transaction;
}
private void validateFields() {
org.springframework.util.Assert.notNull(date, "The date cannot be null.");
}
Have the checker framework issue compiler warnings, when developers try to pass null to setters annotated with #NonNull.
Obviously, in your case, the builder would have some different with()-methods, namely some which matches what is needed for your Transactiion object / saveNewTransaction()-method.
Ps I have not given it any thought what your Transaction class is all about. But if the Transactions class only has that one method, I would create a variant of above mentioned solution:
Create an interface with a single method that defines the functionality.
Create an implementation which contains the logic of your saveNewTransactions()-method. Only difference being that this method should only accept a single argument, which is an "input bean", fx TransactionInputBean.
Create your input bean (a simply class with private fields, and public getters&setters.
Create a builder for the input bean.
you could leave all of these variables uninitialized or set them to a value that shouldn't occur by the setters (eg. -1).
Then in your new Transactions().save(); you'd need to check if they still have that value.
But this solution won't work in the way you wrote above, because you are already saving the transaction when you create the object. And here you'd need to create the new object first and then call all the setters.
Your transactions class could look like this:
package de.jeanma.stackOverflow;
import java.lang.Integer;
import java.lang.String;
public class Transactions{
private String date, time, category, value, tags, description;
private int payee, payer;
public Transactions(){
//Add everything here, needed for the constructor
}
public Transactions(String date, String time, String category, int payee, //I recommend creating an constructor that sets the values as well, beacause you
int payer, String value, String tags, String Description){ // might want to create the object and call the save() directly withoud calling every setter one by one
this.date = date;
this.time = time;
this.category = category;
this.value = value;
this.tags = tags;
this.description = description;
this.payee = payee;
this.payer = payer;
//Add everything here, needed for the constructor as well
}
//Here you can place all your other methods
public void save(){
if(!(isInitialized(date) && isInitialized(time) && isInitialized(category) && isInitialized(value) //here all values are checked if they are initialized.
&& isInitialized(tags) && isInitialized(description) && isInitialized(Integer.valueOf(payee)) //The primitive int's are made to complex Integer's because
&& isInitialized(Integer.valueOf(payer)))){ // the method isInitialized() expects an object
//here you could throw an exception or do something like: System.exit(-1);
}
}
private boolean isInitialized(Object Obj){ // this is the method that's checking if the value is initialized
if(Obj.equals(null)) return false;
else return true;
}
//Add all the setters here (I'm too lazy to do that now)
}
I hope that this awnser satisfies you.
Is it required to make the fields of an Immutable class private as if they are marked as final , can not be changed ?
I mean isn't it enough to just mark the fields as final ?
(I know that it's not necessary for an immutable class to have final fields but it's advisable to have it for compile time check for the class internally.)
No this is not enough.
Consider this example:
final class ImmutableClass {
private final List<String> data;
public ImmutableClass(final List<String> data) {
this.data = data;
}
public List<String> getData() {
return data;
}
}
This class is final so cannot be extended. It's data field is final so cannot be changed after it is assigned.
But:
final ImmutableClass immutableClass = new ImmutableClass(data);
immutableClass.getData().add("Some other value");
Oops.
So to make a class truly immutable all fields should also be immutable classes, or have defensive copies.
For example, to correct the issues about you would need to do this:
final class ImmutableClass {
private final List<String> data;
public ImmutableClass(final List<String> data) {
this.data = new ArrayList<>(data);
}
public List<String> getData() {
return Collections.unmodifiableList(data);
}
}
And this only works because String is immutable. If you had, for instance, a List<Date> you would also need to copy the individual Date objects.
Having private variables accessed through getters gives you more freedom with the implementation of the class. You can, for example, replace a trivial getter with an implementation which calculates or retrieves the value on access or caches the result.
Another reason to keep fields as private even when they are final is when the field is a mutable object. In that case the object can be changed even though it is final which is usually not what you want. Here is an example of a presumably immutable class with a public final field of the mutable Date class.
class DateHolder {
public final Date date;
DateHolder(Date date) {
this.date = date:
}
}
// ...
DateHolder holder = new DateHolder(Date.now());
// this doesn't work because date is final:
//holder.date = new Date(2013, 11, 23);
// but this works even though date is final:
holder.date.setYear(2013);
final fields can only be assigned to from within the constructor. Therefore, making fields final is enough to make them immutable after construction. Assigning pointers to mutable objects to them is a different story.
As this is a hot topic these days, I fail to understand certain concept. Please excuse me if I sound stupid but when I tried creating immutable object most of the posts I found following points
Make class final - makes sense
Dont allow mutators (setters) for the attributes - makes sense
Make attributes private - makes sense
Now I fail to understand why we need below points
Make constructor private and provide createInstance method with the same attributes as constructor or factory method ? How does it help ?
Make attributes final - post of the post fail to explain this point and some where I read to avoid the modification accidentally. How can you modify accidentally, when there are no mutators and class is final ? How making an attribute final is helping ?
Instead of factory pattern, can I use builder pattern ?
I am adding my class and test case here :
public final class ImmutableUser {
private final UUID id;
private final String firstName;
private final String lastName;
public ImmutableUser(UUID id, String firstName, String lastName) {
super();
this.id = id;
this.firstName = firstName;
this.lastName = lastName;
}
/**
* #return the id
*/
public UUID getId() {
return id;
}
/**
* #return the firstName
*/
public String getFirstName() {
return firstName;
}
/**
* #return the lastName
*/
public String getLastName() {
return lastName;
}
}
Test case
public class ImmutableUserTest {
#Test(expected = IllegalAccessException.class)
public void reflectionFailure() throws NoSuchFieldException, SecurityException, IllegalArgumentException, IllegalAccessException {
ImmutableUser user = new ImmutableUser(UUID.randomUUID(), "john", "liu");
Field i =user.getClass().getDeclaredField("firstName");
i.setAccessible(true);
i.set(user, "cassandra");
System.out.println("user " + user.getFirstName()); // prints cassandra
}
}
This test case fails and prints cassandra.
Let me know if I am doing something wrong.
Make constructor private and provide createInstance method with the same attributes as constructor or factory method ? How does it helps ?
Answer: making the constructor private and providing createInstance() (factory method) does not help by itself: it is one of few things you should do in order to allow users to actually use the class and its instances while you still have the control of the way instances are created.
Make attributes final - the post fails to explain this point and somewhere I read to avoid the modification accidentally. How can you modify accidentally, when there are no mutators and class is final ? How making an attribute final is helping ?
Answer: declaring a class as final means that the user can't extend it, so it "blocks" the user from this kind of "workaround". Declaring an attribute as final won't allow the user of the class to change it. It cannot be "modified accidentally", but it can be "modified viciously" using reflection. Let's see an example, say you have:
final public class SomeClass {
final Integer i = 1;
}
from another class you can do as follows:
class AnotherClass {
public static void main (String[] args) throws Exception {
SomeClass p = new SomeClass();
Field i =p.getClass().getDeclaredField("i");
i.setAccessible(true);
i.set(p, 5);
System.out.println("p.i = " + p.i); // prints 5
}
}
Can instead of factory use builder pattern ?
Answer: you can use the builder pattern or any pattern that helps you control the creation of instances of the class.
Further:
If you want to make sure your class is immutable, make sure that any getter returns a deep-copy of the class member. This technique is called "protective/defensive copy". You can read more about it here
I'd start from making attributes final. Making attribute final guarantees that you cannot change the attribute value. I think this is obvious. (I will write additional comment to changing the content of references immutable objects later).
Now, when all your attributes are final they must be initiated via constructor. However some classes have a lot of attributes, so the constructor becomes huge. Moreover sometimes some attributes can be initialized to default values. Attempt to support this causes us to implement several constructors with almost random combination of arguments. However Builder pattern helps us. But how to make user to use Builder instead of direct invocation of constructor? The answer is making constructor private and creating static method that returns builder:
public class Person {
private final String firstName;
private final String lastName;
private final Person mother;
private final Person father;
private Person(String firstName, String lastName, Person mother, Person father) {
// init the fields....
}
public static PersonBuilder builder() {
return new PersonBuilder();
}
public static class PersonBuilder {
// here fields are NOT final
private String firstName;
private String lastName;
private Person mother;
private Person father;
public PersonBuilder bornBy(Person mother) {
this.mother = mother;
return this;
}
public PersonBuilder conceivedBy(Person father) {
this.father = father;
return this;
}
public PersonBuilder named(String firstName) {
this.firstName = firstName;
return this;
}
public PersonBuilder fromFamily(String lastName) {
this.lastName = lastName;
return this;
}
Person build() {
return new Person(name, lastName, mother, father);
}
}
}
And here is the typical usage pattern:
Person adam = Person.builder().named("Adam").build(); // no mother, father, family
Person eve = Person.builder().named("Eve").build(); // no mother, father, family
Person cain = Person.builder().named("Cain").conerivedBy(adam).bornBy(eve); // this one has parents
As you can see builder pattern often is better than factory because it is much more flexible.
I think that you missed one point in your question: references to other (mutable) objects. If for example we add field Collection<Person> children to our Person class we have to care that getChildren() returns either Iterable or at least unmodifirable collection.
Making the constructor private and using the builder pattern are not necessary for immutability. However because your class can't provide setters and if it has many fields, using a constructor with many parameters can be detrimental to readability hence the idea to use the builder pattern (which needs a pervade constructor).
The other answers seem to have missed an important point though.
Using final fields is essential, not only to ensure that they don't get modified, but because otherwise you lose some important thread safety guarantees. Indeed, one aspect of immutability is that it brings you thread safety. If you don't make the fields final your class becomes effectively immutable. See for example Must all properties of an immutable object be final?