语句 m(new Student());将对象new Student()赋值给一个Object类型的参数。这条语句等价于
Object o = new Student();
m(o);
由于Student的实例自动地就是Object的实例,所以,语句Object o = new Student()是合法的,它称为隐式转换。
假设想使用下面的语句把对象引用o赋值给Student类型的变量:
Student b = o;
在这种情况下,将会发生编译错误。为什么语句Object o = new Student()可以运行,而语句Student b = o不行呢?原因是Student对象总是Object的实例,但是,Object对象不一定是Student的实例。即使可以看到o实际上是一个Student的对象,但是编译器还没有聪明到懂得这一点。为了告诉编译器o就是一个Student对象,就要使用显式转换。它的语法与基本类型转换的语法很类似,用圆括弧把目标对象的类型括住,然后放到要转换的对象前面,如下所示:
Student b = (Student)o;
总是可以将一个子类的实例转换为一个父类的变量,因为子类的实例永远是它的父类的实例。当把一个父类的实例转换为它的子类变量时,必须使用转换记号“(子类名)”进行显式转换,向编译器表明你的意图。为使转换成功,必须确保要转换的对象是子类的一个实例。如果父类对象不是子类的一个实例,就会出现一个运行异常ClassCastException。例如:如果一个对象不是Student的实例,它就不能转换成Student类型的变量。因此,一个好的经验是,在尝试转换之前,确保该对象是另一个对象的实例。这是可以利用运算符instanceof来实现的。考虑下面的代码:
Object myObject = new Circle();
...
if(myObject instanceof Circle) {
System.out.println("The circle diameter is " + ((Circle)myObject).getDiameter());
...
}
你可能会奇怪为什么必须进行类型转换。变量myObject被声明为Object。声明类型决定了在编译时匹配哪个方法。使用myObject.getDiameter()会引起一个编译错误,因为Object类没有getDiameter方法。编译器无法找到和myObject.getDiameter()匹配的方法。所以,有必要将myObject转换成Circle类型,来告诉编译器myObject也是Circle的一个实例。
为什么没有在一开始就把myObject定义为Circle类型呢?为了能够进行通用程序设计,一个好的经验是把变量定义为父类型,这样,它就可以接收任何子类型的值。
提示: 为了更好地理解类型转换,可以认为它们类似于水果、苹果、橘子之间的关系,其中水果类Fruit是苹果类Apple和橘子类Orange的父类。苹果是水果,所以,问题可以将Apple的实例安全地赋值给Fruit变量。但是,水果不一定是苹果,所以,必须进行显式转换才能将Fruit的实例赋值给Apple的变量。
下列程序演示了多态和类型转换。程序创建两个对象(第5~6行),一个圆和一个矩形,然后调用displayObject方法显示它们(第9~10行)。如果对象是一个圆,displayObject方法显示它的面积和周长(第15行),而如果对象是一个长形,这个方法显示它的面积(第21行)。
public class CastingDemo {
public static void main(String[] args) {
Object object1 = new Circle4(1);
Object object2 = new Rectangle1(1,1);
displayObject(object1);
displayObject(object2);
}
public static void displayObject(Object object) {
if(object instanceof Circle4) {
System.out.println("The circle area is " + ((Circle4)object).getArea());
System.out.println("The circle diameter is " + ((Circle4)object).getDiameter());
}
else if (object instanceof Rectangle1) {
System.out.println("The rectangle area is " + ((Retangle1)object).getArea());
}
}
}
输出:
The circle area is 3.141592653589793
The circle diameter is 2.0
The rectangle area is 1.0
displayObject(Object object)方法是一个通用程序设计的例子。它可以通过传入Object的任何实例被调用。
程序使用隐式转换将一个Circle对象赋值给object1并且将一个Rectangle对象赋值给Object2(第3~4行),然后调用displayObject方法显示这些对象的信息(第5~6行)。
在displayObject方法中(第8~16行),如果对象是Circle的一个实例,则用显式转换将这个对象转换为Circle对象。使用getArea和getDiameter方法显示这个圆的面积和直径。
只有源对象是目标类的实例时才能进行类型转换。在执行转换前,程序使用instanceof运算符来确保源对象是否是目标类的实例(第9行)。
由于getArea和getDiameter方法在Object类中是不可用的,所以,有必要显式地转换成Circle类型(第10、11行)和Rectangle类型(第14行)。
分享到:
相关推荐
在Java面向对象编程中,`instanceof`运算符是一个至关重要的概念,特别是在处理类与类之间的关系时。农业信息系统开发中,我们可能需要处理多种类型的对象,如农作物、动物、农机具等,这些对象可能继承自同一基类或...
如果不正确地进行向下转型,如将`Brush`对象转换为`Pencil`,就会导致运行时错误,因为它们是兄弟类,不是父子关系。因此,必须谨慎使用向下转型,并确保对象实际上是目标子类的实例。 正确使用向下转型的关键在于`...
Java instanceof 运算符的使用方法 Java instanceof 运算符是 Java 语言中的一种二元运算符,它用于判断前面的对象是否是...理解 instanceof 运算符的使用方法和注意事项,可以帮助开发者编写更加健壮和高效的代码。
在Java编程中,对象类型转换和`instanceof`运算符是两种重要的概念,尤其是在处理类的继承关系时。本文将详细解析这两个主题,并探讨它们在实际编程中的应用场景。 首先,我们要明白对象和引用的区别。对象是类的一...
8. **对象转换和instanceof运算符** - **对象转换** 可以将父类引用转换为子类引用,但需要注意安全问题,只有父类引用实际指向的是子类对象时,转换才是合法的。 - **instanceof运算符** `instanceof`运算符...
10. **instanceof运算符**:用于检查一个对象是否属于特定类或其子类。例如,`if (obj instanceof String) {...}`检查`obj`是否是字符串。 这个"java运算符小程序"可能包含了上述一些或所有运算符的实例,通过实践...
2. 强制类型转换:例如,使用 instanceof 运算符来检查对象的类型,然后使用强制类型转换将其转换为目标类型 例如: ```java AbstractCar car = new BMWCar(); BMWCar bmwCar = (BMWCar) car; // 强制类型转换 ...
3. 当转换可能失败时,使用 `instanceof` 关键字先检查对象的实际类型,以防止运行时异常。 总之,Java的转型运算符是编程过程中不可或缺的一部分,它们允许我们灵活地在不同数据类型之间操作,并在面向对象编程中...
判断数据类型可以使用typeof和instanceof运算符。typeof运算符用于判断基本数据类型,instanceof运算符用于判断复合数据类型。 算数运算符有五种:加法、减法、乘法、除法和取余。加法运算符可以将字符串进行拼接,...
Java 对象类型转换和多态性 Java 对象类型转换是 Java 编程语言中的一种机制,允许开发者在不同的类之间进行类型转换。这种机制使得开发者可以更方便地使用继承和多态性来编写灵活的代码。 向上转型和向下转型是 ...
6. **instanceof运算符**:判断一个对象是否属于特定的构造函数或类,如`"str" instanceof String`和`s instanceof String`。 7. **字符比较**:在JavaScript中,大写字母的ASCII值小于小写字母,因此`"A"为真。 8...
JVM在执行`INSTANCEOF`指令时,会利用类加载机制和对象头的信息快速进行类型比较。在HotSpot JVM中,对象头包含一个指向元数据的指针,这个元数据包含了类的层次结构信息,使得JVM可以高效地完成类型检查。 需要...
instanceof运算符可以用来判断一个对象是否是某个类的实例,或是其继承的类的实例。 对于阅读笔记部分,理解以下内容是十分重要的: 1. ECMAScript的引用类型主要涉及Object、Boolean、Number和String等类。 2. ...
类型转换是多态的一种表现形式,它允许我们将子类对象转换为父类对象。例如,我们可以将一个`Dog`对象(假设`Dog`是`Animal`的子类)赋值给`Animal`类型的引用,这样就可以通过父类引用调用子类的方法。但需要注意...
本篇文章将详细阐述Java中的赋值运算符、关系运算符以及instanceof运算符。 一、赋值运算符(Assignment Operators) Java提供了11种赋值运算符,其中最常见的是"="。赋值运算符用于将右侧的值赋给左侧的变量。...
instanceof 运算符是二目运算符,左边的操作元是一个对象,右边是一个类。例如,ClsSuper o2 = new ClsSub(); if (o2 instanceof ClsSub) { System.out.println("o2 是 ClsSub 类型"); } 当左边的对象是右边的类或...
复合赋值运算符实际上是算术运算符和赋值运算符的结合。例如,`x += 1`等价于`x = x + 1`。 3. 关系运算符:包括大于(>)、小于(<)、等于(==)、不等于(!=)、大于等于(>=)、小于等于()等。它们用于比较两...