简体   繁体   中英

Method reference in Optional.ifPresent() throwing exception

Consider the following lines of codes.

Object object = "s";
Optional.empty().ifPresent(s -> ((StringBuffer) object).append(s));
Optional.empty().ifPresent(((StringBuffer) object)::append);

Functionally, line 2 and line 3 are the same. In fact, in IntelliJ, it suggests that I use method reference for line 2, which would then be exactly the same as line 3. However, when I run the codes with Java 8, line 2 executes fine but line 3 throws a ClassCastException. Obviously, the exception will happen if the codes in ifPresent() are executed, but in both lines 2 and 3, the codes in ifPresent() should not even be executed. So how do we explain the exception happening in line 3?

These two aren't the same (and it's a bug in intellij if it suggests this refactoring, at least without explicitly stating the caveat that they have different semantics).

Optional.empty().ifPresent(s -> ((StringBuffer) object).append(s));

Here, the cast is evaluated when the Consumer is executed. It is effectively:

Optional.empty().ifPresent(new Consumer<Object>() {
  @Override public void accept(Object s) {
    ((StringBuffer) object).append(s);
  }
});

so this will only throw ClassCastException if the consumer is invoked.

OTOH

Optional.empty().ifPresent(((StringBuffer) object)::append);

is effectively:

Optional<Object> empty = Optional.empty();
StringBuffer sb = (StringBuffer) object;
empty.ifPresent(new Consumer<Object>() {
  @Override public void accept(Object s) {
    sb.append(s);
  }
});

Hence, this will throw a ClassCastException before the consumer is invoked.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM