如果您想立即阅读该问题,请跳至最后一句。
假设我们有一个接口和三个类:
interface I{}
class A implements I{}
class B extends A {}
以下声明:
A a = new A();
B b = new B();
现在,有一种经典的转换方式,它允许我将类型A(父类)的引用转换为类型B的对象(子类),如下所示:
a = b; //here a is no longer pointing at object A, and is now pointing at the same object b is pointing at.
b = (B) a; // the casting is now accepted by the compiler and during runtime as well.
这里存在问题所在。每当我看到一行代码都有多个转换时,我就无法读取它(字面意思),因此我无法理解它的含义。
例如,假设我们有这行代码:
a = (B)(I)b;
你怎么读这个? a
是对类型A的对象的引用,并且它被赋予类型B的对象的值(从左侧首先强制转换)。但是等一下,b之前还有另一个演员(I)。那么我们在这里有什么?它是一个被转换为(B)对象的接口吗?或者它是否被投射为界面,也被投射为(B)?
我试图将其分解以避免混淆:
I temp = (I) b;// first line
a = (B) temp;// second line
所以,首先,因为b是I(因为它扩展了实现I的A),所以编译器在运行时接受“第一行”。
“第二行”但是,我们引用了一个对象A被赋予了类型B的值。乍一看,它没有任何问题。但后来我意识到I
不是A也不是B,即使“第二行”中的强制转换可以使编译器认为它是B类的对象,但它不应该在运行时被接受
所以我想回答的主要问题是如何解释以下行:
a = (B)(I)b;
答案 0 :(得分:6)
现实或您不想要的答案
这里真正的问题是粗心的goofball编写了糟糕的代码。 真正的解决方案是;要么不写蹩脚的代码,要么修复代码。
让我们继续作为一个傻瓜或你似乎想要的答案
java中有两种类型的转换;向上和向下铸造。
向上转换是指将类型A的对象转换为接口I的实例;你在铸造" up"继承树。 例如:
A aObject = new A();
I iObject = (I)aObject; // Up casting.
向上转换的好处是编译器能够在编译时确定转换是否合法。
向下转换是指将类型I的对象转换为类型A的对象;你在铸造" down"继承树。 例如:
A aObject;
I iObject = new A();
aObject = (A)iObject;
编译器在编译时不知道向下转换是否成功。 因此,向下转换可能会在运行时抛出异常。
令人困惑的代码:a = (B)(I)b;
是向上投射(安全)和向下投射(不安全)的示例。
作为奖励,铸造绝不是必需的。 将B对象直接分配给A引用总是安全的,因为B类扩展了A类。
解决:"粗心的goofball" 似乎是强大的语言。 它不是强大的语言,它是描述你的情况的最好方法。 事实上,编写这样的代码的人应该被终止(可选地,让你的竞争对手雇佣他们)。
答案 1 :(得分:2)
a = (B)(I)b;
可能会更好地形象化:
a =
// outer CastExpression
(B)(
// with its UnaryExpression being another CastExpression
(I)(b)
);
也就是说,它会将b
转换为I
,然后将其转换为B
,然后将其分配给A
变量。
然而,看起来这些演员表中的任何一个都不是必需的。如果b
是B
的实例,则它也是A
和I
的实例。
答案 2 :(得分:0)
a = (B)(I)b;
将b
投射到I
,然后将其投放到B
。大概是因为你无法直接将b
投射到B
。
现在还没有好的情况可以使用它,因为如果可能的话,应该避免一次性投射。但是,如果你想要像
这样的东西String s = (String) myHashMap;
要编译,你需要upcast以防止编译器禁止明显非法的演员:
String s = (String) (Object) myHashMap;
当然,如果您的myHashMap
不为空,这将导致运行时ClassCastException
,但与之前的示例不同,它将进行编译。
答案 3 :(得分:0)
也许你没有明白,即使施放到I或A,b仍然是B型的对象,它的性质也不会松散。想办法说一下对java的看法'将我的对象视为I'的对象。然后,如果是B型,它也是A型。
因此,指令告诉java使用我的对象,因为它是I类型,并在使用它作为类型B之后立即使用它,通过声明,它也是类型A.因此没有编译或运行时错误。
然后我们可以看到它看起来也大部分都是无用的和丑陋的......