Java类中的懒惰类? [英] Lazy class cast in Java?

查看:270
本文介绍了Java类中的懒惰类?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

有人可以告诉我为什么我在这个片段中没有得到 ClassCastException ?我非常感兴趣,为什么它不工作,因为我的期望。我现在不在乎这是否是不好的设计。

  public class Test {
static class父{
@Override
public String toString(){returnparent; }
}

static class ChildA extends父{
@Override
public String toString(){returnchild A; }
}

static class ChildB extends父{
@Override
public String toString(){returnchild B; }
}

public< C extends Parent> C get(){
return(C)new ChildA();
}

public static void main(String [] args){
Test test = new Test();

//应该抛出ClassCastException ...
System.out.println(test。< ChildB> get());

// throws ClassCastException ...
System.out.println(test。< ChildB> get()。toString());
}
}

这是java版本,编译和运行输出:

  $ java -version 
java版本1.7.0_17
Java环境(构建1.7.0_17-b02)
Java HotSpot(TM)64位服务器VM(构建23.7-b01,混合模式)
$ javac -Xlint:unchecked Test.java
Test .java:24:warning:[unchecked] unchecked cast
return(C)new ChildA();
^
必需:C
found:ChildA
其中C是一个类型变量:
C extends方法中声明的父< C> get $ b 1 warning
$ java Test
child A
线程main中的异常java.lang.ClassCastException:Test $ ChildA不能转换为Test $ ChildB
。 main(Test.java30)


解决方案

类型擦除:泛型只是一个语法特征,通过编译器(出于兼容性原因),并在需要时替换为



在运行时, C get 方法不知道 C (这就是为什么你不能实例化 new C())。 test。< ChildB> get()实际上是对 test.get 的调用。 return(C)new ChildA()转换为 return(Object)new ChildA()无限类型 C (其最左边界)。然后,不需要转换,因为 println 期望将 Object 作为参数。



另一方面, test。< ChildB> get()。toString()失败,因为在调用 toString()之前,将get()强制转换为 ChildB 注意,像 myPrint(test。< ChildB> get())的调用也将失败。 返回的 Parent 返回键入 ChildB 在调用 myPrint 时完成。

  public static void myPrint child){
System.out.println(child);
}


Can someone please enlighten me as to why I don't get a ClassCastException in this snippet? I'm strictly interested into why it isn't working as I was expecting. I don't care at this point whether this is bad design or not.

public class Test {
  static class Parent {
    @Override
    public String toString() { return "parent"; }
  }

  static class ChildA extends Parent {
    @Override
    public String toString() { return "child A"; }
  }

  static class ChildB extends Parent {
    @Override
    public String toString() { return "child B"; }
  }

  public <C extends Parent> C get() {
    return (C) new ChildA();
  }

  public static void main(String[] args) {
    Test test = new Test();

    // should throw ClassCastException...
    System.out.println(test.<ChildB>get());

    // throws ClassCastException...
    System.out.println(test.<ChildB>get().toString());
  }
}

This is the java version, compilation, and run output:

$ java -version
java version "1.7.0_17"
Java(TM) SE Runtime Environment (build 1.7.0_17-b02)
Java HotSpot(TM) 64-Bit Server VM (build 23.7-b01, mixed mode)
$ javac -Xlint:unchecked Test.java
Test.java:24: warning: [unchecked] unchecked cast
    return (C) new ChildA();
               ^
  required: C
  found:    ChildA
  where C is a type-variable:
    C extends Parent declared in method <C>get()
1 warning
$ java Test
child A
Exception in thread "main" java.lang.ClassCastException: Test$ChildA cannot be cast to Test$ChildB
  at Test.main(Test.java:30)

解决方案

Type erasure: generics is only a syntactic feature that is removed by the compiler (for compatibility reasons) and replaced by casts where required.

In runtime, the method C get doesn't know the type of C (that is why you cannot instantiate new C()). An invocation of test.<ChildB>get() is actually an invocation of test.get. return (C) new ChildA() is converted to return (Object) new ChildA() because the erasure of the unbounded type C is Parent (its leftmost bound). Then, no cast is required because println expects an Object as argument.

On the other hand test.<ChildB>get().toString() fails, because test.<ChildB>get() is casted to ChildB before invoking toString().

Note that an invocation like myPrint(test.<ChildB>get()) will also fail. The cast from the Parent returned by get to type ChildB is done when myPrint is invoked.

public static void myPrint(ChildB child) {
  System.out.println(child);
}

这篇关于Java类中的懒惰类?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