I have the following method signature
public abstract class AbstractFilterParametersWithSpecificationSorting<T> extends AbstractFilterParameters
...
public void registerOrderSpecification( final String key, final Class<? extends OrderSpecification<T>> spec ) {
...
I'm passing the following
this.registerOrderSpecification(
AbstractActivityLogWithSiteUser.Index.USER_FULL_NAME,
SortActivityLogUserOrderSpecification.class );
which has this class definition
public class SortActivityLogUserOrderSpecification<AL extends AbstractActivityLogWithSiteUser<?>>
extends AbstractOrderSpecification<AL> implements OrderSpecification<AL>
here's what javac
doesn't like (IDEA thinks it should work, but IDEA is running on Java 8, and the code must compile on Java 7)
Error:(12, 21) java: method registerOrderSpecification in class com.myapp.service.principal.AbstractFilterParametersWithSpecificationSorting<T> cannot be applied to given types;
required: java.lang.String,java.lang.Class<? extends com.myapp.specification.OrderSpecification<AL>>
found: java.lang.String,java.lang.Class<com.myapp.repository.activitylog.specification.SortActivityLogUserOrderSpecification>
reason: actual argument java.lang.Class<com.myapp.repository.activitylog.specification.SortActivityLogUserOrderSpecification> cannot be converted to java.lang.Class<? extends com.myapp.specification.OrderSpecification<AL>> by method invocation conversion
can I cast it? or am I missing some question mark somewhere?
I tried your code and then started simplifying it to get to a smaller example that showed the same problem. I finally got to this (much simpler) code:
abstract class MyList<T> implements java.util.List<T> {
}
public class TestGenerics2<T> {
public void processListClass(final Class<? extends java.util.List<T>> spec ) {
}
public void tryIt() {
this.processListClass(MyList.class);
}
}
Generates this error:
TestGenerics2.java:11: processListClass(java.lang.Class<? extends java.util.List<T>>) in TestGenerics2<T> cannot be applied to (java.lang.Class<MyList>)
I think you should cast it (or refactor your code so that you don't need that generic's complexity).
Like Jon Skeet once said :
Sometimes Java generics just doesn't let you do what you want to, and you need to effectively tell the compiler that what you're doing really will be legal at execution time.
So my answer is inspired by remembering the complaint that spawned the diamond <>
operator in Java 7, and that support was improved in 8.
Why should you write
List<Foo> foos = new ArrayList<Foo>();
when
List<Foo> foos = Lists.newArrayList();
will just work. This of course spawned the diamond operator
List<Foo> foos = new ArrayList<>();
so I wrote a method to wrap my class parameter
protected <E extends OrderSpecification<T>> Class<E> java7classReturnType( Class<E> clazz ) {
return clazz;
}
and calling this will work fine
Class<? extends OrderSpecification<OrganizationActivityLog>> clazz
= this.java7classReturnType( SortActivityLogUserOrderSpecification.class );
this.registerOrderSpecification( AbstractActivityLogWithSiteUser.Index.USER_FULL_NAME, clazz );
}
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.