How to define with Lombok Date And Collections immutable? - java

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

Related

How to serialize and deserialize multi argument enum in Java using JPA 2.1 or lower (Postgres)

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.

Serialization with singleton design pattern

I have a problem with serialization of a class using the singleton pattern. First let me introduce the code:
import java.io.ObjectStreamException;
import java.io.Serializable;
import org.ejml.simple.SimpleMatrix;
public class Operation implements Serializable {
private static final long serialVersionUID = 1L;
private final static int CONSTANT = 10;
private SimpleMatrix data;
private Long timestamp;
private static Operation instance = new Operation ();
private Operation () {
data = new SimpleMatrix(1, CONSTANT);
}
protected static Operation getInstance() {
return instance;
}
//Hook for not breaking the singleton pattern while deserializing.
private Object readResolve() throws ObjectStreamException {
return instance;
}
protected void setData(SimpleMatrix matrix) {
this.data = matrix;
}
protected SimpleMatrix getData() {
return data;
}
public Long getTimestamp() {
return timestamp;
}
public void setTimestamp(Long timestamp) {
this.timestamp = timestamp;
}
}
I have three problems with it hoping that somebody can help me:
As far as I know, static fields are no serialized. So if I deserialize is my final static field CONSTANT set to 10? If not, how can I make this? This is very important.
As you can see, in the constructor a new matrix is created. If I deserialize, is my data overwritten by this constructor? For deserialization I want the data of the serialized version and not a new matrix. The constructor I only need the first time before serialization to instantiate the object.
Before I serialize I will set the field timestamp to the time of serialization. After deserialization I would like to compare this field with the timestamp of some files (to see if files have changed since serialization). What sort of timestamp should I use for both the serialization time and the last modified time of files so that I can easily compare?
The static constant is associated with the class, so serialization and deserialization of your instance won't impact it at all.
For the deserialization to work, you need to set the singleton's data to the deserialized instance data:
private Object readResolve() throws ObjectStreamException {
instance.setData(getData());
return instance;
}
The timestamp can stay as a Long, that's fine. Use System.currentTimeMillis(), you'll be able to compare with a File object lastModified() date. Just set the field when you serialize:
private void writeObject(java.io.ObjectOutputStream out)
throws IOException{
timestamp=System.currentTimeMillis();
out.defaultWriteObject();
}
A test I've made to be sure of what I say, using a String instead of a matrix as in your code:
public static void main(String[] args) throws Exception {
Operation op=getInstance();
op.setData("test1");
byte[] ds=serialize();
System.out.println(new Date(getInstance().timestamp));
op.setData("test2");
deserialize(ds);
System.out.println(getInstance().getData());
}
This gives me the current date and test1, since the deserialize instance has overriden the current instance. serialize and deserialize simply convert between the instance and bytes.
I would suggest that you adopt the Enum Singleton approach for implementing Singletons, as handling Serialization would be done for free. In your case it would be
public enum Operation {
INSTANCE;
// No need to handle Serialization
}
Quoting Joshua Bloch in Effective Java "a single-element enum type is the best way to implement a singleton."
There are plenty benefits to this approach, you can find out here
And also For instance control, prefer enum types to readResolve

How to make a class immutable in java with date field in it?

