Java Compiler accepts generic method reference, but not when passed as variable

Viewed 76

I have a tricky set of classes with generics. I can NOT change Container and GenericContainer, but I can change the rest.

  • the static version with .with(Configuration::initialise) works
  • the one .with(f) doesn't

The problem is the generic SELF parameter on the GenericContainer class, but I can't figure out the exact reason.

The example code is ready for copy/paste.

Initializer:

import java.util.function.BiConsumer;

public interface Initializer {
  <C extends Container<?>, S> C initialize(
    C container,
    BiConsumer<C, S> initializer
  );

  static <C extends Configuration.Container<?>> Initializer.Builder<C> init(
    C container
  ) {
    return new Initializer.Builder<>(container);
  }

  class Builder<C extends Configuration.Container<?>> {
    private final C container;

    public Builder(C container) {
      this.container = container;
    }

    public <S> C with(BiConsumer<C, S> initializer) {
      Initializer initService = null;
      return container;
    }
  }
}

Configuration:

import java.util.function.BiConsumer;
import javax.sql.DataSource;

public class Configuration {

  interface Container<SELF extends Container<SELF>> {}

  static class GenericContainer<SELF extends GenericContainer<SELF>>
    implements Container<SELF> {}

  // works
  public static void initialise(GenericContainer<?> container, DataSource ds) {}

  public static final GenericContainer<?> CONTAINER_1 = Initializer
    .init(new GenericContainer<>())
    .with(Configuration::initialise);

  // doesn't work
  static BiConsumer<GenericContainer<?>, DataSource> f = (con, ds) -> {};
  public static final GenericContainer<?> CONTAINER_2 = new Initializer.Builder<>(
    new GenericContainer<>()
  )
  .with(f);
}
1 Answers

You can't do it because you need to define the type parameter of GenericContainer, but there is no syntax defined in the java standards to supply a generic type parameter to a lambda. As for why it works in the method reference I am not sure, but it might be type inference.

Related