黑马程序员技术交流社区

标题: 关于instanceof和向下转型的一些问题? [打印本页]

作者: Leo_yeung    时间: 2013-10-10 17:41
标题: 关于instanceof和向下转型的一些问题?
本帖最后由 Leo_yeung 于 2013-10-15 00:33 编辑

使用父类的引用类型指向子类的对象,是多态的一种表现。
  1. Fu f=new Zi();
复制代码
但是如果要调用子类中特有的方法时,就要使用到向下转型
  1. Zi z=(Zi)f;
复制代码
因为子类的类型可能会不确定,所以在向下转型前,要先进行判断要转的引用是不是子类的实例
  1. if(f instanceof Zi){
  2.         Zi z=(Zi)f;
  3. }
复制代码
但是,问题出现了,if判断后只有一句代码,就是向下转型,但是去掉if后的大括号编译就报错了,为什么?

作者: long362144768    时间: 2013-10-10 19:19
本帖最后由 long362144768 于 2013-10-10 19:37 编辑

这个主要是涉及引用问题,可能你的引用出现了偏差,类型转换向下转型的要求是,所转目标对象的类必须是引用对象的父类或者本身。其他类不可以package xuexi.sevenday;
public class instensof {
public static void main(String[] args) {
  new instensof().call();
}
public void call(){
  base b = new base();
  b.speak();
  base b1 = new child();
  b1.speak();
  this.callchild(b);
  this.callchild(b1);
}

public void callchild(Object obj){
  base b2 = (base)obj;
  b2.speak();
  if(obj instanceof base){
   base b3 = (base) obj;
   b3.speak();
  }
  if(obj instanceof child){
   base b4 = (child)obj;
   b4.speak();
  }
}
}
class base{
public void speak(){
  System.out.println("base class");
}
}
class child extends base{
public void speak(){
  System.out.println("child class");
}
}
打印结果是
base class//b引用的是父类对象实例
child class//b1引用的是子类对象实例
base class
base class
child class
child class
child class
就会抛出异常
Exception in thread "main" java.lang.ClassCastException: xuexi.sevenday.base cannot be cast to xuexi.sevenday.child
        at xuexi.sevenday.instensof.call(instensof.java:11)
        at xuexi.sevenday.instensof.main(instensof.java:6)
说明你的引用有问题,你的父类引用应该是引用了父类实例,在类型转换时强行转换为子类的实例,编译无法通过的,如果父类引用引用了子类实例,在类型转换时那么可以转换,代码说明 了一切

作者: Leo_yeung    时间: 2013-10-10 21:03
long362144768 发表于 2013-10-10 19:19
这个主要是涉及引用问题,可能你的引用出现了偏差,类型转换向下转型的要求是,所转目标对象的类必须是引用 ...

你是没明白我的问题啊,多态是没问题的,必须是父类的引用指向子类对象啊。我的意思是在使用instanceof进行判断时,如果if语句后的执行语句只有一句时,不是可以省略大括号吗?为什么if语句的大括号省略后就会报错啊,问题在这!!!不解?
作者: long362144768    时间: 2013-10-10 21:15
你可以这样解决
  1. base b3;
  2.                 if(obj instanceof base)
  3.                         b3 = (base) obj;
复制代码
能够解决问题,我想可能是这样定义很容易引起在代码后面再次使用这个变量名时,结果会抛出空指针异常吧,因为你的if语句块标示“{ }”不存在了,可能编译器想表达的意思是你有可能在后面使用这个引用变量,但是这个类变量的生命周期在那句代码结束后就无效了,到时候你检查都很难,
作者: Leo_yeung    时间: 2013-10-12 00:02
long362144768 发表于 2013-10-10 21:15
你可以这样解决能够解决问题,我想可能是这样定义很容易引起在代码后面再次使用这个变量名时,结果会抛出空 ...

这样理解好像也不对啊,就是加上大括号,if判断中定义的变量也是会随着大括号的结束而结束的啊。生命周期还是一样啊。可能是在if判断中定义了一个变量而没有使用的缘故,还是有些不解啊?
作者: long362144768    时间: 2013-10-12 09:46
这样你检查是不是很方便了啊,否则不容易检查的,这也是一个好习惯

作者: Joney__    时间: 2013-10-14 09:59
if (a instanceof Cat){//先判断,a引用型变量是不是指向Cat类  这个类型这样就不会异常
Cat c=(Cat) a;
c.eat();
c .catchMouse();
}else if (a instanceof Dog){
Dog d=(Dog) a;
d.eat();
  d.guard();
        }




这是我学多态时视频上的例子,加括号的原因很简单,如果你不加只能执行If最近的一条,这你肯定知道,加了括号是因为在括号里的代码可能是多条,个人这么理解,希望对你有帮助
作者: 潘才新    时间: 2013-10-14 11:33
a instanceof Cat的instanceof 是比较运算符。
if(a 比较运算符 b){}为什么要把括号去掉呢?

判断的是父类的的引用是不是指向子类的引用
作者: Leo_yeung    时间: 2013-10-15 00:31
潘才新 发表于 2013-10-14 11:33
a instanceof Cat的instanceof 是比较运算符。
if(a 比较运算符 b){}为什么要把括号去掉呢?

if后只有一句代码,就可以省略大括号啊,这个有疑问吗?
这个跟比较运算符有关系吗?if判断中的结果就两个,true和false!




欢迎光临 黑马程序员技术交流社区 (http://bbs.itheima.com/) 黑马程序员IT技术论坛 X3.2