3

How can we create constructor, to set different values that are from same data type?

Its impossible two create two identical constructors:

public User(int age, String name){
}  
public User(int age, String surname){
}

User user1 = new User(33, Jack);
User user2 = new User(33, Sparrow);

Since both name and surname are from same data type, its impossible to know which value the user has meant to set.


We can create a constructor that has all the properties and then pass null for unset arguments.

public User(int age, String name, String surname){
}  

User user1 = new User(33, Jack);
User user2 = new User(33, null, Sparrow);


There is a way to make it, using HashMap imitating the javascript object literal.

package javaapplication;

import java.awt.Color; 
import java.util.HashMap;

public class JavaApplication {

    public static class User {

        public int age;
        public String name;
        public String surname;
        public Color hairColor;

        public User(HashMap<String, Object> arguments) {

            if (arguments.containsKey("hairColor")) {
                this.hairColor = (Color) arguments.get("hairColor");
            }

            if (arguments.containsKey("name")) {
                this.name = (String) arguments.get("name");
            }

            if (arguments.containsKey("surname")) {
                this.surname = (String) arguments.get("surname");
            }

            if (arguments.containsKey("age")) {
                this.age = (int) arguments.get("age");
            }
        }
    }

    public static void main(String[] args) {

        User jack1 = new User(new HashMap<String, Object>() {
            {
                put("hairColor", Color.RED);
                put("name", "Jack");
                put("age", 33);
            }
        });
        System.out.println(jack1.hairColor);  // java.awt.Color[r=255,g=0,b=0]
        System.out.println(jack1.surname);    // null
        System.out.println(jack1.name);       // Jack
        System.out.println(jack1.age);        // 33

        User jack2 = new User(new HashMap<String, Object>() {
            {
                put("hairColor", Color.RED);
                put("surname", "Sparrow");
                put("age", 33);
            }
        });
        System.out.println(jack2.hairColor);    // java.awt.Color[r=255,g=0,b=0]
        System.out.println(jack2.surname);      // Sparrow
        System.out.println(jack2.name);         // null
        System.out.println(jack2.age);          // 33

    }

}

Is there a more elegant way to do it?

1
  • new User().setName(name).setSurname(surname).setAge(age). Or 'static User createUsingSurname(..., surname) Commented Dec 23, 2018 at 13:58

2 Answers 2

2

The typical ways of doing this are with static creation methods or a builder object.

Static creation methods are the way to go if there are distinctive patterns of usage. For your example (where this perhaps isn't the case).

public static User ageName(int age, String name) {
    ...
}  
public static User ageSurname(int age, String surname) {
    ...
}
...

In general it's a good idea to avoid any overloading. With constructors Java rather forces you into it, but sometimes you have to break free.

Builder may go something like:

public class UserBuilder { // This could be made a nested class of User
    private int age = -1;
    private String name;
    private String surname;
    private Color hairColor;

    public UserBuilder age(int age) {
        this.age = age;
        return this;
    }
    // ... other properties ...
    public User build() {
        // Or return new User(this)
        return new User(age, name, surname, hairColor);
    }
}

This uses the typical Java dirty hack of returning this in a builder so you can build a train wreck.

User user1 = new UserBuilder().age(33).name("Jack").build();

You really need real examples of usage to see how it should fit in.

Sign up to request clarification or add additional context in comments.

Comments

2

You are over-complicating things by using a HashMap here. Instead you could make use of the Builder Pattern for the same.

class User {
    // required parameters
    private int age;

    // optional parameters
    private String name;
    private String surname;

    public int getAge() {
        return age;
    }

    public String getName() {
        return name;
    }

    public String getSurname() {
        return surname;
    }

    private User(UserBuilder userBuilder) {
        this.age = userBuilder.age;
        this.name = userBuilder.name;
        this.surname = userBuilder.surname;
    }

    public static class UserBuilder {
        // required parameters
        private int age;

        // optional parameters
        private String name;
        private String surname;

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

        public UserBuilder setSurname(String surname) {
            this.surname = surname;
            return this;
        }

        public UserBuilder(int age) {
            this.age = age;
        }

        public User build() {
            return new User(this);
        }

    }
}

Now you can use it :

User user1 = new User.UserBuilder(12).setName("Jack").build();
User user2 = new User.UserBuilder(12).setSurname("Sparrow").build();

This assumes that age is a mandatory field, name and surname are optional fields for creating an object of User. You can tweak it as per your requirement accordingly.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.