views:

137

answers:

3

I'm looking at some code with this form:


     1  package com.stackoverflow.java.questions;

     2  import java.util.ArrayList;
     3  import java.util.List;

     4  public class B extends A<B> {
     5      
     6      private
     7      <C extends A>
     8      List<C> getList(Class<C> cls) {
     9          
    10          List<C> res = new ArrayList<C>();

                 // "snip"... some stuff happening in here, using cls

    11          return res;
    12      }

    13      public
    14      List<A> getList() {
    15          return getList(A.class);
    16      }

    17  }

    18  abstract class A<C extends A<C>> {

    19  }


Yes, I know it's ugly, but I reduced it as much as I could manage.

My question is how do I properly parameterize the use of A on lines 7, 14, and 15?

Currently, I get warnings (A is a raw type. References to generic type A should be parameterized) from Eclipse for lines 7 and 14. I suspect that I would get one for line 15 as well once I fix the other two, but I'm not certain. Either way, it's not currently parameterized and probably ought to be, but I have no idea what the syntax is supposed to be.

Any thoughts on how to add the proper parameter semantics and syntax to get rid of these warnings?

Note: I'm not sure if it matters whether or not A is a recursive generic. I still get the same warnings if I simply use "abstract class A {}" in place of its current definition.

Honestly, if it were my own code I'd change it all to be a heck of a lot simpler. Unfortunately, it's part of an API so I'm trying to change it as little as possible.

Thanks!

UPDATE:

I'm able to address the warnings by parameterizing them as one would expect, but at the cost of an error. It comes down to this, how do I get a Class<A<B>> from an abstract class?

Something like,

Class<A<B>> cls = A.class;

However, this causes a type mismatch error.

UPDATE, part 2:

Turns out, ya just can't do it due to type erasure. See my other question here.

+4  A: 

You could start by using <C extends A<B>> and List<A<B>> in those first two instances. Passing a type key is, in this case, counterproductive (see how the cls parameter is never used), so, just strip it out.

(You can always say B.<Foo>getList() to specifically instantiate it with a specific type, assuming you're happy for the type to be non-reified of course.)


Update to incorporate OP's edit: Will using A<?> work for your code? In limited cases, you may not need to fully specify the type. Unfortunately, I don't have your code, so only you can find out whether it'll work.

Chris Jester-Young
That's a good point, however I did leave out the fact that the type key is used in the actual code. I must have accidentally cut it out when I added the example.I'll give the other stuff a shot first and report back.
Tom
And in response to your update--I first started out using List<A<?>> on line 14, but then I get the a type mismatch on line 15. (Can't convert from Class<A> to Class<A<?>>.) Just the same, thanks for the suggestion.
Tom
@Tom: Huge bummer. :-( Well, we tried. :-)
Chris Jester-Young
Do you suppose it's not possible to do something like this: A<?>.class? I get a syntax error when I try to do this. (I'm not sure it really makes sense, since .class refers to a static instance of Class for that type, right? What would this even mean w.r.t. generics?) Sounds like time for yet another question. ;-)
Tom
A: 

What exactly do you do here with cls:

// "snip"... some stuff happening in here, using cls

Depending on what you do here, you could possibly replace the Class instance with a Type instance, if you tell me a little more about what you do here I may be able to present you an alternate solution to make it work.

Santi P.
A: 

Turns out, ya just can't do it due to type erasure. See my other question here: http://stackoverflow.com/questions/2390662/java-how-do-i-get-a-class-literal-from-a-generic-type

Tom