我正在研究基于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
中的强制转换有效。
答案 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,因为它们不是来自同一类型层次结构。