如何从另一个泛型类调用泛型接口方法

时间:2014-09-19 23:50:59

标签: java generics interface

这是我的代码。
我有一个通用接口

public interface ClientServerComparator<T> {
    public boolean compare(T entity,T obj);
}

我正在尝试实现另一个泛型类

public class EntityTest<T> {

  public void testPutObject(Client client, T obj ) throws UnExpectedStatusException 
    {
        log.debug("PUT: " + location);
      T entity = testGetObject(client,entityLocation,l);

     if(entity instanceof ClientServerComparator<?> )
     {
        if( false ==  ((ClientServerComparator<?>) entity).compare(entity,obj) )
        {
            log.error("Object fetched back does not match object put");
            throw new UnExpectedStatusException();
        }

     }

    }

我收到以下编译错误:

The method compare(capture#1-of ?, capture#1-of ?) in the type 
ClientServerComparator<capture#1-of ?> is not applicable for the arguments (T, T)

如何让EntityTest泛型类在实现ClientServerComparator泛型接口的对象上调用方法?

2 个答案:

答案 0 :(得分:1)

我认为问题在于您使用的通配符告诉编译器,该实体是任何ClientServerComparator,不一定与T相关。

但是,您已经知道实体是T类型(您已通过实例化实体的类型注释定义)。此外,您正在检查实体是否是ClientServerComparator的实例。我假设,您始终期望实体成为ClientServerComparator的实例。如果是这种情况,那么您可以将EntityTest的泛型类型更改为<T extends ClientServerComparator<T>>并删除实例检查和类型转换:

public class EntityTest<T extends ClientServerComparator<T>> {

    public void testPutObject(Client client, T obj) {
        T entity = testGetObject(client);

        if (entity.compare(entity, obj)) {
            throw new UnExpectedStatusException();
        }

    }
}

现在T是ClientServerComparator<T>,因此您可以在实体上调用compare。

答案 1 :(得分:0)

T是您的班级EntityTestClientServerComparator中的类型变量。但它是变量,这意味着它并不表示两个类中的相同类型。您可以在T中使用Z之类的其他名称调用ClientServerComparator,但这不会改变您的代码含义。

因此,要在两个类型为变量compare的对象上调用T方法,首先需要将对象转换为ClientServerComparator<T>而不是ClientServerComparator<?>。在后一种情况下,它不知道类型是什么(<?>),因此您不能使用泛型类型的参数调用任何方法[您只能调用返回泛型类型的方法]

如果你转向(ClientServerComparator<T>),你会收到编辑关于&#34;未经检查的演员&#34;的警告。这是因为在Java中,泛型只是编译时类型安全的。在运行时,类型变量T的实际值不再为人所知。

从技术上讲,你可能有一个实现Foo的类ClientServerComparator<Bar>。如果您知道代码中没有此代码,则可以使用@SuppressWarnings("unchecked")注释来禁止编译器警告。

像这样:

@SuppressWarnings("unchecked")
public void testPutObject(Client client, T obj) throws UnExpectedStatusException {
    T entity = testGetObject(client, entityLocation, l);

    if (entity instanceof ClientServerComparator) {
        if (false == ((ClientServerComparator<T>) entity).compare(entity, obj)) {
            throw new UnExpectedStatusException();
        }
    }

}