5

I have something along the lines of:

interface Foo<T> {
    //... lines [0,45]...

/*line 46*/ <R, X super T&R> List<X> weave(R value);
    //...
}

But IntelliJ is reporting:

  1. Error:(46, 18) java: > expected
  2. Error:(46, 19) java: illegal start of type
  3. Error:(46, 26) java: '(' expected
  4. Error:(46, 28) java: < identifier > expected
  5. Error:(46, 29) java: 'l' expected
  6. Error:(46, 43) java: < identifier > expected

What's the problem? Am I not allowed to bind a name to a lower bound? Or am I only allowed to use a R&X expression in an upper bound?

Changing it to

interface Foo<T> {
    //... lines [0,45]...

/*line 46*/ <R> List<? super T&R> weave(R value);
    //...
}

yields

  1. Error(46, 31) java: > expected
  2. Error(46, 32) java: '(' expected
  3. Error(46, 33) java: illegal start of type
Matt G
  • 1,661
  • 19
  • 32
  • @rgettman FYI your answer was correct. The downvoter and people that justified the downvote were confusing wildcards with type parameters. "You can't declare a type variable to be super": http://stackoverflow.com/questions/2800369/bounding-generics-with-super-keyword "you can't declare two bounds that are themselves generic type parameters": http://stackoverflow.com/questions/13101991/java-generics-make-generic-to-extends-2-interfaces – Paul Bellora Aug 10 '13 at 00:48

1 Answers1

4

By my reading of the specification, super can only be used with a wildcard and can't be captured into a type variable; see JLS 4.5.1. Similarly, & is only valid in type variables, not type arguments, and type variables can't use super.

After having thought about it, here's my explanation: The reason for a type variable is to eliminate explicit casting to improve type safety. When you declare a type parameter to be super Foo, you're saying that it's okay for that parameter to be any superclass of Foo. This means that it could be anything up to and including Object, and so you have no safe way to presume anything about the objects whose type satisfies that bound, and so there's no information whatsoever contained within a named type variable; you just wildcard it and can call hashCode() or toString(), but nothing type-specific.

chrylis -cautiouslyoptimistic-
  • 75,269
  • 21
  • 115
  • 152
  • Can you think of any way to specify the semantics I'm trying for? – Matt G Aug 10 '13 at 00:25
  • Can you explain the semantics? O:-) It's not easy to infer from your code. What is `interface Foo` supposed to do? What about `weave`? What are you intending by using `super` in a return type? – chrylis -cautiouslyoptimistic- Aug 10 '13 at 00:28
  • Foo is just a collection of T. "weave" is a generalization of the pattern one commonly uses to print the elements of an array: [1, 2, 3].weave(",") would return [1, ",", 2, ",", 3,]. In other words, it returns `this`, except with the parameter spliced between each element. As for the semantics of the generics, I want to return a List of the most-derived supertype common to R and T, although I'm not sure such a mechanism exists. I want to do this so that the returned list is parameterized in some way (and not just a raw List) if possible, for type safety. – Matt G Aug 10 '13 at 00:47
  • I'm going to have to munch on this and still may not give you an answer, but what you're looking for may be something like this: ` List weave(R value)`. I don't have a play project lying around right now; what does the compiler say about that? – chrylis -cautiouslyoptimistic- Aug 10 '13 at 00:53
  • That works, but I have to make it a static method because otherwise the `T extends S` would have to go on the class itself. – Matt G Aug 10 '13 at 01:14
  • What about adding it to the `weave` method as a class variable? Still wants it on the class? – chrylis -cautiouslyoptimistic- Aug 10 '13 at 01:29
  • Adding it at the class level doesn't make a whole lot of sense. Only this one operation out of many has a use for this type information, and it wouldn't be good to have to specify it when you instantiate a class, and carry it around with that instance. Plus the information would be persistent, which doesn't make sense either, because if you wanted to weave the same collection two different times with different types, you'd have to cast it. – Matt G Aug 10 '13 at 02:26
  • let us [continue this discussion in chat](http://chat.stackoverflow.com/rooms/35177/discussion-between-matt-g-and-chrylis) – Matt G Aug 10 '13 at 02:28