generics:< ? >vs.< T >

S

Stefan Ram

I believe that

java.lang.Comparable< ? >

means that any java.lang.Comparable type can be accepted.
The type parameter might also be named as in

< T > ........ final java.lang.Comparable< T >

, but I believe that this also allows any
java.lang.Comparable type, just that it is named »T«.

Then why is the following SSCCE not possible?

interface Alpha { void alpha( final java.lang.Comparable< ? >x ); }

class Beta implements Alpha
{ public< T >void alpha( final java.lang.Comparable< T >x ){} }

public class Main
{ public static void main( final java.lang.String[] args ){} }

Main.java:3: Beta is not abstract and does not override abstract method alpha(java.lang.Comparable<?>) in Alpha
class Beta implements Alpha
^
1 error
 
J

Joshua Cranmer

I believe that

java.lang.Comparable< ?>

This roughly means "This is a comparable of any type" (unknown may also
work here).
< T> ........ final java.lang.Comparable< T>

This roughly means "This is a comparable of some type, to be given by
the user."

There is a distinction.
 
M

markspace

Then why is the following SSCCE not possible?


I think for the same reason that the SSCCE below is not possible: Java
inheritance rules say that covariant parameters do not over-ride a base
method, the overload it. (Did I say that right?) Covariance is only
allowed on the return type, not the method parameters.


interface Alpha {
void gamma( final Object o );
}

class Beta implements Alpha {
public void gamma( final String s ) {}
}
 
J

Joshua Cranmer

I think for the same reason that the SSCCE below is not possible: Java
inheritance rules say that covariant parameters do not over-ride a base
method, the overload it. (Did I say that right?) Covariance is only
allowed on the return type, not the method parameters.

Not quite fully true:

interface Alpha<T> {
void gamma(T t);
}

class Beta implements Alpha<Beta> {
void gamma(Beta b) {}
}

The gamma(Beta b) more or less overrides the gamma(T t), although the
reality is that the compiler emits the following method:
void gamma(Object o) { gamma((Beta)o); }

So yes. And no.
 
M

markspace

The gamma(Beta b) more or less overrides the gamma(T t), although the
reality is that the compiler emits the following method:
void gamma(Object o) { gamma((Beta)o); }

So yes. And no.

Right, so really it's "gamma(Object)" that Alpha declares, and Beta has
to use the same signature. I don't think anything in the JLS obviates
that. So I interpret that as "no," not even generics can violate the
Java rules of inheritance.

Also, now that I think about it, parameterized types are always
invariant, never covariant.

class Alpha<T> {
public Alpha<Object> example() { return null; }
}

class Beta extends Alpha {
public Alpha<String> example() { return null; }
}

is not allowed ever, because the return types are not covariant.
 
L

Lew

Right, so really it's "gamma(Object)" that Alpha declares, and Beta has to use
the same signature. I don't think anything in the JLS obviates that. So I
interpret that as "no," not even generics can violate the Java rules of
inheritance.

Also, now that I think about it, parameterized types are always invariant,
never covariant.

class Alpha<T> {
public Alpha<Object> example() { return null; }
}

class Beta extends Alpha {
public Alpha<String> example() { return null; }
}

is not allowed ever, because the return types are not covariant.

Generics are tricky because we tend to think of them as instructions. They
are not.

'<?>' does not mean "any type"; it means "an arbitrary but unknown subtype of
Object". '<T>' doesn't mean "any type"; it means "a particular inferrable
(therefore known) type". The biggest difference is that the wildcard does not
assert which particular type is in play, but the type parameter does.

