Автоматическое сопоставление конструктора в методе по умолчанию

У меня есть PersonFactory Интерфейс следующим образом:

@FunctionalInterface
public interface PersonFactory<P extends Person> {
    P create(String firstname, String lastname);

    // Return a person with no args
    default P create() {
        // Is there a way I could make this work?
    }
}

Person учебный класс:

public class Person {
    public String firstname;
    public String lastname;

    public Person() {}

    public Person(String firstname, String lastname) {
        this.firstname = firstname;
        this.lastname = lastname;
    }
}

Я хочу быть в состоянии создать свой экземпляр Personвот так:

PersonFactory<Person> personFactory = Person::new;

Person p = personFactory.create(); // does not work
Person p = personFactory.create("firstname", "lastname"); // works

Есть ли способ, которым я мог бы заставить компилятор Java автоматически выбирать правильный конструктор, сопоставляя подпись PersonFactory.create()?

1 ответ

Решение

Одним из способов было бы иметь следующее:

default P create() {
    return create(null, null);
}

Но я не уверен, что ты этого хотел. Проблема в том, что вы не можете сделать ссылку на метод ссылающимся на 2 разных метода (или конструктора). В этом случае вы хотите Person::new ссылаться на конструктор без параметров и конструктор с 2 параметрами, что невозможно.

Когда у тебя есть:

@FunctionalInterface
public interface PersonFactory<P extends Person> {
    P create(String firstname, String lastname);
}

и использовать его как

PersonFactory<Person> personFactory = Person::new;
Person p = personFactory.create("firstname", "lastname");

Вы должны понимать, что метод-ссылка Person::new ссылается на конструктор, принимающий 2 параметра. Следующая строка просто вызывает ее, передавая параметры.

Вы также можете написать это более подробно, используя лямбда-выражение:

PersonFactory<Person> personFactory = (s1, s2) -> new Person(s1, s2); // see, we have the 2 Strings here
Person p = personFactory.create("firstname", "lastname");
Другие вопросы по тегам