Java SDK10:是否明确要求强制转换?

时间:2018-11-28 08:21:18

标签: java

我正在研究基于JDK 8的Java书籍。在关于继承和泛化的章节中,显示了以下示例:

class A {}
class B extends A {}
class C1 extends B { public void x1() {System.out.println("C1.x1");} }
class C2 extends B { public void x2() {System.out.println("C2.x2");} }

然后,声明了一些对象变量,它们的类型均为A

A obj1, obj2, obj3, obj4;

这些变量填充有四个类的实例:

obj1 = new A();
obj2 = new B();
obj3 = new C1();
obj4 = new C2();

现在,obj3.x1()不起作用,因为obj3的类型为A,并且x1()中没有定义A。在这本书中,现在可以声明类型为obj5的新变量C1并为其分配值obj3

C1 obj5 = obj3; // then obj5.x1() should work

但是在此行上,我遇到Incompatible Types编译错误。

SDK8和10之间有区别吗?还是我在某个地方错过了一些错误?

请注意:C1 obj5 = (C1) obj3中的强制转换有效。

4 个答案:

答案 0 :(得分:5)

通过强制转换,您告诉编译器您认为分配是可以的,因为您认为obj3的类型为C1。然后编译器相信您并继续。

如果对此撒谎,则会出现运行时异常。如果没有,一切都很好。

答案 1 :(得分:2)

您确实需要进行强制转换,因此Java 8和Java 10之间没有区别。如果为类赋予有意义的名称,这将更容易理解。假设A =动物,B =哺乳动物,C1 =狗,C2 =猫:

class Animal {}
class Mammal extends Animal {}
class Dog extends Mammal { public void x1() {System.out.println("Woof");}
class Cat extends Mammal { public void x2() {System.out.println("Meow");}

Animal obj1, obj2, obj3, obj4;

obj1 = new Animal();
obj2 = new Mammal();
obj3 = new Dog();
obj4 = new Cat();

当您尝试执行此作业时:

Dog obj5 = obj3;  // obj3 is of type Animal

强制转换是必需的,因为obj3的类型为Animal,但是仅查看此行,编译器就无法确定它实际上是Dog还是其他东西。您必须使用强制转换来告诉编译器“我比你更了解这是什么,所以我希望您将这个Animal视为Dog”。

请注意,仍然会进行运行时检查-如果在运行时发现obj3引用的对象不是Dog,您将得到一个{{1} }。

答案 2 :(得分:1)

您所引用的书中存在错误。这里的Java 8和10没有区别。同样在Java 8中,您需要显式强制转换:

    C1 obj5 = (C1) obj3;
    // then obj5.x1() works:
    obj5.x1();

我相信自Java 1.0以来一直如此。

答案 3 :(得分:1)

看看下面的代码:

A a = new C1(); //reference variable of *A* class points object of *C1* class
C1 c1 = a; //compile time error, requires casting
C1 c1 = (C1) a; // type casting A to C1

在上面的代码中,如果a不是C1类的对象,则将C1类的类型转换对象转换为A类将抛出 ClassCastExcepiton 。如果A和C1类彼此不相关并且不属于同一类型层次结构,则强制类型转换将引发编译时错误,例如您不能转换String和StringBuffer,因为它们不是来自同一类型层次结构。