如何将我的类传递给类的泛型规范?

时间:2015-06-03 21:49:18

标签: java java-7

我有以下方法签名

public abstract class AbstractFilterParametersWithSpecificationSorting<T> extends AbstractFilterParameters
...

public void registerOrderSpecification( final String key, final Class<? extends OrderSpecification<T>> spec ) {
...

我通过以下

    this.registerOrderSpecification(
            AbstractActivityLogWithSiteUser.Index.USER_FULL_NAME,
            SortActivityLogUserOrderSpecification.class );

具有此类定义

public class SortActivityLogUserOrderSpecification<AL extends AbstractActivityLogWithSiteUser<?>>
    extends AbstractOrderSpecification<AL> implements OrderSpecification<AL>

这里javac并不喜欢(IDEA认为它应该有效,但IDEA在Java 8上运行,代码必须在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
我可以施展吗?或者我在某个地方遗漏了一些问号?

2 个答案:

答案 0 :(得分:0)

我尝试了你的代码然后开始简化它以获得一个显示同样问题的小例子。我终于得到了这个(更简单的)代码:

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);
    }

}

生成此错误:

TestGenerics2.java:11: processListClass(java.lang.Class<? extends java.util.List<T>>) in TestGenerics2<T> cannot be applied to (java.lang.Class<MyList>)

我认为你应该把它(或重构你的代码,以便你不需要那个泛型的复杂性)。

Jon Skeet once said

  

有时Java泛型不会让你做你想做的事情,你需要有效地告诉编译器你在执行时真正做的事情是合法的。

答案 1 :(得分:0)

因此,我的回答是通过记住在Java 7中生成菱形<>运算符的投诉而获得的,并且该支持在8中得到了改进。

你为什么要写

List<Foo> foos = new ArrayList<Foo>();

List<Foo> foos = Lists.newArrayList();

会起作用。这当然催生了钻石运营商

List<Foo> foos = new ArrayList<>();

所以我写了一个方法来包装我的类参数

protected <E extends OrderSpecification<T>> Class<E> java7classReturnType( Class<E> clazz ) {
    return clazz;
}

并且调用它将正常工作

Class<? extends OrderSpecification<OrganizationActivityLog>> clazz
            = this.java7classReturnType( SortActivityLogUserOrderSpecification.class );
    this.registerOrderSpecification( AbstractActivityLogWithSiteUser.Index.USER_FULL_NAME, clazz );
}