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

 找回密码
 加入黑马

QQ登录

只需一步,快速开始

本帖最后由 郭孟涛 于 2013-2-19 18:31 编辑
  1. class ObjectDemo
  2. {
  3.         public static void main(String[] args)
  4.         {
  5.                 Object ob = new Test(); // 这里用Object声明对象 ,object 作为一个父类为什么出错
  6.                 System.out.println(ob.talk()); // 这里打印为什么报错?上一句 用 Test 声明变量的时候没有错
  7.         }
  8. }
  9. class Test
  10. {
  11.         public int talk(){
  12.                 return 6;
  13.         }
  14. }
复制代码
下面这个示例,新建了一个子类,打印就正确
  1. class ObjectDemo
  2. {
  3.         public static void main(String[] args)
  4.         {
  5.                 Test ob = new Test1(); //
  6.                 System.out.println(ob.talk()); // 这里打印正确
  7.         }
  8. }

  9. class Test
  10. {
  11.         public int talk(){
  12.                 return 6;
  13.         }
  14. }


  15. class Test1  extends Test
  16. {
  17.       
  18. }
复制代码

7 个回复

倒序浏览
因为左边是引用的类型,父类的引用可以指向子类的对象,Object类是所有类的父类,所以可以用Object类型的引用指向Test类型的对象。
但是引用调用对象的方法只能调用这种引用的类型自身就有的方法,因为编译器只知道你的ob是个Object类型的引用,不知道它指向的对象到底具体是什么类型。
如果你确实知道你的ob指向的是个Test类型的对象,那么可以用强制类型转换。把6行改成下面两行:
Test t = (Test) ob;
System.out.println(t.talk());

点评

新建了一个子类,打印就正确。  发表于 2013-2-19 00:18
回复 使用道具 举报
那不叫建了一个子类,那叫声明了一个子类类型的引用,指向了子类的对象。
方法调用时,编译器看的是引用的类型,只能调用那个引用类型本身就带有的方法。
比如有父类Animal和它的子类Dog,Animal类定义了方法bark();,比如是让“喵喵”,Dog覆盖了bark();,改成“汪汪”。
Animal a = new Dog();
Dog d = new Dog();
a.bark();和d.bark();都是调用的Dog覆盖过的bark();,都会“汪汪”。
但是如果Animal没有定义bark();,那a.bark();就会报错,只能d.bark();。
编译看的是左边的引用类型,运行执行的是右边实际上的对象类型的方法。前提是左边的引用类型也有这个方法。
回复 使用道具 举报
你可能是这么认为的:
第一个例子里Object是Test的父类,调用talk方法时打印错误。
第二个例子里Test是Test1的父类,调用talk方法打印就对了。

但其实是不一样的因为Object里没有talk方法,所以在编译的时候就通过不了。(编译看左,运行看右)
而第二个方法相当于你把Test里的talk方法重写了。所以就通过了。

这么说可能更明白吧
你可以把第二个例子里的Test1中的talk方法的返回值变下,就清楚了。
回复 使用道具 举报
张文彬 发表于 2013-2-19 01:16
你可能是这么认为的:
第一个例子里Object是Test的父类,调用talk方法时打印错误。
第二个例子里Test是Test ...

即使Talk()方法不覆写,一样编译通过
  1. class ObjectDemo
  2. {
  3.         public static void main(String[] args)
  4.         {
  5.                 Test ob = new Test1(); //
  6.                 System.out.println(ob.talk()); // 这里打印正确
  7.         }
  8. }

  9. class Test
  10. {
  11.         public int talk(){
  12.                 return 6;
  13.         }
  14. }


  15. class Test1  extends Test
  16. {
  17.       
  18. }
复制代码
回复 使用道具 举报
郭孟涛 发表于 2013-2-19 01:32
即使Talk()方法不覆写,一样编译通过

那是因为你的父类Test里有talk方法啊。

你可以试试Test里没有talk方法。而Test1里有

编译肯定出错。

这跟我说的覆盖是一个意思就是说编译的时候要看左边有没有。然后运行的时候看右边运行
回复 使用道具 举报
王钊 中级黑马 2013-2-19 17:56:52
7#
兄弟,回头重点看继承多态这一块的视频。
Object ob = new Test(); 这是多态,ob是Object的引用,虽然指向子类对象,但只能调用Object所声明的方法。
Object没有声明talk()方法,所以编译就过不去。
例外,Object一共有11个方法,各个经典,建议学一下吧。
回复 使用道具 举报
您需要登录后才可以回帖 登录 | 加入黑马