Skip to content

Instantly share code, notes, and snippets.

@imagest
Created December 11, 2023 18:29
Show Gist options
  • Save imagest/4a2dd769594b9325113129710fcbfd4e to your computer and use it in GitHub Desktop.
Save imagest/4a2dd769594b9325113129710fcbfd4e to your computer and use it in GitHub Desktop.
Interesting Java compiler riddle
public class Example {
interface Identifier {}
class Request {}
class Response<T extends Identifier> {}
class ErrorResponse extends Response {}
// the inline lambda and the method _should_ behave exactly the same,
// but compiler somehow retains parameterzied upper bound type for _lambda_, but not for method.
// Ljava/util/function/Function<LExample$Request;LExample$Response<+LExample$Identifier;>;>;
private Function<Request, Response<? extends Identifier>> handleWithLambda = response-> new Response<>();
// <(LExample$Request;)LExample$Response<+LExample$Identifier;>;>
private Response<? extends Identifier> nonLambda(Request request) {
return new Response<>();
}
// signature - <()Ljava/util/concurrent/CompletionStage<LExample$Response<+LExample$Identifier;>;>;>
// Compiles - CompletionStage<Response<extends Identifier>>
public CompletionStage<Response <? extends Identifier>> withLambda() {
return CompletableFuture.completedStage(new Request())
.thenApply(handleWithLambda)
.exceptionally(err -> new ErrorResponse());
}
// Doesn't compile - CompletionStage<Response<capture of extends Identifier>>
public CompletionStage<Response <? extends Identifier>> withMethod() {
return CompletableFuture.completedStage(new Request())
.thenApply(this::nonLambda)
.exceptionally(err -> new ErrorResponse());
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment