Make pure immutable class - java

I have following classes :
Emp.java
final public class Emp {
private Integer id;
private String name;
private Department department;
public Emp(Integer id, String name, Department department) {
this.id = id;
this.name = name;
this.department = department;
}
public Department getDepartment() {
return department;
}
public Integer getId() {
return id;
}
public String getName() {
return name;
}
}
Department.java
public class Department {
private Integer id;
private String name;
public Department(Integer id, String name) {
this.id = id;
this.name = name;
}
public Integer getId() {
return id;
}
public String getName() {
return name;
}
public void setId(Integer id) {
this.id = id;
}
public void setName(String name) {
this.name = name;
}
}
EmployeeTest.java
public class EmployeeTest {
public static void main(String args[]) {
Department dept1 = new Department(1, "dept1");
Emp emp = new Emp(1, "emp1", dept1);
emp.getDepartment().setName("dept2");
System.out.println("emp = "+emp);
}
}
Here Emp class is not purely an immutable class because somehow I am able to change the values of Department (as shown in the example).
What are the best possible changes which will make Emp class a pure Immutable class ?

In getters for non-primitive field, use this structure
public class Line {
private final Point start;
private final Point end;
public Line(final Point start, final Point end) {
this.start = new Point(start);
this.end = new Point(end);
}
public Point getStart() {
return new Point(start);
}
public Point getEnd() {
return new Point(end);
}
}
So, simply create new instance of department that is equals to previous
P.S. In my example you can see pure immutable class
EDIT:
Also you can add to Department class copy-contructor
public Department(final Department dep)
{ ... }
And to Employer
getDepartment()
{
return new Department(department);
}

See Efffective Java:
Item 15: Minimize mutability – 5 rules to follow.
Don’t provide any methods that modify the object’s state
Ensure that the class can’t be extended
Make all fields final
Make all fields private
Ensure exclusive acess to any mutable components

