0

I am a bit baffled about Java type checking:

I have a static method declared as:

public static void register(EClass eClass, Class<? extends Page<EObject>> pClass) { ... }

I call it as:

Page.register(HyconmdePackage.Literals.STATION, StationPage.class);

where the second argument is declared as (forget about the first one: it's ok):

public class StationPage extends Page<Station> { ...
public abstract class Page<O> { ...
public interface Station extends Identifiable { ...
public interface Identifiable extends EObject { ...

but I get the error:

The method register(EClass, Class<? extends Page<EObject>>) in the type Page is not applicable for the arguments (EClass, Class<StationPage>)

I tried also declaring Page as:

public abstract class Page<O extends EObject> { ...

but the error remains and I have further problems in class Page.

What's my error? (I hope this is enough to guess the problem; trimming down program to size to have a working example would not be a trivial task)

TiA

ZioByte
  • 2,690
  • 1
  • 32
  • 68

2 Answers2

2

StationPage extends Page<Station>, but your method signature requires it to extend Page<EObject>.

Note that, even though Station (indirectly) extends EObject, this does not mean that Page<Station> extends Page<EObject>. So you cannot use Page<Station> when a Page<EObject> is expected.

Declare the method like this:

public static void register(EClass eClass,
    Class<? extends Page<? extends EObject>> pClass)

You can ofcourse also use type parameters instead of wildcards:

public static <P extends Page<E>, E extends EObject> register(EClass eClass,
    Class<P> pClass)
Jesper
  • 202,709
  • 46
  • 318
  • 350
  • Weird: if I put **both** methods I get error `Erasure of method register(EClass, Class extends Page>) is the same as another method in type Page`. I assume it means Compiler **knows** the methods are different, but it also knows JVM won't be able to distinguish. Is this right? – ZioByte Jul 05 '14 at 12:39
  • Yes, because of [type erasure](http://stackoverflow.com/questions/313584/what-is-the-concept-of-erasure-in-generics-in-java). – Jesper Jul 05 '14 at 12:42
1

Simple. Page<Station> is not considered to extend Page<EObject>. Check again the generics tutorial at oracle.com

To see what I mean, look how would this code work if Page<Station> was considered to extend Page<EObject>

public void addItem(Page<EObject> page, EObject item) {
  page.add(item);
  ...
}

addItem(new StationPage(), new EObject());

That would result in an error, since you are attempting to pass an EObject to a method that expects Station. An error that the JVM would not be able to identify as such, since the generics information is not used at runtime. So, the compiler must interpret that as a compilation error, and StationPage does not extend from Page<Object>

Using generics as Jesper instructed

public void addItem(Page<? extends EObject> page, EObject item) {

will allow the compilation, but will put restrictions in the type of operations that you may use with the page parameter (it will not allow to call page.addItem, exactly for the same motive).

SJuan76
  • 24,532
  • 6
  • 47
  • 87