2

我正在使用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;
  1. 有没有办法避免执行此演员阵容所需的中间步骤?

  2. 是什么导致了第一个演员的问题?

4

2 回答 2

2

问题出在方法定义“getRepositoryFor”中。除非您将其分配给定义了泛型的变量,否则它不会为“T”泛型建立合同。

public <T,S extends Serializable> CrudRepository<T,S> getRepositoryFor(Class<?> domainClass)

我猜那个级别的编译器看不到CustomerRepositoryextends 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 中的一个复杂领域,并且存在一些已知的限制来降低编译器的复杂性。

于 2013-05-25T21:41:02.610 回答
0

This is about type inference. Say we have method declaration

<T> T foo(){ return null; }

and a statement like

foo(); 

there is not enough information to infer T here.

Couldn't compiler use context information to aid inference, like

void bar(String str){ }

bar(foo());  // T must be String, right?

In general that's not supported; you can imagine how complicate it can get in general.

However in two specific cases, the target type is taken into consideration in type inference

String s = foo();   // assign it to a type

String baz()
{
    return foo();   // return it to a type
}

That is true from Java5 to Java7.

In Java 8, type inference take advantage of more contextual type information, your code may work then:)

于 2013-05-26T00:59:07.487 回答