4

I am trying to avoid isPresent checks in my code below, but the compiler emits an error with the message

"No instance(s) of type variable(s) U exist so that void conforms to U"

on the call to printAndThrowException. This is my code:

values.stream()
    .filter(value -> getDetails(value).getName.equals("TestVal"))
    .findFirst()
    .map(value -> printAndThrowException(value))
    .orElseThrow(new Exception2("xyz"));

The method in question printAndThrowException has the below signature:

void printAndThrowException(Pojo value)

The above method always throws an exception of type RuntimeException. The abovementioned code isn't the exact code, just transformed my code to represent the situation.

What's the problem here and how to avoid using isPresent when calling printAndThrowException?

7
  • You have to provide a bit more details on the types of variables (values) and what each step in the stream pipeline returns and in which step do you get this error
    – Thiyagu
    Commented Jan 24, 2022 at 11:45
  • 1
    orElseThrow should take a supplier. So, it will be .orElseThrow(() -> new Exception2(..))
    – Thiyagu
    Commented Jan 24, 2022 at 11:46
  • @user7 : Added more details. Also, orElseThrow does not show any error, error is on the call to printAndThrowException.
    – nikel
    Commented Jan 24, 2022 at 12:27
  • 2
    map() is used to convert one value to another value- not the case here - this use case seems more like a case for ifPresentOrElse() (Java 9 or later) Commented Jan 24, 2022 at 13:55
  • 1
    @MCEmperor I realised that It would be cleaner to call the method in ifPresent and throw exception at the call place itself :)
    – nikel
    Commented Jan 25, 2022 at 12:49

1 Answer 1

10

Optional.map() expects a Function<? super T, ? extends U> as parameter. Since your method returns void, it cannot be used like this in the lambda.

I see three options here:

  • make that method return Void/Object/whatever instead – semantically not ideal but it would work
  • make that method return the exception, and change the lambda definition to
    .map(v -> {
        throw printAndReturnException();
    });
    
  • use ifPresent(), and move the orElseThrow() outside of the call chain:
    values.stream()
        .filter(value -> getDetails(value).getName.equals("TestVal"))
        .findFirst()
        .ifPresent(value -> printAndThrowException(value))
    throw new Exception2("xyz");
    

Not the answer you're looking for? Browse other questions tagged or ask your own question.