what are possibilities of creating immutable bean in Java. For example I have immutable class Person. What's a good way to create instance and fill private fields. Public constructor doesn't seems good to me because of a lot input parameters will occure as class will grow in rest of application. Thank you for any suggestions.
public class Person {
private String firstName;
private String lastName;
private List<Address> addresses;
private List<Phone> phones;
public List<Address> getAddresses() {
return Collections.unmodifiableList(addresses);
}
public String getFirstName() {
return firstName;
}
public String getLastName() {
return lastName;
}
public List<Phone> getPhones() {
return Collections.unmodifiableList(phones);
}
}
EDIT: Specify question more precisely.
You could use the builder pattern.
public class PersonBuilder {
private String firstName;
// and others...
public PersonBuilder() {
// no arguments necessary for the builder
}
public PersonBuilder firstName(String firstName) {
this.firstName = firstName;
return this;
}
public Person build() {
// here (or in the Person constructor) you could validate the data
return new Person(firstName, ...);
}
}
You can then use it like this:
Person p = new PersonBuilder.firstName("Foo").build();
At first sight it might look more complex than a simple constructor with tons of parameters (and it probably is), but there are a few significant advantages:
You don't need to specify values that you want to keep at the default values
You can extend the Person class and the builder without having to declare multiple constructors or needing to rewrite every code that creates a Person: simply add methods to the builder, if someone doesn't call them, it doesn't matter.
You could pass around the builder object to allow different pieces of code to set different parameters of the Person.
You can use the builder to create multiple similar Person objects, which can be useful for unit tests, for example:
PersonBuilder builder = new PersonBuilder().firstName("Foo").addAddress(new Address(...));
Person fooBar = builder.lastName("Bar").build();
Person fooBaz = builder.lastName("Baz").build();
assertFalse(fooBar.equals(fooBaz));
You should have a look at the builder pattern.
One good solution is to make your fields final, add your constructor private and make use of Builders in your code.
In our project we combined the Builder pattern with a validation framework so that once an object is created we are sure it's immutable and valid.
Here is a quick example:
public class Person {
public static class Builder {
private String firstName;
private String lastName;
private final List<String> addresses = new ArrayList<String>();
private final List<String> phones = new ArrayList<String>();
public Person create() {
return new Person(firstName, lastName, addresses, phones);
}
public Builder setFirstName(String firstName) {
this.firstName = firstName;
return this;
}
public Builder setLastName(String lastName) {
this.lastName = lastName;
return this;
}
public Builder addAddresse(String adr) {
if (adr != null) {
addresses.add(adr);
}
return this;
}
public Builder addPhone(String phone) {
if (phone != null) {
phones.add(phone);
}
return this;
}
}
// ************************ end of static declarations **********************
private final String firstName;
private final String lastName;
private final List<String> addresses;
private final List<String> phones;
private Person(String firstName, String lastName, List<String> addresses, List<String> phones) {
this.firstName = firstName;
this.lastName = lastName;
this.addresses = addresses;
this.phones = phones;
}
public List<String> getAddresses() {
return Collections.unmodifiableList(addresses);
}
public String getFirstName() {
return firstName;
}
public String getLastName() {
return lastName;
}
public List<String> getPhones() {
return Collections.unmodifiableList(phones);
}
}
In my example you can see that all the setters in the Builder return the Builder instance so that you can easily chain the setters calls. That's pretty useful.
You could take a look at the Builder pattern presented by Joshua Bloch.
As I said before, combined with a validation framework (see for ex. http://www.hibernate.org/subprojects/validator.html) this is really powerfull.
With interfaces. Do this:
public interface Person {
String getFirstName();
String getLastName();
// [...]
}
And your implementation:
// PersonImpl is package private, in the same package as the Factory
class PersonImpl {
String getFirstName();
void setFirstName(String s);
String getLastName();
void setLastName(String s);
// [...]
}
// The factory is the only authority to create PersonImpl
public class Factory {
public static Person createPerson() {
PersonImpl result = new PersonImpl();
// [ do initialisation here ]
return result;
}
}
And never expose the implementation to the places where you want Person to be immutable.
Initializing in the constructor is nevertheless the simplest and safest way to achieve immutability, as this is the only way to have final fields in your immutable class (which is the standard idiom, and has beneficial effects especially if your class is used in a multithreaded environment). If you have lots of properties in your class, it may be a sign that it is trying to do too much. Consider dividing it to smaller classes, or extracting groups of related properties into compound property classes.
Using a Builder (with a private constructor) is a possibility, however it still needs a way to set the properties of the object being built. So you fall back to the original dilemma of constructor parameters vs accessing the private members. In the latter case you can't declare the properties of the object being built as final, which IMHO is a great minus. And in the former case you still have the same long list of constructor parameters you wanted to avoid in the first place. Just now with a lot of extra boilerplate code on top of it.
You can achieve an "immutable" bean by making a read-only interface and then making the implementation into a mutable bean. Passing around the interface won't allow for mutation, but when you construct the object and have the implementation, you can do all sorts of bean-y things:
public interface Person {
String getFirstName();
String getLastName();
// ... other immutable methods ...
}
public class MutablePerson implements Person {
// ... mutable functions, state goes here ...
}
Use the factory-pattern:
let Person be an interface with only "get"-functions
create a PersonFactory with an appropriate API for building a Person-object
the PersonFactory creates an object which implements the Person-interface and returns this
Have final fields.
Make the class as "final" class by declaring as final public class Person
do not use setXXX() methods to set the value since it will change the state of a variable. however getXXX() methods are allowed.
Use a private constructor so that you can set fields using the constructor itself.
Follow the above guidelines for Immutable class.
Use final fields for all your instance variables. You can create a constructor if you like and choose to not expose setters, e.g.,
public class Person {
private final String firstName;
....
public Person(String firstName, ... ) {
this.firstName = firstName;
}
}
Related
I am using Spring to develop new REST API, I have BaseResponse class which acts as base responses for all response. this class contains attribute String requestUuid; at some cases this requestUuid must be serialized with attribute name requestUuid , on other cases it must be seriliazed as request_uuid, i know i can use #JsonProperty as a field level annotation, but it will affect all responses. is there is any way to override attribute name specifically for each one of the derived classes.
You can use the #JsonProperty on the method level instead. That way, you can override the field's getter method in the subclass and annotate that.
For example:
class BaseResponse {
private String requestUuid;
public getRequestUuid() {
return requestUuid;
}
}
class OtherResponse extends BaseResponse {
#Override
#JsonProperty("request_uuid")
public getRequestUuid() {
return super.getRequestUuid();
}
}
You can send the field twice with different key names.
#JsonAnyGetter
public Map<String, Object> otherFields() {
Map<String, Object> otherFields = new HashMap<>();
otherFields.put("requestUuid", this.requestUuid);
otherFields.put("request_uuid", this.requestUuid);
return otherFields;
}
Also, ignore your actual field:
#JsonIgnore
private String requestUuid;
Expanding on #JoshA response, another alternative is to define a constructor and annotate it. This leads to a more concise code by avoiding the need to override the getter methods in derived classes.
class BaseResponse {
private String firstName;
private String lastName;
public BaseResponse(String firstName, String lastName) {
this.firstName = firstName;
this.lastName = lastName;
}
public getFirstName() {
return firstName;
}
public getLastName() {
return lastName;
}
}
class OtherResponse extends BaseResponse {
public OtherResponse(#JsonProperty("given_name") String firstName, #JsonProperty("family_name") String lastName) {
super(firstName, lastName);
}
}
NO, its not possible, what is possible you can make new class for different type of requests.
Creating immutable class using setter method from outside class.As i have a POJO Class Object creation may be done using setter method.How come it possible to make immutable using setter
Setters are mutators.
https://en.wikipedia.org/wiki/Mutator_method
I think you might be referring to a factory method?
https://www.tutorialspoint.com/design_pattern/factory_pattern.htm
Or maybe you have some hybrid thingo going on.
People more experienced then me would have better answers.
You can use the Builder Pattern. There you have a separate builder class with a kind of setter for each field. The final build() eventually creates the immutable object.
public final class Person {
private final String forename;
private final String surename;
private final int age;
private Person(String forename, String surename, int age) {
this.forename = forename;
this.surename = surename;
this.age = age;
}
public String getForename() {
return forename;
}
public String getSurename() {
return surename;
}
public int getAge() {
return age;
}
public static PersonBuilder createBuilder() {
return new PersonBuilder();
}
public static class PersonBuilder {
private String forename;
private String surename;
private int age;
private PersonBuilder() {
}
public PersonBuilder withForename(String forename) {
this.forename = forename;
return this;
}
public PersonBuilder withSurename(String surename) {
this.surename = surename;
return this;
}
public PersonBuilder withAge(int age) {
this.age = age;
return this;
}
public Person build() {
return new Person(forename, surename, age);
}
}
You can then create a Person instance like so:
Person person = Person.createBuilder().withSurename("Krueger")
.withForename("Freddy").withAge(47).build();
With a builder you have the best of both worlds. The flexibility of setters (including fluent API) and immutable objects at the end.
Edit:
Joshua Bloch stated in Item 15: "Minimize Mutability" in his book "Effective Java":
To make a class immutable, follow these five rules:
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. [...]
Ensure exclusive access to any mutable components. [...]
To fulfill point 2 I added the final keyword to the above Person class.
According to this widely accepted definition of immutability a class with setters is per se not immutable because it violates point 1.
If think the intention to ask this question in an interview is to see wether the candidate is able to recognize the discrepancy in the question itself and how far goes the knowledge about immutability and the various alternatives to create instances of immutable classes (per constructor, per static factory methods, per factory classes, per builder pattern, ...).
I have 2 builders in my codebase, which can be accessed like this :
return new Developer.Builder("John", "Doe").age(30).build();
return new Manager.Builder("Eve", "Page").age(40).build();
I want to make the API simpler by encapsulating in an enum :
return Google.Developer.Builder("John", "Doe").age(30).build();
return Google.Manager.Builder("Eve", "Page").age(40).build();
My goal is to simplify the process for
Changing company names from Google to Microsoft
If a new role is added (apart from Developer and Manager), users of my code can know about it in one place.
Only option which comes to my mind is having company name as enum - but then I won't be able to implement builder pattern.
You can create an API similar to what you describe:
enum Google {
Developer, Manager;
public Builder builder(String name) {
return new Builder(this, name);
}
public static class Builder {
public Builder(Google role, String name) { ... }
public Builder age(int age) { ... }
public Employee build() { ... }
}
}
Now you can write
Employee e = Google.Developer.builder("John").age(30).build();
I don't see what the point is for all this. Do the builders somehow depend on the company and role in a non-trivial way?
If not, you can define the Builder as a separate class and use an interface to mark what ever represents roles in companies, similar to Sleiman's answer.
You could even parametrize the Employee class with company, if this makes sense in your application...
interface CompanyRole { /* just a marker */ }
enum Google implements CompanyRole {
...
Employee.Builder<Google> builder(String name) {
return new Employee.Builder<>(this, name);
}
}
class Employee<T extends CompanyRole> {
...
static class Builder<T extends CompanyRole> {
EmployeeBuilder(T role, String name) { ... }
Employee<T> build() { ... }
}
}
And you can still write
Employee<Google> e = Google.Developer.builder("John").age(30).build();
You can add an interface that represents a company
interface Company{
}
And have an enum of well known companies,
enum Companies implements Company{
GOOGLE,
MICROSOFT,
...
}
And now in your builder you can add a method that takes a Company rather an enum
Builder company(Company company){
addCompany(company);
return this;
}
And construct it fluently like this
Developer.Builder("John", "Doe").company(Companies.GOOGLE).age(30).build();
And now companies can either be constants or something you load from a db (anything that implements Company). It is type-safe either ways.
Review
return Google.Developer.DevBuilder("John", "Doe").age(30).build();
This makes no sense. Taking a closer look, above call leads to a class Google, which contains an inner class Developer. That class defines a static method called DevBuilder that takes 2 parameters, first and last name, and returns an instance of Builder/DeveloperBuilder.
This is not an object oriented, extensible approach. Even though you gave us very little context, I'd argue that companies are static objects, which are not subject to change. Referring to the example you made in the comments - a new company is more likely than a new CompressFormat.
Further, there is no possibility to change behaviour via polymorphism, except for the dynamic calls to age(int) and build().
Dynamic approach
Below a concept of a more dynamic approach (of course mechanics should be added, to make sure that there is only one object for a company, e.g. Company.byName("Google") etc.)
public static void main(String[] args) {
Company google = new Google();
Manager manager = google.newManager();
}
static abstract class Company {
public Manager newManager() {
return new ManagerBuilder("Eve", "Page").age(40).build();
}
}
static class Google extends Company {
}
You can easily add new companies and change the way a manager (or any other employee) is created, you can also use the default.
Refactoring
With some more playing around, you can remove the boiler plate code in the classes for employees and their corresponding builders, by creating two base classes as follows
static abstract class Person<P extends Person<P>> {
protected final String firstName;
protected final String lastName;
protected final int age;
public <T extends AbstractBuilder<P, T>> Person(AbstractBuilder<P, T> builder) {
this.firstName = builder.firstName;
this.lastName = builder.lastName;
this.age = builder.age;
}
}
static abstract class AbstractBuilder<P extends Person, T extends AbstractBuilder<P, T>> {
protected final String firstName;
protected final String lastName;
protected int age;
public AbstractBuilder(String firstName, String lastName) {
this.firstName = firstName;
this.lastName = lastName;
}
abstract T self();
abstract P build();
T age(int age) {
this.age = age;
return self();
}
}
Utilizing the above, creating a class Manager and its Builder yields following code
static class Manager extends Person<Manager> {
public <T extends AbstractBuilder<Manager, T>> Manager(AbstractBuilder<Manager, T> builder) {
super(builder);
}
}
static class ManagerBuilder extends AbstractBuilder<Manager, ManagerBuilder> {
public ManagerBuilder(String firstName, String lastName) {
super(firstName, lastName);
}
#Override
ManagerBuilder self() {
return this;
}
#Override
Manager build() {
return new Manager(this);
}
}
Managerand its Builder, or any other employee can be extended with more fields.
I have always been programming in java, and recently i started learning some c++.
In C++ it is conventional to set setter params as const, why don't we see this as much in java ?
I mean are there any disadvantages to creating a setter like so:
public void setObject(final Object o){ this.o=o; }
vs
public void setObject(Object o){ this.o=o; }
The first one should enforce for Object param o to stay constant through the whole set function, not ?
Edit:
A final param would enforce this NOT to happen :
public void setName(String name){
name="Carlos";
this.name=name;
}
The user will never be able to set the name different from "Carlos"
There's little advantage to setting a Java method parameter as final since it does not stop someone from changing the parameter reference's state within the method. All it prevents is the re-assignment of the parameter variable to something else, which does nothing to the original reference, and it allows for use of the parameter in anonymous inner classes. If you wanted true safety in this situation, you'd strive to make your parameter types immutable if possible.
Edit
You've posted:
public void setObject(Object o){
o++; // this does not compile
this.o=o;
}
Which mixes primitive numeric and reference type. It only makes sense if o is an Integer or other numeric wrapper class, and even so, making it final would not prevent someone from creating:
private void setI(final Integer i) {
this.i = 1 + i;
}
But neither your code nor this code above would affect the parameter object on the calling code side.
Edit
OK now you've posted:
public void setName(String name){
name="Carlos";
this.name=name;
}
But then someone could write
public void setName(final String name){
this.name= name + " Carlos";
}
Here's where the danger comes and where final doesn't help. Say you have a class called Name:
public class Name {
private String lastName;
private String firstName;
public Name(String lastName, String firstName) {
this.lastName = lastName;
this.firstName = firstName;
}
public String getLastName() {
return lastName;
}
public void setLastName(String lastName) {
this.lastName = lastName;
}
public String getFirstName() {
return firstName;
}
public void setFirstName(String firstName) {
this.firstName = firstName;
}
}
And then a class, Foo, with a Name field and a setter. This is dangerous code:
class Foo {
private Name name;
public void setName(final Name name) {
name.setFirstName("Carlos");
this.name = name;
}
}
Because not only does it change the state of the field, it changes the state of the Name reference in the calling code, and the final modifier won't help one bit. The solution: make Name immutable.
e.g.,
import java.util.Date;
// class should be declared final
public final class BetterName {
private String lastName;
private String firstName;
private Date dateOfBirth;
public BetterName(String lastName, String firstName, Date dob) {
this.lastName = lastName;
this.firstName = firstName;
// make and store a private copy of non-immutable reference types
dateOfBirth = new Date(dob.getTime());
}
// only getters -- no setters
public String getLastName() {
return lastName;
}
public String getFirstName() {
return firstName;
}
public Date getDateOfBirth() {
// return copies of non-immutable fields
return new Date(dateOfBirth.getTime());
}
}
Okay, a final parameter/variable cannot be assigned to. As the java compiler needs to be capable to determine if a variable/parameter is actually final (for anonymous inner classes), optimization is no factor AFAIK.
It is more that C++ has a larger tool set, which java tried to reduce. Hence using C++ const string& is important, saying
The string is passed by pointer, access is automatically dereferenced.
If the actual argument is a variable, the variable itself is not changed.
Mind there might be a conversion operator for passing something else than a const string&.
Now java:
Java does not allocate objects on the stack, only keeps primitive types and object handles on the stack.
Java has not output parameters: a variable passed to a method call will never change its immediate value.
Back to your question:
As a setter in java mostly would not benefit from a final parameter.
A final will be a contract to not use the variable for a second assignment.
However:
public final void setXyz(Xz xyz) {
this.xyz = xyz;
}
is more useful: this method cannot be overriden, and hence may be safely used in a constructor. (Calling an overriden method in a constructor would be in a context of a still not initialized child instance.)
Im getting class name (string) and the class have few sets method and
since Its dynamic (I can get any class) I need to use all the sets method and update it with data .
how can I do that ?
To get the class field I'm using the following code
className = obj.getClassName();
Class<?> classHandle = Class.forName(className);
for example here I need to update firstName and last name
public class Person {
private String id;
private String firstName;
private String lastName;
public void setLastName(String lastName) {
this.lastName = lastName;
}
public void setfirstName(String firstName) {
this.firstName = firstName;
}
or different class here i need to set the salary and the job description
public class Job {
private double salery;
private String jobDescr;
public void setSalery(double salery) {
this.salery = salery;
}
public void setJobDescr(String jobDescr) {
this.jobDescr = jobDescr;
}
}
For starters, What you've done is good. I assume you have a Map<String, Object> of the attributes to be set: attributeMap.
//this is OK
className = obj.getClassName();
Class<?> classHandle = Class.forName(className);
//got the class, create an instance - no-args constructor needed!
Object myObject = classHandle.newInstance();
//iterate through all the methods declared by the class
for(Method method : classHandle.getMethods()) {
//check method name
if(method.getName().matches("set[A-Z].*")
//check if it awaits for exactly one parameter
&& method.getParameterTypes().length==1) {
String attributeName = getAttributeName(method.getName());
//getAttributeName would chop the "set", and lowercase the first char of the name of the method (left out for clarity)
//To be extra nice, type checks could be inserted here...
method.invoke(myObject, attributeMap.get(attributeName));
}
}
Of course, a lot of exception handling is to be done, this is just a basic idea of what is to be done...
Recommended reading:
Class
Class.getMethods()
Method
Method.invoke()