为什么必须将派生类转换为显式而非隐式

时间:2014-12-19 15:23:48

标签: java object casting implicit

Object o = new Student(); // Implicit casting

我非常了解这段代码,而我所理解的是,引用变量“o”是指“Object”类型的数据,我们可以看到Student从“Object”扩展,这意味着它引用了一个实例学生。 如果我写了以下代码:

Object x = o;

这会将o中的值分配给x,这意味着如果我们遵循x的方向,我们将转到上面的学生对象!

我的问题是,为什么我不能写下面的代码? :

Student x = o;

“o”指的是“对象”类型的对象,该对象将其地址(在内存中)分配为“o”,为什么我们不能将保存在o中的值分配给x!

7 个答案:

答案 0 :(得分:5)

这里没有施法。

正如您所说,ObjectStudent的基类 这意味着Student的每个实例也都是Object,我们可以将其视为一个。

Object o = new Student(); // A Student is an Object

然而,相反的关系并不成立 - 并非Object的所有实例都是Student

Student分配给o后,编译器无法获得 Student的信息。
该信息在运行时可用 - 您可以说o instanceof Student,它会 是真的 - 但编译器不知道这一点。

答案 1 :(得分:3)

Object o;

if (Math.random < 0.5) {
  o = new Student();
} else {
  o = new Dog();
}

你显然不能Student x = o;

除非狗也是学生,否则这是一个不同的故事。

答案 2 :(得分:3)

Object o = new Student();  //upcasting - Implicit cast
Student x = (Student) o;   //downcasting -Explicit cast

向上推广:我们正在缩小参考转换(向上移动继承层次结构)。由于学生IS-A对象,它不需要显式转换

向下转型:我们正在扩大引用转换(向下移动继承层次结构)。由于Object可以是任何东西,我们必须使用显式强制转换将其强制转换为Student。

答案 3 :(得分:2)

Java只允许隐式向上转换,而不是隐式向下转换。

Java中的向上转换也称为扩展转换,而向下转换称为缩小转换。

可以隐式或显式地将对象强制转换为超类型。在此示例中,ObjectStudent的超类型。

Object o = new Student();
Object x = o; // implicit works
Object x = (Object) o; // explicit works

无法将对象隐式强制转换为子类型,并且必须显式转换。在此示例中,StudentObject的子类型。

Object o = new Student();
// Student x = o; // implicit doesn't work
Student x = (Student) o; // explicit works

Explicit and Implicit Type Casting - Herong Yang

5.1.5. Widening Reference Conversion - Java docs

5.1.6. Narrowing Reference Conversion - Java docs

答案 4 :(得分:1)

您需要明确地将其转换为学生

Student x = (Student) o;

之所以这样,是因为编译器不知道这是否正确,所以你需要将其转换为&#34;我相信这会有效。请相信我&#34;

答案 5 :(得分:1)

您可以将Student实例分配给声明为Object类型的变量,因为每个Student都是Object的一种(或特化)。由于并非每个对象都是学生,因此编译器会将其知道的事物分配给对象的任何特化,例如Student。因此,您可以毫无困难地隐式地分配一个更通用类型的实例变量,但是在相反的方向上,编译器需要保证您的意思是这样做,因此您明确地向下转换。

Student x = (Student)o;

这只是静态类型语言的本质。

答案 6 :(得分:1)

你基本上必须看看它是否通过IS-A测试,你可以说Student IS-A Object(因为Java中的每个类都是Object类的子类),这就是第一个隐式转换工作的原因。 / p>

但是你不能说Object IS-A Student,因为它可能不是。除非您知道它将是Student,否则您可以使用以下方式进行 downcast

Student x = (Student) o;

如果您在 downcast 中犯了错误,您可能希望将其包装在if语句中,如下所示:

if(o instanceof Student) {
    Student x = (Student) o;
}