0

Let's say I have Node class that is part of a graph. Each Node handles generic types T and S, so that we have Node<T, S>. Each Node can add inputs to itself from other Nodes via an addInput method.

class Node<T, S> {
  <T2, S2> void addInput(SomeUpdater<T2, S2> input) {
    // processes input
  }
}

One input Node's T becomes the receiver Node's T2 in the addInput method.

Now let's say I want to store the inputs of each Node, within the Node. So:

class Node<T, S> {
  Map<String, NodeCache<T2, S2>> cache = new HashMap<>();

  <T2, S2> void addInput(SomeUpdater<T2, S2> input) {
    this.cache.put(thisIsOfTypeT2, thisIsOfTypeS2);
  }
}

This doesn't work, because 1) T2 and S2 could be one of a handful of types, depending on which inputs are added, and the code above would require that all inputs have the same T2, S2 types; 2) I would have to add T2 and S2 to the Node class, which I don't want to do.

Wildcards almost work fine:

class Node<T, S> {
  Map<String, NodeCache<?, ?>> cache = new HashMap<>();

  <T2, S2> void addInput(SomeUpdater<T2, S2> input) {
    this.cache.put("a string", new NodeCache<T2, S2>()); // compiler is fine
    this.cache.get("a string").get(thisIsOfTypeT2); // compiler nopes out of this one
  }
}

On the second get, I get method NodeCache.get(CAP#1) is not applicable (argument mismatch; T2 cannot be converted to CAP#1). I'm familiar with this great answer on wildcard generics, so generally I think wildcards may be out(?).

Alternatively, I could do something like Map<String, NodeCache<? extends SuperTypeA, ? extends SuperTypeB>> cache = new HashMap<>();, but I run into the same problems. Ideally I'd even have Map<String, NodeCache<? extends SuperTypeA, ? extends SuperTypeA & SuperTypeB>>, but I don't think Java even supports multiple bounded types for wildcards.

Not sure how to proceed from here, though. Any suggestions would be appreciated.

  • 2
    If every call to `addInput` can use different bindings for `T2` and `S2`, then the only thing they all have in common is that they are all `Object`, and that's also all you can safely know when extracting them from the cache, which means that generics cannot help you here, you should just declare it all as `Object`. – Andreas May 12 '20 at 03:27
  • Editing the post to say that it could be possible to restrict inputs based on a few options, such that: `Map> cache = new HashMap<>();` Of course, `? extends A & B` is not possible, so might need another solution there. – StarseedLure May 12 '20 at 03:29
  • While you are editing the post, can you explain what `T` and `S` have to do with anything? – Andreas May 12 '20 at 03:31
  • Added; is that a bit more clear? – StarseedLure May 12 '20 at 03:39

0 Answers0