【问题标题】:Why does casting based on Class.class work but not getClass?为什么基于 Class.class 的强制转换有效但 getClass 无效?
【发布时间】:2014-10-08 17:39:01
【问题描述】:

我进行了以下 3 项测试。前两个有效,最后一个无效。我提出这个问题的动机是我希望能够转换对象A,以便它与对象B 具有相同的类,而AB 的子类型。

  @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);
  }

谁能解释为什么前两个成功时最后一个失败,为什么会这样?实现这一目标的更好方法是什么?

【问题讨论】:

  • 我假设是因为 .class 是在编译时评估的,但 .getClass() 是在运行时评估的。
  • 编译器应该警告你使用原始类型Class而不是参数化类型Class<>,这将暗示你的声明有问题。

标签: java class generics casting


【解决方案1】:

需要指定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 类型进行参数化。

【讨论】:

    【解决方案2】:

    Java Language Specification 状态

    C.class 的类型,其中C 是类、接口或 数组类型(§4.3),是Class&lt;C&gt;

    所以表达式的类型

    String.class
    

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

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

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

    Object#getClass() 的返回类型是 Class&lt;? extends T&gt;,其中 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();
    

    你会没事的。

    【讨论】:

      猜你喜欢
      • 2022-01-09
      • 1970-01-01
      • 2017-10-19
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2016-09-18
      • 2020-06-17
      • 1970-01-01
      相关资源
      最近更新 更多