Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

"Unexpected token" using lower-bounded wildcard (Java)

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
like image 952
Matt G Avatar asked Oct 04 '22 07:10

Matt G


1 Answers

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.

like image 50
chrylis -cautiouslyoptimistic- Avatar answered Oct 11 '22 17:10

chrylis -cautiouslyoptimistic-