1

I'm having an unexpected error while compiling this example code (in the fails() method). IntelliJ used to not report the error in the IDE, but it has since started to report it (some of the classes were in a library, which seemed to confuse it)

public class Main {

    // The command
    public interface ToMessageOperation<MODEL, MESSAGE> {

        void run(MODEL object, MESSAGE message) throws Exception;
    }

    // A command
    public class SelfLink<MODEL> implements ToMessageOperation<MODEL, LinkedMessage> {

        @Override
        public void run(MODEL object, LinkedMessage linkedMessage) throws Exception {

        }
    }

    // A message type
    public interface LinkedMessage {

        void linkme();
    }

    // A message
    public interface BootInfo extends LinkedMessage {
    }

    //The Executor
    public interface GetRequest<MODEL, MESSAGE> {

        GetRequest<MODEL, MESSAGE> runAll(ToMessageOperation<? super MODEL, ? super MESSAGE>... operations);
        GetRequest<MODEL, MESSAGE> cleanUp();
        MESSAGE now();
    }

    // The command factory
    public SelfLink selfLink() {
        return null;
    }

    public <MODEL, MESSAGE> GetRequest<MODEL,MESSAGE> get(Class<MESSAGE> message) {

        return null;
    }

    public BootInfo works() {

        return get(BootInfo.class).cleanUp().now();
    }

   public BootInfo alsoWorks() {

        return get(BootInfo.class).runAll(new ToMessageOperation<Object, BootInfo>() {
            @Override
            public void run(Object object, BootInfo bootInfo) throws Exception {

            }  
        }).now();
    }

   public BootInfo surprisedItWorks() {

        return get(BootInfo.class).runAll(new ToMessageOperation<Object, LinkedMessage>() {
            @Override
            public void run(Object object, LinkedMessage message) throws Exception {

            }  
        }).now();
    }

    public BootInfo fails() {

        return get(BootInfo.class).runAll(new SelfLink()).now();
    }

}

I'm a bit surprised that the error only happens when I add the runAll() method, as all methods return the same objects.

I'm really surprised that the method works with different types that are assignable from the failing case ( where the ToMessageOperation type is inherited instead of being explicit ). And even that shouldn't change the return type, right ?

Am I doing something wrong ?

JP Belanger
  • 119
  • 8
  • You don't have a lot of options, I think. You could do this: return get(BootInfo.class).runAll(selfLink()).now(); or use @SuppressWarnings. See here: http://stackoverflow.com/questions/450807/how-do-i-make-the-method-return-type-generic – mttdbrd Jun 17 '15 at 03:01
  • Your code seems incomplete. Is `BootResource.get()` supposed to be static? An actual buildable, runnable example would help. – markspace Jun 17 '15 at 03:10
  • @markspace `BootResource.get()` isn't supposed to be static (it's there in the example). I agree, a whole compilable example could help (I was just trying to keep the noise down). I'll fix the question later today. – JP Belanger Jun 17 '15 at 11:59
  • Also of note, this fails with jdk 1.8.0_45. It seems to work with 1.7.0_45. Starting to suspect a compiler bug. – JP Belanger Jun 19 '15 at 03:24

1 Answers1

0

I quickly fixed it by putting explicit generic parameters on SelfLink

public class SelfLink<MODEL,MESSAGE extends LinkedMessage> implements ToMessageOperation<MODEL, MESSAGE> {


    @Override
    public void run(MODEL object, MESSAGE linkedMessage) throws Exception {

        linkedMessage.linkme();
    }
}

public <MODEL,MESSAGE extends LinkedMessage> SelfLink<MODEL, MESSAGE> selfLink() {

    return null;
}

Using the factory class for selflink, the code looks like this:

public BootInfo fails() {

    return get(BootInfo.class).runAll(selfLink()).now();
}

I don't understand why this is necessary in java 8, but use is pretty much equivalent. If I get a better explanation I'll accept it as an answer.

JP Belanger
  • 119
  • 8