Returning Method value inside a Consumer expressio

2020-07-23 09:05发布

问题:

I'm trying to return a boolean inside a Method and i'm using a consumer function. Is there any way to return that value directly inside that Consumer expression?

Here's the Code:

private static boolean uuidExists(UUID uuid) {
    MySQL.getResult("", rs -> {
        try {
            if(rs.next()){
                return rs.getString("UUID") != null;
            }
        } catch (SQLException e) {
        }
    });

    return false;
}

EDIT:

I know that i could create a boolean and change that value but i do not wanna do that.

EDIT:

getResult code:

public static void getResult(String qry, Consumer<ResultSet> consumer){
        new BukkitRunnable() {
            @Override
            public void run() {
                if(isConnected()) {
                    consumer.accept(Warpixel.getWarpixel().getStats().getResult(qry));
                    return;
                }
                consumer.accept(null);
            }
        }.runTaskAsynchronously(Bedwars.getMain());
    }

回答1:

No, it's not possible. The lambda expression is an implementation of Consumer.accept and can therefore not return a value because that method is void.

I know that i could create a boolean and change that value but i do not wanna do that.

Not really either. In a lambda expression, you may only reference local variables that are final (making it inherently impossible). You would have to use other techniques (such as a modifiable reference object) to go around this limitation.

An approach that could be suggested is to use a future here:

CompletableFuture<Boolean> future = new CompletableFuture<Boolean>();

MySQL.getResult("", rs -> {
    try {
        if(rs.next()){
            future.complete(rs.getString("UUID") != null);
        }
    } catch (SQLException e) {
        //handle exception
    }

    future.complete(false); //mind this default value
});

return future.join(); //this will block until the `Consumer` calls complete()

It's important to note that this is a way to block an execution meant to be asynchronous.



回答2:

It's a lambda expression, which gets executed after the uuidExists method has completed. You have to make an interface used as a callback (just like the function getResult does).

public interface UuidCallback {
    void onCompleted(boolean uuidExists);
}

It will be executed when you getResult. You have to pass the callback in an additional parameter to uuidExists:

private static boolean uuidExists(UUID uuid, UuidCallback callback)

and call the completed method when you get your result

if(rs.next()){
    callback.onCompleted(rs.getString("UUID") != null);
}

Then, when executing uuidExists you have to make another lambda expression:

uuidExists(someUUIDInstance, uuidExists -> {
    // boolean uuidExists now has your result
});

Hope it helps



回答3:

Your method getResult is declared as:

void getResult(String qry, Consumer<ResultSet> consumer){ ... }

Where Consumer<ResultSet> is a functional interface representing a function taking a ResultSet as input and has a void return type.

What you're after is called a predicate i.e. Predicate<ResultSet>