简体   繁体   中英

Java - Multiple constructors using same data type

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?

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.

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.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM