为什么基于Class.class的转换工作但不是getClass?

时间:2014-10-08 17:39:01

标签: java class generics casting

我有以下3项测试。前两个工作,最后一个没有。我提出这个问题的动机是,我希望能够转换对象A,使其与对象B具有相同的类,当A已知为子类型时B

  @Test
  public void testWorks() {
    Object bar = "foobar";
    String blah = (String) bar;
    System.out.println(blah); // Outputs foobar
  }

  @Test
  public void testAlsoWorks() {
    Object bar = "helloworld";
    String blah = String.class.cast(bar);
    System.out.println(blah);  // Outputs helloworld
  }

  @Test
  public void testfails() {
    Object bar = "foobar";
    String thetype = "hello";
    Class stringclass = thetype.getClass();
    String blah = stringclass.cast(bar); // Compiler error: incompatible types: Object cannot be converted to String                                                                                                            
    System.out.println(blah);
  }

任何人都可以解释为什么最后一个案例在前两个案件成功时失败了,为什么会出现这种情况?什么是更好的方法来实现这一目标?

2 个答案:

答案 0 :(得分:16)

您需要指定Class的类型参数:

Class<String> stringclass = (Class<String>) thetype.getClass();

Class<? extends String> stringclass = thetype.getClass();

java.lang.Class.cast(Object obj)将一个对象强制转换为此Class对象所代表的类或接口。

如果没有指定类型,则不会告诉编译器Class实例stringclass表示哪个类或接口。

当您致电String.class时,Class对象会使用String类型进行隐式参数化。

答案 1 :(得分:11)

Java Language Specification

  

C.class的类型,其中C是类,接口或的名称   数组类型(§4.3),是Class<C>

所以表达式的类型

String.class

Class<String>Class是一个泛型类,其中方法cast在其返回类型中使用泛型类型变量。所以

的结果
String.class.cast(bar);

T类型的表达式,其中T已在此调用中绑定到String

Object#getClass()的返回类型为Class<? extends T>,其中T是其调用的表达式的已删除类型。

在这种情况下,那是

Class<? extends String>

但是,您要将其分配给原始参考。

Class stringclass = thetype.getClass();

由于变量stringclassraw, any uses of its methods that depend on the generic type variable are erased.

所以Class#cast(Object)现在的返回类型为Object,不能分配给String变量。

你做完了

Class<? extends String> stringclass = thetype.getClass();
你会好的。