I have created an immutable class with a date field. How do I ensure that even the date field is immutable, since even if you make date field final you can still assign a different value to it later?
In your getDate() method, return a new Date() instance, instead of the same instance.
public Date getDate() {
// Not correct.
return this.date; // This will make your class mutable.
// Instead use,
return new Date(this.date.getTime()); // This will make sure your date field cannot be changed.
}
java.time
Other Answers are correct that in showing strategies for fixing values within your objects.
Let me also recommend that you use the modern java.time classes rather than the terrible legacy classes. In place of Date, use Instant. In place of Calendar, use ZonedDateTime.
The java.time classes are designed as immutable objects. Methods such as plus…, minus…, to…, and with all produce a fresh object, leaving the original intact. The classes carry no setter methods.
Bonus tip: In your own immutable classes, you may find it useful to follow the method naming patterns established by the java.time classes.
About java.time
The java.time framework is built into Java 8 and later. These classes supplant the troublesome old legacy date-time classes such as java.util.Date, Calendar, & SimpleDateFormat.
The Joda-Time project, now in maintenance mode, advises migration to the java.time classes.
To learn more, see the Oracle Tutorial. And search Stack Overflow for many examples and explanations. Specification is JSR 310.
Using a JDBC driver compliant with JDBC 4.2 or later, you may exchange java.time objects directly with your database. No need for strings nor java.sql.* classes.
Where to obtain the java.time classes?
Java SE 8, Java SE 9, and later
Built-in.
Part of the standard Java API with a bundled implementation.
Java 9 adds some minor features and fixes.
Java SE 6 and Java SE 7
Much of the java.time functionality is back-ported to Java 6 & 7 in ThreeTen-Backport.
Android
Later versions of Android bundle implementations of the java.time classes.
For earlier Android, the ThreeTenABP project adapts ThreeTen-Backport (mentioned above). See How to use ThreeTenABP….
The ThreeTen-Extra project extends java.time with additional classes. This project is a proving ground for possible future additions to java.time. You may find some useful classes here such as Interval, YearWeek, YearQuarter, and more.
You can clone date object so that it cannot be modified
public Date getDate (){
return (Date) this.date.clone ();
}
Here is the simple example of immutable class in Java
public final class Employee{
final String pancardNumber;
public Employee(String pancardNumber){
this.pancardNumber=pancardNumber;
}
public String getPancardNumber(){
return pancardNumber;
}
}
The above class is immutable because:
The instance variable of the class is final i.e. we cannot change
the value of it after creating an object.
The class is final so we cannot create the subclass.
There is no setter methods i.e. we have
no option to change the value of the instance variable.
These points makes this class as immutable. In case of Date attribute, you can use constructor to set your date with every new object and import org.joda.time.DateTime class. This is a better version than the java.util.Date because it is immutable. Using a java.util.Date would be dangerous as it is a mutable class and we can’t control the calling thread (which might modify it). Here is example.
public final class Bill {
private final int amount;
private final DateTime dateTime;
public Bill(int amount, DateTime dateTime) {
this.amount = amount;
this.dateTime = dateTime;
}
public int getAmount() {
return amount;
}
public DateTime getDateTime() {
return dateTime;
}
}
This is an example of a Bean(Class) with an immutable HAS-A Date Object.
import java.util.Date;
public class MyBean {
private Date date; // Immutable Date Step 1 Make Private
public MyBean(Date date)
{
// Immutable Date Step 2 If Set through Constructor then get a specialised (sub class) Date.
this.date= getImmutableDate(date); // THIS METHOD RETURNS AN IMMUTABLE DATE
}
public MyBean(){} // Allow Default Constructor
public Date getDate() {
return date;
}
// Immutable Date Step 3- Allow setting of date only once!!
public void setDate(Date date) {
if(this.date==null)
{
this.date= getImmutableDate(date);
}
}
/* Override all Setter methods of Date class. So even if user gets reference of Date Object it is not the original date object
* it would be a modified date object whose all setter methods do nothing*/
private Date getImmutableDate(Date date)
{
/* This is an Anonymous Inner Class that extends java.util.Date class, it overrides all the setter methods
* making the date object IMMUTABLE( i.e setXXX has no effect)
* */
date =new Date(date.getTime()){
private static final long serialVersionUID = 1L;
#Override
public void setYear(int year) {}
#Override
public void setMonth(int month) {}
#Override
public void setDate(int date) {}
#Override
public void setHours(int hours) {}
#Override
public void setMinutes(int minutes) {}
#Override
public void setSeconds(int seconds) {}
#Override
public void setTime(long time) {}
};
return date;
}
}
Use defensive copying. This means that if you have to pass the date to some other class, for example through a method parameter or returned from a method, you should make a copy.
Making a copy of a Date is easy:
new Date(myDate.getting())
Identify the mutable instance variables(like date or hashmap) return new objects with copied content for all mutable objects. Immutable variables can be returned safely without extra effort.
See below example:
import java.util.Date;
public final class ImmutableClass
{
/**
* Integer class is immutable as it does not provide any setter to change its content
* */
private final Integer immutableField1;
/**
* String class is immutable as it also does not provide setter to change its content
* */
private final String immutableField2;
/**
* Date class is mutable as it provide setters to change various date/time parts
* */
private final Date mutableField;
//Default private constructor will ensure no unplanned construction of class
private ImmutableClass(Integer fld1, String fld2, Date date)
{
this.immutableField1 = fld1;
this.immutableField2 = fld2;
this.mutableField = new Date(date.getTime());
}
//Factory method to store object creation logic in single place
public static ImmutableClass createNewInstance(Integer fld1, String fld2, Date date)
{
return new ImmutableClass(fld1, fld2, date);
}
//Provide no setter methods
/**
* Integer class is immutable so we can return the instance variable as it is
* */
public Integer getImmutableField1() {
return immutableField1;
}
/**
* String class is also immutable so we can return the instance variable as it is
* */
public String getImmutableField2() {
return immutableField2;
}
/**
* 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 getMutableField() {
return new Date(mutableField.getTime());
}
#Override
public String toString() {
return immutableField1 +" - "+ immutableField2 +" - "+ mutableField;
}
}
For more details :
http://www.javainterviewpoint.com/make-class-immutable-java/
Only way to do this.
Create a custom DateClass and Overrider the set** methods and dont provide any functionality to this methods.

Immutable classes in java

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.

Regarding an immutable class

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.

Categories

Resources