A股上市公司传智教育(股票代码 003032)旗下技术交流社区北京昌平校区

 找回密码
 加入黑马

QQ登录

只需一步,快速开始

© 王德升 中级黑马   /  2012-5-10 17:31  /  2264 人查看  /  9 人回复  /   0 人收藏 转载请遵从CC协议 禁止商业使用本文

本帖最后由 王德升 于 2012-6-3 23:15 编辑

class Animal{
public String name;
Animal(String name){
  this.name=name;
}
}

class Cat extends Animal{
public String eyesColor;
Cat(String n,String s){
  super(n);
  eyesColor=s;
}

}

class Dog1 extends Animal{
public String furColor;
Dog1(String n,String s){
  super(n);
  furColor=s;
}
}
public class TestAnimal {
public static void main(String args[]){
  Animal a=new Animal("name");
  a=new Dog1("bigyellow","yellow");
  System.out.print(a.furColor);
  System.out.print(a instanceof Dog1);
}
}
我不懂,为什么在这里a是Dog1类型的。
但是却不能调用furColor呢,?  

评分

参与人数 1技术分 +1 收起 理由
攻城狮 + 1 赞一个!

查看全部评分

9 个回复

倒序浏览
你错了,从你的代码来看,a并不是Dog1类型而是Animal类型,这里涉及到java的多态性和动态绑定原理。1
不要认为你这样写了 Animal a=new Animal("name");
  a=new Dog1("bigyellow","yellow");
就是Dog1类型。你要a的前面。
回复 使用道具 举报
你错了,从你的代码来看,a并不是Dog1类型而是Animal类型,这里涉及到java的多态性和动态绑定原理。
不要认为你这样写了 Animal a=new Animal("name");
  a=new Dog1("bigyellow","yellow");
就认为是Dog1类型。你要a的前面。
回复 使用道具 举报
因为a被申明为父类Animal的对象的引用,而Dog1继承了Animal类,这就是父类的引用指向了子类对象,也就是java中的多态。但是多态的访问是有前提的,通过父类的引用指向子类对象来访问子类从父类所继承过来的方法(非静态成员方法的重写),这样的访问方式不能访问子类所特有的成员。正如楼主提供的代码一样,furColor只在子类Dog1里面申明,而父类Animal没有声明,furColor是子类Dog1特有的,所以不能调用。就算在父类Animal中声明了furColor,a访问的还是自己的furColor,也不是Dog1里面的furColor。
回复 使用道具 举报
本帖最后由 杨威 于 2012-5-10 18:33 编辑

这是多态的原则问题,问题原因标示在代码中
  1. public class TestAnimal
  2. {
  3.         /*public static void main(String args[])
  4.         {
  5.                 Animal a=new Animal("name");//你这里创建了父类的对象a
  6.                 a=new Dog1("bigyellow","yellow");//你这语句是想将父类对象子类类型,这是不行的。必然是错误
  7.                 System.out.print(a.furColor);
  8.                 System.out.print(a instanceof Dog1);
  9.         }
复制代码
多态一直都是针对子类对象在做变化,我们能转换的是父类的引用指向自己的子类对象,该引用可以被提升,也可以被强制转换(即向下转型)。
回复 使用道具 举报
Animal a=new Animal("name");
  a=new Dog1("bigyellow","yellow");
多态呀。a在new Dog1以后,他的引用数据类型仍然是Animal
就好像,父亲是农民,儿子是音乐家,父亲没有演奏功能
儿子可以穿上父亲的衣服帽子冒充父亲去田里干活,是因为儿子继承了父亲种田的功能
但是儿子不能仍然这身装扮冒充父亲去舞台演奏把,因为父亲没干过这事
如果儿子要上台演奏,就必须换了衣服。也就是类型转换
回复 使用道具 举报
本帖最后由 小小企鹅 于 2012-10-27 22:34 编辑

a会被当作Animal这个类的实例,编译器无法将此对象识别为Animal以外的事物
如果想要调用Dog1特有的方法,就必须将类型声明为Dog1。
public class TestAnimal {
public static void main(String args[]){
        Animal a = new Animal("name");
        a= new Dog1("bigyellow","yellow");
        System.out.print(((Dog1)a).furColor);  //将类型转换成Dog1
        System.out.print(a instanceof Dog1);
}
}
回复 使用道具 举报
坐等答案
回复 使用道具 举报
李啸 中级黑马 2012-5-10 20:10:08
9#
首先给你解释下Java面向对象值多态的一种通俗的说法:一种方法多种实现换句话说父类的某个方法被多个子类重写那么就可以定义父类的引用指向之类的实例来调用被重写过的方法也叫向上转型
public class TestAnimal {
public static void main(String args[]){
   Animal a=new Animal("name");//你这里的a首先指向了父类的实例
   a=new Dog1("bigyellow","yellow");//这时候因为你Dog1类是继承了父类所以把子类的实例付给了a近一步实现了父类引用指向了子类的实例
   System.out.print(a.furColor);//这时候a指的就是Dog1类中furColor属性
   System.out.print(a instanceof Dog1);//这里会输出true因为a是Dog1的对象
}
}
回复 使用道具 举报
哥们,我想你还没明白多态到底是怎么回事。
这个的furCorlor是子类中的属性。那么你既然是用Animal定义a的。
Animal a=new Animal("name");
这样,编译器就会认为a是Animal类的。
虽然它其实是已经又被指向Dog1了,但是这就像是在一个子类的变量的外面打了一层叫做Animal包装,去骗过编译器,当然Animal里面实际上没有furCorlor这个子类的属性,这样就拿不到属性,在my eclipse里面是点不出furCorlor的。如果你去验证,输出a的地址,JVM运行的时候会自动拆分的。
这就是为什么输出的时候会是子类的对象地址。
System.out.print(a);//输出a的地址
输出为:Dog1@150bd4d
显然这时a实际上已经指向Dog1了~但是表面上它仍然是Animal
至于怎么解决这个问题~最简单的方法就是强制转换一下
System.out.print(((Dog1)a).furColor);  
这样就解决了~
回复 使用道具 举报
您需要登录后才可以回帖 登录 | 加入黑马