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

 找回密码
 加入黑马

QQ登录

只需一步,快速开始

© 小黑马 黑马帝   /  2012-8-31 13:34  /  2696 人查看  /  6 人回复  /   0 人收藏 转载请遵从CC协议 禁止商业使用本文

本帖最后由 马小龙 于 2012-8-31 15:45 编辑

复习以前内容,在覆写这个知识点的返回值问题上产生疑问,
写了一个demo:



  1.     class Base {  
  2.       public Base newInstance() {  
  3.         return new Base();  
  4.       }  
  5.       public Base newInstance2() {  
  6.         return new Base();  
  7.       }  
  8.     }  
  9.     class Test extends Base {  
  10.       // 返回值不同  
  11.       public Test newInstance() {  
  12.         return new Test();  
  13.       }  
  14.       // 返回值相同  
  15.       public Base newInstance2() {  
  16.         return new Test();  
  17.       }  
  18.     }  
复制代码
发现如果用jdk1.4以前的版本编译会报错, 但是换成用jdk1.5以后的版本后就会编译成功,为什么?

评分

参与人数 1技术分 +1 收起 理由
张立江 + 1 这个问题我也一直没注意过。。.

查看全部评分

6 个回复

倒序浏览
版本不一样,照理说不应该报错的,返回值不一样,相当于创建了一个新的方法,不叫覆盖,编译器出问题了吧
回复 使用道具 举报
5.0版本之后支持 重写的的返回值为不同类型,但这个类型必须是所复写方法类型的子类。

以前上网时看到过关于这个的讨论,里面提到5.0新特性可以让重写的方法返回不同类型,
我自己试过几次都没成功,后来发现只有返回是子类类型才可以,其他类型的话都不行。

点评

向你向你学习!细节决定成败!  发表于 2012-8-31 15:38

评分

参与人数 1黑马币 +20 收起 理由
小黑马 + 20 赞一个!

查看全部评分

回复 使用道具 举报
尤洋 发表于 2012-8-31 14:53
5.0版本之后支持 重写的的返回值为不同类型,但这个类型必须是所复写方法类型的子类。

以前上网时看到过关 ...

就是说也是属于覆盖范畴, 运行时新建子类对象的话,调用就是调用子类方法.
回复 使用道具 举报
本帖最后由 尤洋 于 2012-8-31 15:44 编辑
马小龙 发表于 2012-8-31 15:16
就是说也是属于覆盖范畴, 运行时新建子类对象的话,调用就是调用子类方法. ...


属于覆盖,而不是新建了一个方法
验证方法很简单,改下代码试试就知道了
  1. public class YanZheng{

  2.         /**
  3.          * @param args
  4.          */
  5.         public static void main(String[] args) {
  6.                 // TODO Auto-generated method stub
  7.                 Test t=new Test();//初始化会输出fffffffff
  8.                 t.newInstance();//调用newInstance()方法,子类中具有父类的方法,如果不是复写的话,两个方法同名就会分不清到底该调用哪个newInstance()方法。
  9.         }
  10. }

  11. class Base {
  12.         
  13.   public Base newInstance() {  
  14.     return new Base();  
  15.   }  
  16.   public Base newInstance2() {  
  17.     return new Base();  
  18.   }  
  19. }  
  20. class Test extends Base {
  21.         Test()
  22.         {
  23.                 System.out.println("fffffffff");
  24.         }
  25.   // 返回值不同  
  26.   public Test newInstance() {  
  27.     return new Test();  
  28.   }  
  29.   // 返回值相同  
  30.   public Base newInstance2() {  
  31.     return new Test();  
  32.   }  
  33. }  
复制代码
回复 使用道具 举报
我用反射试了一下,好像没有复写哦,只是调用不了了

import java.lang.reflect.Method;

class Base {  

  public Base newInstance() {  

    return new Base();  

  }  

  public Base newInstance2() {  

    return new Base();  

  }  
  
}  

class Test extends Base {  

  // 返回值不同  

public Test newInstance() {  

    return new Test();  

  }  

  // 返回值相同  

  public Base newInstance2() {  

    return new Test();  

  }  
  public static void main(String [] args)
  {
          Test t = new Test();
          Class clazz = t.getClass();
          Method [] me = clazz.getMethods();
          for(Method m:me)
          {
                  System.out.println(m.getName());
          }
  System.out.println(t.newInstance().getClass());
  }
  }
回复 使用道具 举报
尤洋 中级黑马 2012-8-31 16:58:38
7#
本帖最后由 尤洋 于 2012-8-31 17:22 编辑
黑马张涛 发表于 2012-8-31 15:58
我用反射试了一下,好像没有复写哦,只是调用不了了

import java.lang.reflect.Method;

你用反射得出两个相同方法名 并不能说明 父类方法没被复写。
只是由于返回值类型不同,复写前后的方法被getMethods()方法 判断为两个不同的Method对象。这两个对象再调用getName()方法得出两个函数名
而返回值类型相同时,复写前后的方法会被getMethods()认为是同一个Method对象。最后只有一个Method对象调用getName()方法得出一个函数名。

你的代码只能验证复写前后的两个方法 返回值 函数名 和参数列表是否相同,而不能说明是否被复写
回复 使用道具 举报
您需要登录后才可以回帖 登录 | 加入黑马