That's why they're incompatible. No way the compiler can assert that some
unknown wildcard type (the capture of the wildcard's bound) is reliably
compatible with the assertrf type 'T'. We just don't know which type the
wildcard represents and cannot match it to 'T'.
 
S

Stanimir Stamenkov

Wed, 09 Mar 2011 07:32:17 -0500, /Lew/:
'<?>' does not mean "any type"; it means "an arbitrary but unknown
subtype of Object".

Hm, I thought '<?>' means "any type possibly not an Object subtype"
as a type could be defined by an interface which doesn't inherit
from the Object class. That's what I thought the reason I cannot
assign 'List<?>' to an 'List<Object>', for example. The '<? extends
Object>' would be "an arbitrary but unknown subtype of Object".
 
L

Lew

Stanimir said:
/Lew/:

Hm, I thought '<?>' means "any type possibly not an Object subtype" as a type
could be defined by an interface which doesn't inherit from the Object class.

Good point.
 
A

Arved Sandstrom

Good point.
I haven't the time this morning, before schlepping off to work, to delve
into JLS intricacies, but the observation that the interface doesn't
inherit from the Object class doesn't seem quite right with me.

It's in Section 9.2 of the JLS, "Interface Members", that each interface
(if there are no direct superinterfaces), _implicitly_ declares public
abstract member methods that match the public instance methods of Object
(unless the interface declares an override-equivalent that also has the
same return type and throws).

Following from that, it's a 5-minute experiment to write a simple test
that creates an instance of an anonymous class that implements an
interface, and inspect the Class of the superclass of that anonymous
class instance - it is, as one might expect, java.lang.Object.

And I think it's relevant that Section 4.10.2 says, among other things,
that the direct supertype of an interface type C is the type Object, if
C has no superinterfaces. You'd expect to see that statement given
common sense, and the actual behaviour as exhibited by a simple example.

It's not that _interface_ inherits from the Object class, but every
object that could conceivably implement it ultimately will.

AHS
 
S

Stanimir Stamenkov

Thu, 10 Mar 2011 07:00:56 -0400, /Arved Sandstrom/:
I haven't the time this morning, before schlepping off to work, to
delve into JLS intricacies, but the observation that the interface
doesn't inherit from the Object class doesn't seem quite right
with me.

It's in Section 9.2 of the JLS, "Interface Members", that each
interface (if there are no direct superinterfaces), _implicitly_
declares public abstract member methods that match the public
instance methods of Object (unless the interface declares an
override-equivalent that also has the same return type and throws).

Yes, every instance in Java is expected to be an 'Object' subtype
and the JLS seems to take this into account to make the following
possible:

Comparable obj;
...
obj.toString();

The 'Comparable' interface doesn't declare a 'toString()' method,
still one can invoke it on references declared as 'Comparable'
without casting. And that doesn't explain why '<?>' and '<Object>'
are not compatible. May be it is omission in the specification and
implementation of the Java Generics?
 
D

Daniele Futtorovic

And that doesn't explain why '<?>' and '<Object>' are not
compatible. May be it is omission in the specification and
implementation of the Java Generics?

Because List<?> might be inferred to be, say, List<T>, and List<T> is
not a subtype of List<Object>.
 
S

Stanimir Stamenkov

Thu, 10 Mar 2011 19:00:51 +0100, /Daniele Futtorovic/:
Because List<?> might be inferred to be, say, List<T>, and List<T>
is not a subtype of List<Object>.

The point made was in Java everything effectively inherits from
Object (even interface types), so why <T> would not be subtype of
<Object>?
 
D

Daniele Futtorovic

Thu, 10 Mar 2011 19:00:51 +0100, /Daniele Futtorovic/:

The point made was in Java everything effectively inherits from Object
(even interface types), so why <T> would not be subtype of <Object>?

The point is that List<T> /is not a/ List<Object>.
 
L

Lew

The point is that List<T> /is not a/ List<Object>.

If we use '<=' as a type operator to mean "is a subtype of", and '!<='
to mean "is not a subtype of", then

( T <= U ) does not imply ( Foo<T> <= Foo<U> )

In fact, you will usually find ( Foo<T> !<= Foo<U> ).

I don't have time or energy right now to figure out if "usually" there
should be "always".
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

Forum statistics

Threads
473,755
Messages
2,569,536
Members
45,007
Latest member
obedient dusk

Latest Threads

Top