How can I avoid misuse of a constructor with multiple parameters of the same type?

Viewed 126

Should I avoid constructors like this?

public Person(String firstName, String lastName) {
    this.firstName = firstName;
    this.lastName = lastName;
}

Because they can be misused:

Person person = new Person("Smith", "John");

And if so, what should I do instead?

3 Answers

Use builder, and Lombok project can simplify code

@Builder
public class Person {
    private final String firstName;
    private final String  lastName;
}

Usage is

Person.builder()
    .firstName("John")
    .lastName("Smith")
    .build();

Constructor with multiple fields of the same type is a valid implementation. If you want to avoid misused issues you can use a builder pattern instead.

Person person = Person.builder().firstName("John").lastName("Smith").build();

Using the builder-pattern will help, but if you really want to avoid misuse, you should make firstName and lastName typed using value classes.

Proper value classes with no overhead will come in a later Java version, but you could use records if you're on Java 14 (preview feature) or later. It's a bit more cumbersome to make value classes on lower Java versions (you need to create a class with 1 property).

record FirstName(String firstName) {}
record LastName(String lastName) {}

Now you can do this in your constructor:

public Person(FirstName firstName, LastName lastName) {
    this.firstName = firstName;
    this.lastName = lastName;
}

With this, your example where you switched "John" and "Smith" would no longer compile.

I often use this pattern when I have a lot of ID-fields I need to pass around. The consequence of mixing them up would be greater.

Another nice side effect of doing this is that your IDE (at least IntelliJ) will have more type-information to suggest auto-completion of your code. Using value classes could therefore speed up your coding a little bit :)

Related