0

It's kinda hard to explain the problem so I will explain with the code below.
I would like to create the method applyAll.
applyAll take a setter method from the User class and call a function (passed as parameter) to set value of that method.

Problems are:

  • what is the type of User::setLogin ?
  • how can I call this generic method ?
public class UserBuilder {
    private List<User> users;

    /* ... */

    public <T> UserBuilder applyAll(??? method, Function<Integer, T> func) {
        for (int index = 0; index < users.size(); index++) {
            // I don't know how to call 'method' parameter (which is a method of User class)
            users.get(i)[method](func.apply(index));
        }
        return this;
    }

    public UserBuilder withLogin(Function<Integer, String> func) {
        return applyAll(User::setLogin, func);
    }

    /* ... */
}
public class User {
    private String login;

    void setLogin(String login) { this.login = login; }
}

Example of use case:

List<User> users = new UserBuilder(10).withLogin((index) -> "user_" + index).build();
3
  • "what is the type of User::setLogin ?" we can't know without seeing its declaration. But since you use it as an array index, the only thing it could be is an int, but a method reference cannot be an int. Do you mean method.apply(users.get(i)) or something? Commented Jun 8, 2022 at 12:23
  • Looks like you are confusing Method (which is a description of a method in reflection) with a "method reference" (which is a way to represent a method as a lambda). Commented Jun 8, 2022 at 12:24
  • Yes the type Method is confusing, I changed it by "???" because I don't know which type User::setLogin refers to. I also added the User class. Commented Jun 8, 2022 at 12:28

2 Answers 2

1

In this case, User::setLogin can resolve into a java.util.function.BiConsumer<User, T>:

public <T> UserBuilder applyAll(BiConsumer<User, T> setter, Function<Integer, T> func) {
    for (int i = 0; i < users.size(); i++) {
        setter.accept(users.get(i), func.apply(i));
    }
    return this;
}
Sign up to request clarification or add additional context in comments.

Comments

1

The setter that is relevant here must clearly 'take' one parameter, of type T (after all, that's what you pass to it in your example code - the result of func.apply(index), which is an instance of T), and which returns - well, nothing. It's a setter.

Thus, it's a java.util.function.Consumer<T> - a method that takes Ts and produces nothing - that 'consumes Ts'. To be perfectly correct, it'd be allright if the setter consumes some supertype of Ts just as well (if your function produces Integers, and your setter accepts Numbers - that's okay). So let's make that Consumer<? super T>.

public <T> UserBuilder applyAll(Consumer<? super T> setter, Function<Integer, T> func) {
 ...
}

and you can call it:

List<String> names = ....;
Function<Integer, String> nameMaker = idx -> names.get(idx);
builder.applyAll(User::setName, nameMaker);

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.