And since the whole state of an immutable object has to be passed into the constructor, the compiler can tell us when we forget to pass a certain field. The compiler will point out all the places where we have to add that new field in the client code. The main features are that the fields are final , telling the compiler that their values must not change once initialized and that all field values are passed into the constructor. Instead of writing the constructor by hand, we can use Lombok to generate the constructor for us:.
RequiredArgsConstructor generates a constructor that takes values for all final fields as parameters. Note that if we change the order of the fields, Lombok will automatically change the order of the parameters. This is the price to pay for automatic code generation. An immutable object may have fields that are optional so that their value is null. Passing null into a constructor is a code smell, however, because we assume knowledge of the inner workings of the immutable.
Instead, the immutable should provide a factory method for each valid combination of fields:. The User class may have an empty ID because we somehow have to instantiate users that have not been saved to the database yet. Instead of providing a single constructor into which we would have to pass a null ID, we have created a static factory method to which we only have to pass the name. Internally, the immutable then passes a null ID to the private constructor.
We can give names to the factory methods like newUser and existingUser , to make clear their intent. In the User class from above, the ID is an optional field and may be null. Any client calling getId will immediately know that the value might be empty and will act accordingly. This would make it obvious at a glance at the field declarations that the ID may be empty. This is bad practice, however, since an Optional may also be null.
This would mean that each time we work with the value of the ID field within the User class, we would have to first check if the Optional is null and then check if it has a value or is empty. To only allow valid state, an immutable may check within its constructor s if the passed-in values are valid according to the business rules of the class:. This way we can always be certain that we have an object with a valid state in our hands.
Also, the validation is very close to the validated fields as opposed to the validation code being in some service at the other end of the codebase , making it easy to find and maintain together with the fields.
Instead of validating our immutable by hand as we did above, we can also take advantage of the declarative approach of the Bean Validation library:. We simply add Bean Validation annotations to mark validation rules and then call validateSelf as the last statement in the constructor. The validateSelf method is implemented in the parent class SelfValidating and might look like this:.
A builder is a class whose goal it is to make object instantiation easy. Instead of calling a constructor which takes all field values as arguments, we call fluid builder methods to set the state of an object step-by-step:.
This is especially helpful if we have a lot of fields since its better readable than a call to a constructor with many parameters. Using a builder to create an immutable object instance is not a good idea, however. Look at the code above: we called the build method after only initializing the id field. The name field is still empty. If the User class also requires a value for the name field, the builder will probably simply pass null into the constructor and object instantiation will fail at runtime.
Had we used the factory methods from above, the compiler would know which combinations of fields are valid and which are not at compile time. For example, the Student object, in the example below, is immutable even if the property dateJoined is Date object. The code from the above example is available on GitHub. See the original article here.
Thanks for visiting DZone today,. Edit Profile. Sign Out View Profile. Over 2 million developers have joined DZone. Java Immutable Objects. Want to learn more about immutable objects in Java? Like Join the DZone community and get the full member experience. Immutable Objects in Java. An overview plus some practical tips on immutable objects in Java. Like Join the DZone community and get the full member experience. Join For Free. An immutable object is an object that will not change its internal state after creation.
Immutable objects are always thread safe. Threads Are Everywhere It is not important if you write explicit multithreaded application or not, often you work in a multithreaded environment without directly managing thread instances. Here are few example of multithreaded applications where the programmer doesn't manually invoke the creation of new threads: Web applications because servlets are handled by a pool of threads Swing desktop applications where threads handle GUI events Timer instances create new threads to handle future task executions Creating an Immutable Object To create an immutable object you need to follow some simple rules: Don't add any setter method Declare all fields final and private If a field is a mutable object create defensive copies of it for getter methods If a mutable object passed to the constructor must be assigned to a field create a defensive copy of it Don't allow subclasses to override methods.
Now we discover point by point the reasons of the five rules explained before. Don't add any setter method If you are building an immutable object its internal state will never change.
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. 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!
0コメント