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?
Related
I am new to Java. I have a problem to solve, but I don't quite understand how constructors work. I understand how to create a superclass and a subclass but I don't understand the constuctors within them (or how they actually work - I have done rediculous amounts of research on constructors, but it's just not making much sense).
I am trying to write a program that creates a superclass called Employees. This Employee class has instance variables employeeId (which is an integer) and employeeName (which is a String).
The subclass is called Manager. The Manager subclass has an instance variable called employeeTitle (which is a String). It also has a method with the name of managerDetails(). ManagerDetails() is supposed to display the employeeId, employeeName, and the employeeTitle.
This is what I have so far:
package tryingoutjava;
public class TryingOutJava {
class Employee {
int employeeId;
String employeeName;
void Employee() {
}
}
class Manager extends Employee {
String employeeTitle;
void managerDetails() {
}
}
public static void main(String[] args) {
}
}
I am very confused on how to set up the constructors for the superclass and the subclass, or even what a constructor really looks like. I've seen examples all over the internet, but no one actually highlights the actual part that is the constructor, or how everything is linked visually, which is what helps me learn.
I guess I'm also having issues with understanding how to set up a method that calls on an object. If anyone has the time to help, it would greatly be appreciated. Thanks!
I guess you want something like this. Be noted, that it is a good idea to separate classes one-per-file in this case, as they are separate entities here. It is a good idea to limit data access to entity fields, as such using encapsulation.
Employee.java:
package tryingoutjava;
public class Employee {
// Protected access because we want it in Manager
protected int employeeId;
protected String employeeName;
public Employee(int employeeId, String employeeName) {
this.employeeId = employeeId;
this.employeeName = employeeName;
}
}
Manager.java:
package tryingoutjava;
public class Manager extends Employee {
private String employeeTitle;
public Manager(String employeeTitle, int employeeId, String employeeName) {
// Use super to invoke Employee constructor
super(employeeId, employeeName);
this.employeeTitle = employeeTitle;
}
// Just create a simple string describing manager
#Override
public String toString() {
return "Manager{" +
"employeeTitle='" + employeeTitle +
"employeeId=" + employeeId +
", employeeName='" + employeeName + '\'' +
'}';
}
}
Application.java:
package tryingoutjava;
public class Application {
// Example of construction plus printing of Manager data
public static void main(String[] args) {
Employee davie = new Employee(1, "Dave The Cable Guy");
Manager tom = new Manager("CFO", 2, "Tomas");
System.out.println(tom.toString());
}
}
Constructors (most often than not) just delegate construction of parent through super invocation. While there are other techniques, like Builder pattern, this is the most basic and understandable approach. There are several other ways to do this, but this should get you started, hope it helps!
Purpose of Constructor
constructor is a method like other method but it is called when instantiate (or create a object from your class) for initialize your object for first use or later use. for example a class like Student must created (instantiated) when we give it name and family name for example. Without them, create a Student is not good because maybe we forget to give it proper name and use it incorrectly. constructor forces us to provide minimum things needed for instantiating objects from classes.
Constructor implementation in inheritance
About inheritance, it is different. When you want to create a Student which is a Human (extends Human) you must first create Human inside your Student and set special feature for your Student like ID which is not for Human (Human has name and etc). so when you create a Student with constructor, the super constructor (for Human) is called too.
What do we do in constructor
as I mentioned, we provide default value for our properties which must set them before creating and using object. (for using them properly) every subclass call super class constructor implicitly with super() but if super class doesn't have any default constructor (constructor with no argument) you must explicitly say super(...) at the first lien of subclass constructor (otherwise compile error)
What is the program steps when using constructor (Advanced)
super class static constructor and static variable (read by self if you want to know more about things I say here)
subclass class static constructor and static variable
super class variable and block constructor
super class constructors
sub class variable and block constructor
sub class constructors
I only mentioned 4 & 6.
I try to explain completely. My English is not good. I'm sorry.
If you know how a method works, then you know how a constructor works. The constructor is simply a special method that allows you to execute some code before the object is created.
Person p = new Person("Bob", 25); // Calls constructor Person(String name, int age)
Then in the constructor you can do things like assign initial values to any instance variables.
private String name;
private int age;
public Person(String name, int age) {
this.name = name;
this.age = age;
}
If the class is a subclass you need to call a constructor of the parent class before the object is created unless the parent class has a constructor with no parameter in which case java can call it for you if you don't specify anything. Here Worker extends Person.
private String occupation;
public Worker(String name, int age, String occupation) {
super(name, age) // Calls constructor Person(String name, int age)
this.occupation = occupation;
}
I guess you can achieve what you want in a single file via the code snippet below:
You can copy paste it in your code and it should work.
You can see how the constructor of parent class is being called by the help of super() and also the methods. Here I have used methods like getEmployeeTitle() which should help you get an overview on how to write methods. I have also overridden the toString() method so that you can understand how to override Object class' useful methods like toString().
Note : Although I have created all the classes in one code snippet for the sake of simplicity , but it is highly recommended that you create a separate file for each of these classes.
class Employee {
int employeeId;
String employeeName;
Employee(int employeeId, String employeeName) {
this.employeeId = employeeId;
this.employeeName = employeeName;
}
}
class Manager extends Employee {
private String employeeTitle;
Manager(int employeeId, String employeeName, String employeeTitle) {
super(employeeId, employeeName);
this.employeeTitle = employeeTitle;
}
public String getEmployeeTitle() {
return employeeTitle;
}
#Override
public String toString() {
return ("employeeId: " + employeeId + ", employeeName: " + employeeName + ", employeeTitle" + employeeTitle);
}
}
public class TryingOutJava {
public static void main(String[] args) {
Manager manager = new Manager(007, "John Doe", " Sr. Manager");
System.out.println(manager);
System.out.println(manager.getEmployeeTitle());
}
}
The nested builder patterns that I've come across online usually have something like this:
class Person{
private int id;
private String name;
private int age;
... so on
private Person(Builder builder){
this.id = builder.id;
this.name = builder.name;
this.age = builder.age;
}
public static class Builder{
private int id;
private String name;
private int age;
... so on
public Builder id(int id){
this.id = id;
return this;
}
public Builder name(String name){
this.name = name;
return this;
}
.... so on
public Person build(){
return new Person(this);
}
}
}
My question is, is it necessary to duplicate fields in Person and Builder? It seems like a lot of redundant code. And my second question is, would the following code be a viable replacement, why or why not?
class Person{
private int id;
private String name;
private int age;
... so on
private Person(){}
public static class Builder{
private Person person = new Person();
public Builder id(int id){
this.person.id = id;
return this;
}
public Builder name(String name){
this.person.name = name;
return this;
}
.... so on
public Person build(){
return person;
}
// UPDATED -- another build method
public Person build(){
Person built = this.person;
this.person = new Person();
return built;
}
}
}
Note: I understand this topic may be opinionated and there may not be a "right" answer, but I just want to hear different ideas and opinions. I'm not looking for the ultimate truth.
Your code would be fine as long as:
you keep your Person member variables private (you are doing so)
you don't provide methods that allow modification of those member variables (the code you show does not do, but you have omitted parts of it)
those member variables are immutable or you ensure getters provide copies of them. usually better that the members are already immutable (hint: even java collections). otherwise you will be creating instances on each getX call.
once Builder.build is called, noone must be able to modify Person instance state, not even Builder itself. this is not happening in the code you posted
builder does not expose "temporal instance" being built (if any at all). No instance must be exposed aside the return of build method.
there are opinions about which is the preferred way or not, matter of taste most of the time. But in terms of being right or not, that approach would be fine with some modifications. At the end, what happens before the build is called is purely internal to the Builder. It's an implementation matter. The important thing is that the previous rules are met.
To fix rule 4: your Builder.build method should return a deep clone of the temp instance being used (there are ways to achcieve that without needing to specify each field). Or, you should have a flag in builder that forbids calling any other method on Builder instance, once build has been called.
Side note: i usually prefer that Builder class also uses private constructor. I would have this on Person class:
public static Builder builder() {
return new Builder();
}
This can give you more flexibility on the way to initialize the Builder, or even you can have several builder methods doing not exactly the same stuff in terms of "preconfiguring" the builder (and since they are methods, you have more flexibility on naming than on constructors :) )
I have a given web service. (This is only an example, the real one is more complex, but it has the same problem.) The service has three methods and all three methods have a person as parameter and need other things from it. (I can't change the entity or methods.)
Entity (Person) (It has only a default constructor):
private String name;
private int age;
private Address address;
private List<String> hobbies;
private List<Person> friends;
Method1 needs name and age.
Method2 needs address name and age.
Method3 needs all.
I need to fill the object from my own objects. I need to write a "converter". What is the best practice for it?
My solutions:
Builder Pattern with builds for three methods.
Set all attributes and send unhandled overhead (bad solution in my eyes).
Creating a builder that sets only required fields sounds good.
You can inherit from this class for each of your needs and implement your own constructors
public class Target {
// fields
}
public class Purpose1 extends Target {
public Purpose1(String name, int age) {
// set fields or do whatever you wish
}
}
public class Purpose2 extends Target {
public Purpose2(String address, String name, int age) {
// set fields or do whatever you wish
}
}
public class Purpose3 extends Target {
public Purpose3(...) {
// set fields or do whatever you wish
}
}
And then you may use instances of subclasses where class Target is required.
I think you can get what you want with a suitable usage of decorator pattern:
https://en.wikipedia.org/wiki/Decorator_pattern
I was doing some reading here. The user suggested that
if you plan on subclassing and want the validation setter available,
declare it protected final instead of private.
why declare a method protected final when I could declare it private and have the constructor in the base class set the variables.
Example:
public class Person {
private String firstName;
private String lastName;
public Person(String firstname,String lastname) throws InvalidDataException
{
setFirstname( firstname);
setLastname(lastname);
}
public void personFirstName(String firstName) throws InvalidDataException {
setFirstname(firstName);
}
public void personLastName(String lastname) throws InvalidDataException {
setLastname(lastname);
}
public String getFirstName() {
return firstName;
}
public String getlasttName()
{
return lastName;
}
private void setFirstname(String firstname) throws InvalidDataException{
if( firstname == null ||firstname.length() < 1) {
throw new InvalidDataException("First Name Cannot be Empty");
}
this.firstName=firstname;
}
private void setLastname(String lastname) throws InvalidDataException {
if( lastname == null ||lastname.length() < 1) {
throw new InvalidDataException("Last Name Cannot be Empty");
}
this.lastName = lastname;
}
}
public class Professor extends Person {
private String professorID;
public Professor(String professorID,String firstname, String lastname) throws InvalidDataException {
super(firstname, lastname);
// TODO Auto-generated constructor stub
setProfessorID(professorID);
}
public void setID(String professorID) throws InvalidDataException{
setProfessorID(professorID);
}
public String getID()
{
return this.professorID;
}
private void setProfessorID(String ID) throws InvalidDataException{
if( ID == null ||ID.length() < 1) {
throw new InvalidDataException("ID Cannot be Empty");
}
this.professorID=ID;
}
public void printData()
{
System.out.println("Professor ID: " + this.getID() + " First Name: " + this.getFirstName() + " Last Name: " + this.getlasttName());
}
}
In what situation would I want to declare the private methods in Person to be protected final? My subclass Professor can access them through the constructor in the base class.
protected
The protected key word is an access modifier that allows subclasses to access this resource. In this case, the method.
final
The final key word is a polymorphic restriction that prevents subclasses from redefining a given resource. Again, in this case, the method.
With these definitions in mind, this creates a validation method that the subclass can still access without being able to change it. In short, no subclasses can violate the terms of the validation. By just putting the calls in the constructor, this means that subclasses can not make validation calls anywhere else. They have to create a new object every time they want to test, which is obviously not desirable.
Doing it this way makes it more testable, but allows subclasses as much flexibility as they should be permitted while not breaking the validation rules.
That's for the case where the subclass should be able to set the value. Since you can't foresee the subclasses, you better make the assumption that all values can be set by a third value. For instance in some culture's a women takes the name of her husband. For instance:
public class Women extends Person {
public void marry (Person person) {
setLastName(person.getLastName());
}
}
The book probably suggests not to make the field protected, after all each class must guarantee that its own state is valid. By thus rewriting a validator yourself, you could invalidate the state from the super class point of view.
It is for instance reasonable to assume that a persons name doesn't contain digits. You can implement this logic in the setter-validator. If you however declare the field protected, one could overrule this.
Making the method public, as you did, is probably not adviseable, at least not in a general case. That would imply every object has the right to set a persons name.
Besides extending, the use for protected can be for Managing Classes.
See, protected does not mean only a child class has access to the field in question. But any class within the same package.
Say you have an abstract class Entity
And another class SpecificEntity1 extends Entity
And another class SpecificEntity2 extends Entity
but you want a way to keep track of all entities.
What you do is you make the constructors for the specific classes protected
put all of the classes in the same package and create another class in that package like EntityManager with a createEntity method. that way you can only create your entities using that class outside of the package.
This is not the first time that I've found myself in a situation in which I have to adapt two objects with almost the same data, for example:
User.java (Object returned from another library)
private String name;
private String surname;
private String email;
private String telephone;
...
getters and setters();
constructor();
MyUser.java
private String name;
private String surname;
private String email;
private String telephone;
...
getters and setters();
constructor();
I usually create a method to convert one object into another one, like this:
User m1 = new User();
MyUser m2 = new MyUser();
m2.setName(m1.getName());
m2.setsurmame(m1.getsurname());
...and so on...
Does anybody know a different way to do this kind of stuff?
Use Object Composition For objects that you create using the other library, create an instance of ExternalUser. But if you want to create them locally, create a BrandNewUser. Then you can just treat them the same way, with one version using the pass-through composition methods, and the ones created by your code using your own internal implementation.
You can create your object like this:
public interface MyUser {
// all the methods you need
String getSurname();
}
public class ExternalUser implements MyUser {
private User _user;
private ExternalUser() { }
public ExternalUser(User u) {
this._user = u;
}
public String getSurname() {
return _user.getSurname();
}
}
public class BrandNewUser implements MyUser {
private String _surname;
public ExternalUser(String name, String surname) {
this._surname = surname;
}
public String getSurname() {
return _surname;
}
}
There is a AutoMapper project in C Sharp.
In the gist of it it provides an easy way of mapping properties from a source instance to a destination instance where the source and destination instances can be of different classes.
this link shares some interesting thoughts about similar projects in Java : Automapper for Java
One thing you can do is pass that User object in a method of MyUser class or constructor of MyUser class and then perform those setters.
Using constructor :
public MyUser(User u){
setName(u.getName());
setSurname(u.getSurname());
...
}
Or creating a seperate method :
public void setMyUser(User u){
setName(u.getName());
setSurname(u.getSurname());
...
}
Then you can use it like this:
User u = new User();
//hope all values are set in User u object
MyUser m = new MyUser(u);
In cases where appropriate, refactor those objects to inherit from each other, rather than duplicate properties and logic.
In cases where the objects must remain distint, you can use any one of a variety of clone tools to perform deep copies from object to object. Here is a decent, non-exhaustive list:
Orika
Dozer
PropertyUtils
Maybe you can use beanutils which provides copy properties function.
http://commons.apache.org/beanutils/