我使用import org.springframework.data.repository.support.Repositories
在Quartz Job中获取Spring Data Repository的实例。
Repositories
类有一个getRepositoryFor(Class<?> domainClass)
方法,它返回相应存储库的实例,但存储库的类型为CrudRepository<Object, Serialiazable>
。
如果我尝试将返回的CrudRepository
向上转换为自定义存储库类型CustomerRepository
,Eclipse会通知我无法执行强制转换。
// Eclipse Error: Cannot cast from CrudRepository<Object,Serializable>
// to CustomerRepository
this.customerRepository =
(CustomerRepository)super.repositories.getRepositoryFor(Customer.class);
但是,如果我将存储库分配给CrudRepository<Customer, Long> repository
类型的字段,那么我可以转换为CustomerRepository
。
//No Problems here
CrudRepository<Customer, Long> repository =
super.repositories.getRepositoryFor(Customer.class);
CustomerRepository repository = (CustomerRepository) repository;
是否还要避免执行所需的中间步骤 这个演员?
第一次演员导致问题的原因是什么?
答案 0 :(得分:2)
问题出在方法定义“getRepositoryFor”中。除非您将其分配给定义了泛型的变量,否则它不会为“T”泛型建立合同。
public <T,S extends Serializable> CrudRepository<T,S> getRepositoryFor(Class<?> domainClass)
我想那个级别的编译器看不到CustomerRepository
扩展CrudRepository<Customer, Long>
。我想这个例子可以帮助您理解这个问题:
public class TestCast {
public static class MyMap extends HashMap<String, String> {
}
public static <T> Map<T,String> getMap1(Class<?> myClass) {
return new HashMap<T,String>();
}
public static <T> Map<T,String> getMap2(Class<T> myClass) {
return new HashMap<T,String>();
}
public static void main(String[] args) {
// Works, because it knows T is String as you state it with the variable type Map<STRING,String>
Map<String,String> map = getMap(String.class);
// Compilation error, it doesn't know T is String and cast won't work either
MyMap myMap = getMap1(String.class);
// Works, because it knows T is String as it is getting it in the method parameter, no need to rely on the variable that is getting the value
MyMap myMap = (MyMap) getMap2(String.class);
}
}
这是Java中的一个复杂领域,有一些已知的限制可以降低编译器的复杂性。
答案 1 :(得分:0)
这是关于类型推断。假设我们有方法声明
<T> T foo(){ return null; }
和
之类的陈述foo();
此处没有足够的信息来推断T
。
无法编译器使用上下文信息来辅助推理,例如
void bar(String str){ }
bar(foo()); // T must be String, right?
一般来说,不支持;你可以想象一般来说它会变得多么复杂。
然而,在两种特定情况下,类型推断中会考虑目标类型
String s = foo(); // assign it to a type
String baz()
{
return foo(); // return it to a type
}
从Java5到Java7都是如此。
在Java 8中,类型推断利用了更多的上下文类型信息,您的代码可能会起作用:)