了解Guava的TypeToken.isAssignableFrom方法

Ser*_*gio 6 java generics reflection types guava

我正在使用Guava TypeToken类来测试是否可以将任意类型的实例分配给其他类型的对象.

在下面的代码片段中,我正在测试声明为List可分配的类型List<String>,并且反之亦然:

TypeToken rawListType = new TypeToken<List>(){};
TypeToken parameterizedListType = new TypeToken<List<String>>(){};
System.out.println(rawListType.isAssignableFrom(parameterizedListType)); //true
System.out.println(parameterizedListType.isAssignableFrom(rawListType)); //false
Run Code Online (Sandbox Code Playgroud)

为什么第二次调用isAssignableFrom返回false?,假设下面的代码编译,所以我可以List<String>List(带警告)分配?:

List l = null;
List<String> l2 = null;
l = l2; 
l2 = l; //Type Safety Warning 
Run Code Online (Sandbox Code Playgroud)

我的直觉是Guava正在回答这些类型的实例是否可以在没有警告的情况下分配(?).如果这是正确的,我怎么可能检查可转让的编译器允许我分配一个对象到另一个(有或没有警告),就像是在第二个代码片段所示?感.

Pau*_*ora 3

正如您所说,我们知道编译器将允许从原始类型分配泛型类型,但这并不意味着可分配性。编译器正在执行隐式未经检查的强制转换(因此出现警告)。

由于您确实想检查相应原始类型的可分配性,因此您可以只使用TypeToken.getRawType然后使用Class.isAssignableFrom.

编辑:正如您所指出的,这种方法可以相互计数List<Integer>和分配。List<String>为了避免这种情况,我认为你需要一个更通用的解决方案:

boolean checkRawAssignability(TypeToken<?> assigned, TypeToken<?> from) {

    //if from is a raw type, compare raw types instead
    final Type fromType = from.getType();
    if (fromType instanceof Class<?>) {
        return assigned.getRawType().isAssignableFrom((Class<?>)fromType);
    }

    //otherwise use normal methodology
    return assigned.isAssignableFrom(from);
}
Run Code Online (Sandbox Code Playgroud)

请注意,此解决方案不考虑数组类型。

  • @Sergio:恕我直言,TypeToken 实现的是更重要的概念。编译器所做的是一种黑客行为(就像原始类型本身的使用一样)。无论如何,应该记录下来,我建议[提出问题](http://code.google.com/p/guava-libraries/issues/entry)。 (2认同)