在转换编译器的上下文中,“承诺”一词是什么意思?

时间:2018-09-19 10:13:21

标签: java casting compilation terminology

摘自一本Java书:

  

在将值存储在变量中时,编译器会检查您是否没有承诺。如果将子类引用分配给超类变量,则将有前途,而编译器将简单地允许您这样做。如果您将超类引用分配给子类变量,您将很有希望。然后,您必须使用强制转换,以便可以在运行时检查承诺

如果您能向我解释技术问题上的“承诺”,我将理解。我查看了字典,但该词不适合本段内容。

1 个答案:

答案 0 :(得分:2)

这不是标准术语,但是作者似乎正在使用它(试图)使初学者可以使用它。 (这并不容易。)基本上,他们是说如果您有:

class Base {
    public void baseMethod() {
        // ...
    }
}
class Derived extends Base {
    public void derivedMethod() {
        // ...
    }
}

您可以这样做:

Base b = new Derived();

...因为Base类型定义的所有功能(baseMethod)在您分配的对象(Derived的实例)上可用。您“承诺”对象b所指的对象将具有baseMethod,并且确实如此。

但是您不能这样做:

Derived d = new Base();

...因为Derived类型定义了您要分配的对象(derivedMethod实例)所不具备的功能(Base)。您“承诺”对象d所指的对象将有derivedMethod,但没有,所以您“承诺太多”。


发表评论:

  

在第二个示例中铸造如何出现?

该示例中未涉及。强制转换不会改变对象的含义,而只是改变您对它的引用。¹

但是假设您有这样的事情:

void someMethod(Base obj) {
    if (obj instanceof Derived) { // Just an example, `instanceof` is usually
                                  // an anti-pattern
        Derived d = (Derived)obj;
        // ...
    }
}

该方法接收一个对象,并且只有一个Base引用。但是随后代码检查并发现该对象实际上是Derived(或Derived的子类),因此它使用强制转换来更改其具有的引用类型,以便可以使用{{ 1}}功能。铸造就是这样进入的。

同样,请注意,在十分之九的情况下,使用Derived是一种反模式。在十分之九的情况下,您想重构代码,以便将接口类型传递给仅定义代码所需功能的代码。第十种情况很少见。 :-)

  

在第二次铸造中铸造是否总是成功?

仅当您确定地确定对象属于您要转换的类型或该类型的子类时,才可以。如果您不确定,则强制转换可能会抛出ClassCastException


¹... ...在将图元(例如instanceof)强制转换为其包装对象(例如int)的特殊情况下,反之亦然。即使这样,它也不会更改对象,它只是创建一个对象(在转换为包装类型时)或创建一个基元(在转换为原始类型时)。