title: "incompatible types" compiler error with lambda / method referencing and generics
body: <p>I stumbled upon an issue when working through some old code, replacing several anonymous classes with either lambda expressions or method references. The problem is a bit hard to explain with words, but I'll do my best, and I've also added a short example illustrating my problem to the best of my abilities below.</p>
  
  <p>My example consists of...</p>
  
  <ol>
  <li><p>A functional interface, <b>GenericListener</b>, which takes a <b>type parameter V</b> and has a single method "genericCallback(V genericValue)".</p></li>
  <li><p>A class, <b>CallbackProducer</b>, which takes a <b>type parameter T</b>. This class also has a method to add a GenericListener with type Integer.</p></li>
  <li><p>A <strong>Main</strong> class which creates CallbackProducers and adds GenericListeners to them.</p></li>
  </ol>
  
  <p>When I run CallbackProducer's addIntegerListener method from Main's constructor, I get the <strong>compiler error: "incompatible types"</strong> whenever i avoid specifying the type of CallbackProducer's T.</p>
  
  <p>The method addIntegerListener only uses GenericListener's V. As far as I know, it doesn't use CallbackProducer's T in any way.</p>
  
  <p><strong>I've put several calls to addIntegerListener + comments in Main's constructor, 3 of which cause compiler errors</strong>. But as far as I can see (and according to IntelliJ) all of them should be legal. If you comment out the 3 first calls to addIntegerListener the application will compile and run just fine.</p>
  
  <p>Also, if CallbackProducer didn't use generics, and we removed the type parameter T completely, the 3 first calls to addIntegerListener would compile.</p>
  
  <p>Is there a reason for this behavior? Am I misunderstanding something, or is this a weakness or bug in the java compiler? (I'm currently using java 1.8_51)</p>
  
  <p>Thanks in advance for any clarification!</p>
  
  <pre class="lang-java prettyprint-override"><code>import javax.swing.*;
  
  public class Main {
  
      public static void main(final String[] args) {
          SwingUtilities.invokeLater(Main::new);
      }
  
      public Main() {
  
          // Compiler error, type of CallbackProducer's "T" not specified
          CallbackProducer producer1 = new CallbackProducer();
          producer1.addIntegerListener(this::integerReceived);
  
          // Compiler error, no diamond brackets for CallbackProducer
          new CallbackProducer().addIntegerListener(this::integerReceived);
  
          // Also compiler error for lambdas with no diamond brackets on CallbackProducer
          new CallbackProducer().addIntegerListener(intValue -&gt; integerReceived(intValue));
  
          // Works because a (any) type for CallbackProducer's "T" is specified
          CallbackProducer&lt;Object&gt; producer2 = new CallbackProducer&lt;&gt;();
          producer2.addIntegerListener(this::integerReceived);
  
          // Works because of the diamond brackets
          new CallbackProducer&lt;&gt;().addIntegerListener(this::integerReceived);
  
          // Lambda also works with diamond brackets
          new CallbackProducer&lt;&gt;().addIntegerListener(intValue -&gt; integerReceived(intValue));
  
          // This variant also works without specifying CallbackProducer's "T"
          // ... but it is a workaround I'd prefer to avoid if possible :-P
          GenericListener&lt;Integer&gt; integerListener = this::integerReceived;
          new CallbackProducer().addIntegerListener(integerListener);
      }
  
      private void integerReceived(Integer intValue) {
          System.out.println("Integer callback received: " + intValue);
      }
  
      // A callback producer taking generic listeners
      // Has a type parameter "T" which is completely unrelated to
      // GenericListener's "V" and not used for anything in this
      // example really, except help provoking the compiler error
      public class CallbackProducer&lt;T&gt; {
          // Adds a listener which specifically takes an Integer type as argument
          public void addIntegerListener(GenericListener&lt;Integer&gt; integerListener) {
              // Just a dummy callback to receive some output
              integerListener.genericCallback(100);
          }
      }
  
      // A simple, generic listener interface that can take a value of any type
      // Has a type parameter "V" which is used to specify the value type of the callback
      // "V" is completely unrelated to CallbackProducer's "T"
      @FunctionalInterface
      public interface GenericListener&lt;V&gt; {
          void genericCallback(V genericValue);
      }
  }
  </code></pre>
  
  <p>Here's a shortened down version without all the comment clutter and with only two calls to "addIntegerListener", one of which causes compiler error.</p>
  
  <pre class="lang-java prettyprint-override"><code>import javax.swing.*;
  
  public class Main {
  
      public static void main(final String[] args) {
          SwingUtilities.invokeLater(Main::new);
      }
  
      public Main() {
  
          CallbackProducer producer1 = new CallbackProducer();
          producer1.addIntegerListener(this::integerReceived);    // Compiler error
  
          CallbackProducer&lt;Object&gt; producer2 = new CallbackProducer&lt;&gt;();
          producer2.addIntegerListener(this::integerReceived);    // Compiles OK      
      }
  
      private void integerReceived(Integer intValue) {
          System.out.println("Integer callback received: " + intValue);
      }
  
      public class CallbackProducer&lt;T&gt; {
          public void addIntegerListener(GenericListener&lt;Integer&gt; integerListener) {
              integerListener.genericCallback(100);
          }
      }
  
      @FunctionalInterface
      public interface GenericListener&lt;V&gt; {
          void genericCallback(V genericValue);
      }
  }
  </code></pre>