views:

186

answers:

4

While preparing for the SCJP-6 exam I faced with a difficult issue. I can’t find answer by myself. Please, answer for the question and give short comments:

abstract class A<K extends Number> {
   // insert code here
}    
  1. public abstract <K> A<? extends Number> useMe(A<? super K> k);

  2. public abstract <K> A<? super Number> useMe(A<? extends K> k);

  3. public abstract <K> A<K> useMe(A<K> k);

  4. public abstract <V extends K> A<V> useMe(A<V> k);

  5. public abstract <V super K> A<V> useMe(A<V> k);

  6. public abstract <V extends Character> A<? super V> useMe(A<K> k);

  7. public abstract <V super Character> A<? super V> useMe(A<K> k);

Which method can be inserted in the placeholder above?

P.S. I tried to look on the specification. Those one was not helpful for me.

A: 

Only the second (public abstract A useMe(A k);) seems to work, just plugging it into an IDE.

James Kingsbery
+2  A: 

The best way to go about this is to try each one and see what the compiler tells you. I get the following results for each one (using NetBeans, so your results may vary slightly):

public abstract <K> A<? extends Number> useMe(A<? super K> k);
// seems to work

public abstract <K> A<? super Number> useMe(A<? extends K> k);
// type parameter ? extends K is not within its bound

public abstract <K> A<K> useMe(A<K> k);
// type parameter K is not within its bound

public abstract <V extends K> A<V> useMe(A<V> k);
// seems to work

public abstract <V super K> A<V> useMe(A<V> k);
// > expected
// illegal start of type
// <identifier> expected
// missing method body, or declare abstract
// cannot find symbol
//   symbol: class V
//   location: class A<K>

public abstract <V extends Character> A<? super V> useMe(A<K> k);
// type parameter ? super V is not within its bound

public abstract <V super Character> A<? super V> useMe(A<K> k);
// > expected
// illegal start of type
// <identifier> expected
// missing method body, or declare abstract
Bill the Lizard
Thank you for your answer! I also tried to feed the compiler with this code. I want to understand compiler's logic. For example, third variant: why "K" is not within bounds?
abatishchev
@abatishchev: The class declaration specifies that `K extends Number`, but the third variant uses an unbounded `K`. I'd Google each error message, or check out the Java [Generics Tutorial](http://java.sun.com/docs/books/tutorial/java/generics/index.html) for more details on what's allowed.
Bill the Lizard
+1  A: 

I'll try to explain a bit more...

1 does not work because you cannot substitute A<? super K> for A<K extends Number>... no guarantee that a superclass extends the same class as the subclass.

1, 2 and 3 do not work because the initial type parameter hides the original K used in the class declaration.

5 does not work because <V super K> cannot substitute for <K extends Number>... no guarantee that a superclass extends the same class as the subclass.

6 & 7 should be obvious.

4 works because if we know V extends K then we know V extends Number (since all classes that K extends V extends). We can therefore substitute A<V> for <K extends Number>.

I hope this makes sense... someone may be able to come along and explain better.

derivation
+2  A: 

Answer 1,2,3: The generic type K shadowed class type K. In those methods K is just new generic type. Compiler tries to pass conditional evaluation <K extends Number>. Method 1,2 passes and 3 - fails.

Answer 4 is completely correct.

Answer 5,7 has syntax error.

Answer 6 incorrect, because test <V extends Number> will fail.

dya-victor