Java Object Cast如何在场景后工作?

pet*_*ter 40 java polymorphism casting

可能重复:
Java强制转换操作符如何工作?
Java强制实现

我总是想知道如何使用Java进行对象转换.我理解原始类型它会更像二进制表示级别,但是对象呢?有点像Polymorphism或者dynamic binding在某种程度上会在运行时确定一切吗?例如:

class Parent{
     void A(){}
}
class Child extends Parent{
     @Override
     void A(){}
}

Parent p = new Parent();
Child c = (Child) p;
Run Code Online (Sandbox Code Playgroud)

这是如何在幕后工作的?它是否创建了一个新实例Child?而且,如果你试图施放会发生什么:

Child b = (Child) new Object();
Run Code Online (Sandbox Code Playgroud)

最后一个,在将一个原语转换为包装类时:

Double d = (Double) 3.3;
Run Code Online (Sandbox Code Playgroud)

我知道你没有必要施展它,但如果你这样做呢?在后端发生了什么重大事件?

ast*_*eri 17

当您使用显式转换时,系统中不会创建新对象(在您的最后一种情况下,您将基本类型转换为对象包装器,因为double它不是像Doubleis 的对象).请注意,由于Java的自动装箱功能,因此不需要此显式强制转换.

在您的(Child) new Object()场景中,您将收到ClassCastException,因为a Object不是a Child(尽管相反的情况属实).

第一个场景的答案是最复杂的.基本上,父类被视为接口可能是.当你施放的ChildParent,只有ParentAPI是可用的.但是,仍将调用重写的方法.所以,如果你这样做:

Parent p = (Parent) new Child();
p.a();
Run Code Online (Sandbox Code Playgroud)

...的Childpublic void a()将被调用,即使它正在通过的镜片观察Parent类.但是,如果你有在第二个方法Child是,Parent没有(假设public void b()为实例),你会不会能够调用,如果没有铸造对象回Child.

正如您所说,"在幕后",创建的唯一新事物是指向同一对象的另一个对象引用.您可以根据需要为同一个单一对象提供尽可能多的引用.考虑这个例子:

Parent p = new Parent();
Parent p1 = p;
Parent p2 = p;
Parent p3 = p2;
Run Code Online (Sandbox Code Playgroud)

在这里,有四个引用(p,p1,p2p3),每个指向你所创建的同一对象new Parent()的声明.

不过,我可能会在哲学观点上争辩说,这种新引用的创建实际上是明确的,而不是在你说的时候Parent p = something.

链接:


Bev*_*ynQ 10

对你的主要问题的简单答案是否定的.所有演员都在语法检查时发生.

转换会影响语法检查器查看对象的方式,它不会影响对象本身,而Child转换为Parent,仍然是Child.

但是,仅在运行时检查演员表.这就是为什么它是危险的,除非没有别的办法,否则不应该使用它.

  • 我认为您的答案是最短且非常清楚的,除此之外,我还想标记一些有用的东西:如果您想在投射对象时避免危险情况 (CastClassException),则可以始终使用 if(object) 检查CastObjectClass 的实例) (2认同)

Osc*_*Ryz 5

对此:checkcast,其作用是验证引用是否可分配。如果是,则不更改堆栈,并保留对该引用的操作。

因此,如果您有:

 Child c = ( Child )  anyObject; 
 c.sayHi();
Run Code Online (Sandbox Code Playgroud)

如果强制转换成功,则sayHi 可以调用该方法:

如果可以将objectref强制转换为解析的类,数组或接口类型,则操作数堆栈不变;否则,checkcast指令将引发ClassCastException。

这是“字节码”

$ cat CastDemo.java 
class Parent {}
class Child extends Parent {}
class Main {
    Child c = (Child) new Parent();
}
$ javap -c Main
Compiled from "CastDemo.java"
class Main {
  Child c;

  Main();
    Code:
       0: aload_0       
       1: invokespecial #1                  // Method java/lang/Object."<init>":()V
       4: aload_0       
       5: new           #2                  // class Parent
       8: dup           
       9: invokespecial #3                  // Method Parent."<init>":()V
      12: checkcast     #4                  // class Child
      15: putfield      #5                  // Field c:LChild;
      18: return        
}
Run Code Online (Sandbox Code Playgroud)


Mar*_*nik 4

首先,要非常小心,不要将转换转换混淆。它们可能共享表面语法,但过程却截然不同。

在Java中,您可以将对象向下转换为任何类型,但在运行时,ClassCastException如果该对象实际上与目标类型不兼容,您将得到一个。这发生在字节码级别:有一条专门用于向下转换的字节码指令。

Child c = (Child) new Object();
Run Code Online (Sandbox Code Playgroud)

将无条件地导致ClassCastException.

Double d = 3.3; // note: no explicit casting needed
Run Code Online (Sandbox Code Playgroud)

将在 的实例中执行自动装箱Double。所以这里,实际上创建了一个新的实例。

正常、成功的 dowcast 可能如下所示:

Object o = "a";
String s = (String)o;
Run Code Online (Sandbox Code Playgroud)

这里,没有创建任何对象:只有 的值o被复制到 中s。该值是一个参考值。