对象转换和instanceof运算符

语句 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行)。  

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值