-2

We all know that objects in Java can be modified.

I want to present three options when working with an object and indicate their advantages and disadvantages.

public class SetterApplication {
    public static void main(String[] args) {
        User john = new User("John", 22);
        increaseAge(john, 2);
        System.out.println(john);       // User{name='John', age=24}

        User johnUpper = upperName(john);
        System.out.println(johnUpper);  // User{name='JOHN', age=24}
        System.out.println(john);       // User{name='JOHN', age=24}

        User johnLower = lowerName(john);
        System.out.println(johnLower);   // User{name='john', age=24}
        System.out.println(johnUpper);   // User{name='JOHN', age=24}
    }

    /**
     * Case #1
     * change the object passed in and return nothing
     * @param user user
     * @param inc inc
     */
    public static void increaseAge(User user, Integer inc) {
        user.setAge(user.getAge() + inc);
    }

    /**
     * Case #2
     * change the passed object and return the changed object
     * @param user user
     * @return User
     */
    public static User upperName(User user) {
        user.setName(user.getName().toUpperCase());
        return user;
    }

    /**
     * Case #3
     * do not change the passed object and return a completely new object
     * @param user user
     * @return User
     */
    public static User lowerName(final User user) {
        return new User(user.getName().toLowerCase(), user.getAge());
    }
}

class User {
    private String name;
    private Integer age;

    public User(String name, Integer age) {
        this.name = name;
        this.age = age;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public Integer getAge() {
        return age;
    }

    public void setAge(Integer age) {
        this.age = age;
    }

    @Override
    public String toString() {
        final StringBuilder sb = new StringBuilder("User{");
        sb.append("name='").append(name).append('\'');
        sb.append(", age=").append(age);
        sb.append('}');
        return sb.toString();
    }
}

"Case #1" - the most common way, but to contain the corresponding disadvantage, is that the existing object is modified. But this behavior is predictable, since we do not return anything.

"Case #2" - also often found in code. But this case is misleading - because it returns a modified transferred object, which can be misleading that we are returning a new object, but this is not true.

"Case #3" - this method is the most fashionable way. Where we do not modify the transferred object and return a new object. But in this method there is a huge disadvantage that in Java it is not easy to implement (deep) cloning and the second is that it can be very resource-intensive, the object can be very large.

My question is which of the three options is preferable? What do you prefer to use? And which of the options do you consider the worst?

FreeOnGoo
  • 868
  • 1
  • 8
  • 26
  • 2
    All three are bad because they are `static`. – Marvin Feb 25 '19 at 19:33
  • @Marvin very funny, it's just for example – FreeOnGoo Feb 25 '19 at 19:35
  • https://stackoverflow.com/a/1253519/2345933 – Adam Siemion Feb 25 '19 at 19:35
  • In case 3, if all methods that would mutate the object follow this pattern of returning a new object, then deep cloning isn't a concern, because the object including any others it contains will never change. Indeed, in this case, the object(s) should be immutable and the fields should all be final. – David Conrad Feb 25 '19 at 19:37

1 Answers1

1

This is a broad topic. Anyway immutability is always to prefer.
As coding immutable classes is usually tedious (you may want to provide a copy constructor, or a copy method. And what if I want to copy only a certain subset of its properties?) I use the Immutables library.

Just don't make your class implements Cloneable because you want to use the clone method.
Avoid that one. You'd also need an explicit cast.

LppEdd
  • 20,274
  • 11
  • 84
  • 139
  • Yes, I understand that immutability is better, but everyone forgets about costs. It just seems that you only need to work with immutable objects, forgetting the disadvantages – FreeOnGoo Feb 25 '19 at 19:43
  • 1
    @FreeOnGoo that depends on how heavy the object to copy is. The advantages immutability offers are too many to even think about its "costs". Start seeking for absolute performance or memory optimization when it matters. – LppEdd Feb 25 '19 at 19:46