If you don't like removing setters and do initialization in a constructor, you can think about returning immutable (from the point of view of the Emp class) objects, which will web objects' copies, in getters (see https://stackoverflow.com/a/128712/1579085).
final public class Emp {
private Integer id;
private String name;
private Department department;
public Emp(Integer id, String name, Department department) {
this.id = id;
this.name = name;
this.department = (Department) department.clone();
}
public Department getDepartment() {
return (Department) department.clone();
}
public Integer getId() {
return id;
}
public String getName() {
return name;
}
}
And implement the method clone() in Department (which will implement the interface Cloneable) of course.
This approach is suitable, if you need to be able to modify Department, but the objects of the Emp class should be safe from those outer modifications.

make all attributes final, and remove all setters

Implement clone() in Department and make Emp return a clone of department in getDepartment().
If references to Department used in constructing Emp are available after construction, then Emp's constructor should clone given Department.

Related

How to return an instance of Inherited class from parent abstract class

I'd like to solve such problem. I have some abstract class and a concrete class with setters that return the instance of that class:
#MappedSuperclass
public abstract class BaseEntity implements Serializable {
private Integer id;
public Integer getId() {
return id;
}
public BaseEntity setId(Integer id) {
this.id = id;
return this;
}
}
next abstract:
#MappedSuperclass
public abstract class NamedEntity extends BaseEntity {
private String name;
public String getName() {
return name;
}
public NamedEntity setName(String name) {
this.name = name;
return this;
}
}
and finally a concrete class:
#Entity
public class Person extends NamedEntity {
private String address;
public String getAddress() {
return address;
}
public void setAddress(String address) {
this.address = address;
}
}
I'd like to use this kind of builder but in current setup it's not working due to different return types of parent setters
public Person build() {
Person person = new Person()
.setId(1); //return BaseEntity instead of Person
.setName("name") //returns NamedEntity instead of Person
.setAddress("foo"); //return Person!
return person;
}
of course ther's a workaround with overriden setters but.... can it be done other way using generics?
#Override
public Person setId(Integer id) {
super.setId(id);
return this;
}
#Override
public Person setName(String name) {
super.setName(name);
return this;
}
Thanks for all the sugestions
I know the builder pattern, but in this particular case is the same workaround as overriding the methods setId and setName
The point here is:
it is possible that setId method will return the instance of child class the method is called from
let's say I'd like to put a complex object to my builder (why not?):
public class Person extends NamedEntity {
private String address;
... getters/setters
public Builder builder() {
return new Builder();
}
public final static class Builder {
private final Person person;
private Long id;
private String name;
private String address;
private Builder() {
this.person = new Person();
}
public Builder withId(Long id) {
person.setId(id);
return this;
}
..... other setters
public Builder withDto(PersonDTO dto) {
person
.setId(dto.getId())
.setName(dto.getName())
.setAddress(dto.getAddress()
}
public Person build() {
return person;
}
}
}
as you may guess the person.setId returns instance of BaseEntity
You can use the same trick as enums (Enum), a generic type parameter for the child class.
#MappedSuperclass
public abstract class BaseEntity<E extends BaseEntity<E>> implements Serializable {
private Integer id;
public Integer getId() {
return id;
}
protected final E getThis() {
return this;
}
public E setId(Integer id) {
this.id = id;
return getThis();
}
}
#MappedSuperclass
public abstract class NamedEntity<E extends NamedEntity<E>> extends BaseEntity<E> {
private String name;
public String getName() {
return name;
}
public E setName(String name) {
this.name = name;
return getThis();
}
}
For child classes of Person you need not continue with this pattern.
#Entity
public class Person extends NamedEntity<Person> {
private String address;
public String getAddress() {
return address;
}
public Person setAddress(String address) {
this.address = address;
return this;
}
}
Now you can do_
Person einstein = new Person()
.setId(76)
.setName("Albert")
.setAddress("Princeton, New Jersey");
The alternative is a Builder pattern, however it has the same inheritance problem, and you might end up with *.Builder classes inheriting from parent Builder classes.
I would even say it is not worth this boiler plate code, just for a fluent API (chained calls). The criteria API for instance does hardly need using created objects, and the passed values for the setters must come from some code too.
Also setters implies the classes are mutable. It would be much nicer if most fields were immutable. With entity classes unrealistic, but setters are an ugly initialisation. When possible use constructors/builders without setters.
You can implement the Builder pattern by introducing a nested class Builder with a set of self-returning methods (i.e. returning an instance of Builder) which can be chained in a fluent way.
Method Builder.build() should return an instance of Person.
Note that you setters of your entities can be void.
That's how implementation might look like:
public class Person extends NamedEntity {
private String address;
public String getAddress() {
return address;
}
public void setAddress(String address) {
this.address = address;
}
public static class Builder {
private Person person;
public Builder() {
this.person = new Person();
}
public Builder name(String name) {
person.setName(name);
return this;
}
public Builder address(String address) {
person.setAddress(address);
return this;
}
public Builder id(Integer id) {
person.setId(id);
return this;
}
public Person build() {
return person;
}
}
}
Usage example:
Person person = new Person.Builder()
.name("Alice")
.address("Wonderland")
.id(1)
.build();
Note:
There could be multiple ways to obtain an instance of Builder. You can introduce in the Person class a static method builder() returning a new Builder, or static methods like withName(String), withId(Integer) might also be handy (for inspiration have a look at User class from Spring Security).
When dialing with immutable objects, Builder class should have all the field of the target class duplicated instead of keeping the reference to the target object. And in such case, method build() would be responsible for constructing an instance of the target type.

Realm for Android: Many to Many Relationship

I am trying to learn Realm basics by implementing a simple Android project.
The idea is that user have several items and several item lists and an item can be added to any of these lists and a list can have many items. Therefore, there is a many to many relationship between Item and List objects. Here are my objects.
public class Item extends RealmObject {
#PrimaryKey
private String id;
private String name;
private boolean isDone;
public String getId() {
return id;
}
public void setId(String id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public boolean isDone() {
return isDone;
}
public void setDone(boolean done) {
isCollected = done;
}
}
public class List extends RealmObject {
#PrimaryKey
private String id;
private String name;
private RealmList<Item> items;
public String getId() {
return id;
}
public void setId(String id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public RealmList<Item> getItems() {
return items;
}
public void setItems(RealmList<Item> items) {
this.items = items;
}
}
My problem is, the field isDone might be different depending on the item's status in a given list. But when I update this field in a list, all the other items added to different lists get updated too. Since they are using the same object it makes sense but that is not to behavior I want. Is there a Realm way to create a pivot table/object with an extra column/field (in that case isDone) ?
Any help would be appreciated.
The problem is that the isDone property of Item doesn't truly belong to Item. If you can set the same Item in multiple Lists, then the property that a given task is deemed complete within a given List is the property of the List.
public class Item extends RealmObject {
#PrimaryKey
private String id;
private String name;
//private boolean isDone;
#LinkingObjects("completedItems")
private final RealmResults<List> tasksCompletedIn = null;
public String getId() {
return id;
}
public void setId(String id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
//public boolean isDone() {
// return isDone;
//}
//public void setDone(boolean done) {
// isDone = done;
//}
}
public class List extends RealmObject {
#PrimaryKey
private String id;
private String name;
private RealmList<Item> items;
private RealmList<Item> completedItems;
Then you know if it's a completed item if completedItems.contains(item) (where item is a managed object, or overrides equals to check against only id)

Is there any performance or any other issues if I use a generic setter method in place of multiple setter methods in POJO or this is a bad practice?

I want to use a generic setter method which will take Object as argument and inside the setter I'll set the value of the property. For example, in place of
public class Student {
private Long id;
private String name;
private int age;
public Long getId() {
return id;
}
public void setId(Long id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
}
I want to use this :
public class Student {
private Long id;
private String name;
private int age;
public Long getId() {
return id;
}
public String getName() {
return name;
}
public int getAge() {
return age;
}
public void setValues(Object propertyValue) {
if(propertyValue instanceof Long){
this.id = (Long) propertyValue;
}else if(propertyValue instanceof String){
this.name = (String) propertyValue;
}else if(propertyValue instanceof Integer){
this.age = (Integer) propertyValue;
}
}
}
Note: In my POJO, all the property have unique type (No duplicate type for multiple properties).
For one, casting should always be avoided.
Second it's slower than having setters (no need to check instanceof)
Third it's even taking up more memory! You use 10 lines to replace 3 setters which would require only 9 lines :P
Fourth it's very ugly! But hey, that's just my opinion
Fifth it's not flexible, if you add anything to your pojo, you have to carefully add the check or maybe even revert to setters anyway

trouble with spark cassandra connector in java

I am trying to query cassandra from spark in java. Below is the code to fetch data but mapToRow method takes two parameter. first is class and second is ColumnMapper. How to get instance of the ColumnMapper class in java. Googling it recommends creating object of derived class JavaBeanColumnMapper but didn't find how JavaBeanColumnMapper class should be instantiated.
List<String> dates = Arrays.asList("2015-02-02","2015-02-08");
JavaRDD<DailyTaxlot> openTaxlots = CassandraJavaUtil.javaFunctions(sc).
cassandraTable("wedbush_praveen_testing", "cf_taxlots",CassandraJavaUtil.mapToRow(DailyTaxlot.class),).
where("openclosetag=?","Open").where("rundate IN",dates);
Any lead will be appreciated.
Have a look at the example from the spark-cassandra-connector here:
JavaApiDemo.java
In the example you can see how the Person bean class is defined. The API will instantiate it as needed for each row.
JavaRDD<Person> rdd = CassandraJavaUtil.javaFunctions(sc).cassandraTable("test", "people", mapRowTo(Person.class));
// Bean definition
public static class Person implements Serializable {
private Integer id;
private String name;
private Date birthDate;
public static Person newInstance(Integer id, String name, Date birthDate) {
Person person = new Person();
person.setId(id);
person.setName(name);
person.setBirthDate(birthDate);
return person;
}
public Integer getId() {
return id;
}
public void setId(Integer id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public Date getBirthDate() {
return birthDate;
}
public void setBirthDate(Date birthDate) {
this.birthDate = birthDate;
}
}

How to map the simplevalue type of Set collection using annotation

Could anyone please explain me how to use Simple value type of Set, by using annotation mapping without using one to many relationship. I have shown example in this below code. In this code I have person name and person petnames, here the person petname is the simple value type of the Set. I want map to the person name in the one table in the one table and petnames in the other table.
private static final long serialVersionUID = 1L;
#Id
#GeneratedValue(strategy = GenerationType.AUTO)
private Long id;
private String name;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public Long getId() {
return id;
}
public void setId(Long id) {
this.id = id;
}
private Set<String> petname;
public Set<String> getPetname() {
return petname;
}
public void setPetname(Set<String> petname) {
this.petname = petname;
}
public boolean addPetNames(String a) {
return petname.add(a);
}
The JPA annotation works like this: (quite self explaining I think)
#ElementCollection
#CollectionTable(
name="PET_NAMES",
joinColumns=#JoinColumn(name="PERSON_ID")
)
#Column(name="PET_NAME")
private Set<String> petname;

Categories