1

My IDE is complaining that "NCM_Callable cannot be converted to Callable<ReturnInterface<? extends Object>> on this line this.ph.submitCallable(new NCM_Callable(this, new DeviceGroup(this.deviceGroupNames.get(i)), ph)); In the "fetchDevices()" method

I just want to be able to pass Callables to my ecs that returns a ReturnInterface containing any type of object.

I suspect there is something wrong with my usage of <> generic definitions, but I can't seem to figure out what it is. Any help would be appreciated.

  @Override
public void fetchDevices() throws Exception {
    System.out.println("[NCM_Fetcher]fetchingDevices()");
    for (int i = 0; i < this.deviceGroupNames.size(); i++) {
        System.out.println("[NCM_Fetcher]fetchingDevices().submitting DeviceGroup Callable " + i+ " of "+this.deviceGroupNames.size());
        this.ph.submitCallable(new NCM_Callable(this, new DeviceGroup(this.deviceGroupNames.get(i)), ph));
    }
    this.ph.execute();//See progressBarhelper below
}

ProgressBarHelper: I have a strange error at "ecs.submit()". From what I've read, it seems like I may need a helper method? How do I fix?

public class ProgressBarHelper extends SwingWorker<Void, ReturnInterface> implements ActionListener {
ExecutorService pool = Executors.newFixedThreadPool(Runtime.getRuntime().availableProcessors());

protected CompletionService<ReturnInterface<?>> ecs;

public final void submitCallable(Callable<? extends ReturnInterface<?>> c) {
    //create a map for this future
    ecs.submit(c);
    this.callables.add(c);//Error here is Callable<CAP#1 cannot be converted to Callable<ReturnInterface<?>>
    System.out.println("[ProgressBarHelper]submitted");

}
}

And Finally, the NCM_Callable class with its Generics.

public class NCM_Callable implements Callable<ReturnInterface<ResultSet>>, ReturnInterface<ResultSet> {
CoupFlu
  • 311
  • 4
  • 20
  • First create a [mcve]. You will likely solve your problem in the process. – 4castle Aug 10 '16 at 15:22
  • Possible duplicate of [Java generics, nested collection of wildcard](http://stackoverflow.com/questions/6293871/java-generics-nested-collection-of-wildcard) – 4castle Aug 10 '16 at 15:29
  • It is not a duplicate. – CoupFlu Aug 10 '16 at 16:58
  • Did it solve your problem though? Looking at the second answer, you have to change the method signature to instead use `Callable extends ReturnInterface extends Object>> c` – 4castle Aug 10 '16 at 17:28
  • By the way, ` extends Object>` is the same as just `>` – 4castle Aug 10 '16 at 17:30
  • I'm not sure why I have to put a Generic wildcard for ReturnInterface. I always want a ReturnInterface. The only thing that changes is the Class type of the variable that ReturnInterface contains. Can you explain further? – CoupFlu Aug 10 '16 at 17:33
  • Sure, it could be a bit cleaner, but I've seen questions without any code at all. Hopefully my upvote will counteract any downvotes this question receives, because the question could be a lot worse. – RobotKarel314 Aug 10 '16 at 17:41
  • It wouldn't change the semantics of what objects can be used at all. The other answers & comments on the question explain further. – 4castle Aug 10 '16 at 17:44
  • @RobotKarel314 No need for commentary on your vote unless you are providing constructive criticism. If you need to justify your upvote like that, it probably means you should just leave it be. – 4castle Aug 10 '16 at 17:45
  • I have made the changes you suggested, but now receive an error at "ecs.submit(c). I will post the error above. – CoupFlu Aug 10 '16 at 17:52
  • @4castle I believe this might be related to my problem, but i can't see how to make it work. [link](http://stackoverflow.com/questions/18483833/proper-use-of-unbounded-wilcard-generics) – CoupFlu Aug 10 '16 at 18:30
  • @RobotKarel314 does this make the question clearer? – CoupFlu Aug 10 '16 at 19:04
  • @4castle Fine. My constructive criticism is that people shouldn't be so harsh. – RobotKarel314 Aug 10 '16 at 23:40
  • I still have no solution – CoupFlu Aug 11 '16 at 13:12

1 Answers1

0

As far as I could check, the problematic line is ecs.submit:

public final void submitCallable(Callable<? extends ReturnInterface<?>> c) {
    // create a map for this future
    ecs.submit(c); // Error here is Callable<CAP#1 cannot be converted to Callable<ReturnInterface<?>>
   this.callables.add(c); // this is fine on my machine
}

The problem is that java generics is invariant. There's a workaround for this: you can replace the wildcard with a named, bound type:

public final <T extends ReturnInterface<?>> void // this is how you name and bind the type
   submitCallable(Callable<T> c) { // here you are referring to it
    // create a map for this future
    ecs.submit((Callable<ReturnInterface<?>>) c); // here you need to cast. 
    ...
}

The casting is okay in runtime due to type erasure. But then be very careful on what you do with those Callables.

Finally, this is how you can invoke this function:

private static class ReturnInterfaceImpl implements ReturnInterface<String>  {

};

public void foo() {
    Callable<ReturnInterfaceImpl> c = new Callable<ReturnInterfaceImpl>() {
        @Override
        public ReturnInterfaceImpl call() throws Exception {
            return null;
        }
    };
    submitCallable(c);
}
Tamas Rev
  • 7,008
  • 5
  • 32
  • 49
  • I had gotten flustrated and just ended up accepting a callable. Its good that someone could explain why my code was not working though. – CoupFlu Aug 15 '16 at 14:22