2013-04-06 87 views
-1

生效:选择哪个重载调用是在编译时进行的。 实施例:使用重载vs覆盖,编译时间vs运行时间

class parentsecond{ 
    public int getdouble(int x){ return x*2;} 
} 
class second extends parentsecond{ 
    public int getdouble(int x){ return x*3;} 
} 
class third{ 
    public static void calloverload(parentsecond s){ 
     System.out.println(s.getdouble(4)); 
    } 
    public static void calloverload(second s){ 
     System.out.println(s.getdouble(4)); 
    } 

    public static void main(String[] args){ 
     third t=new third(); 
     parentsecond s=new second(); 
     t.calloverload(s); 
    } 

} 

回答是12. 并且行为为实例方法重载的方法相同的太。因此,在任何一种情况下,调用哪个重载方法的决定都是在运行时而不是编译时(它总是被调用的'second''getdouble)进行的。

因此,对于'Effective Java'中的这个特定项目有一些限制,我没有得到。

请帮助澄清'在编译时解决超载'的含义。

如何从这个上面不同:

.... 

    class fourth{ 

      public static String getCollection(Set<?> s){ 
       return "Set"; 
      } 
      public static String getCollection(Collection<?> c){ 
       return "Collection"; 
      } 

      public String getiCollection(Set<?> s){ 
       return "Set"; 
      } 
      public String getiCollection(Collection<?> c){ 
       return "Collection"; 
      }  

      public static void main(String[] args){ 

       Collection<String> c=new HashSet<String>(); 
       System.out.println(fourth.getCollection(c)); 
       fourth f=new fourth(); 
       System.out.println(f.getiCollection(c)); 
... 

这个答案在这种情况下,始终是“收集”,而不是实际的运行时类型。

+3

你能澄清你的问题吗? – 2013-04-06 02:32:09

+3

问题是什么? – Buddha 2013-04-06 02:32:54

+0

重新说明了问题,使其更清晰 – IUnknown 2013-04-06 02:37:24

回答

2

声明类型的sparentsecond所以当编译器通过代码运行时,它将分配该取parentsecond作为参数

public static void calloverload(parentsecond s)... 

然而,首要的是一个不同的主题的方法。实例s的实际类型为second,因此将执行secondgetdouble方法。这是一个多态的例子。在java中,多态性是通过late-binding完成的。

要从this answer:

引述JLS状态在§8.4.9超载:

  1. 当一个方法被调用(§15。12)中,实际参数(以及任何显式类型参数)的数量和参数的编译时类型在编译时用于确定将被调用的方法的签名(第15.12.2节)。
  2. 如果要调用的方法是实例方法,则将在运行时使用动态方法查找(第15.12.4节)确定要调用的实际方法。

参数是s,其编译时间类型是parentsecond。它的运行时间类型是second

编辑要回答您的问题,请参阅上面的第1点。在运行时不需要评估任何内容。编译器在两次调用中都使用编译时类型Collection

+0

现在有了完美的意义。当我打印出哪个重载的'calloverload'版本被调用时 - 它确实是接受父对象的ne。然后在传入类的运行时版本上调用getdouble。 – IUnknown 2013-04-06 03:22:28

+0

@IUnknown我很高兴这有帮助。你应该听听_Russell_下面说的。重载方法时,尽量不要使用子类型。 – 2013-04-06 03:23:21

0

重点不在于编译器无法搞清楚;问题在于超载对程序员来说是令人困惑的,因此可能会导致错误。

如果您需要抽出JLS来确定哪种方法与您调用方式最匹配,那么每个查看该代码的维护程序员都必须经历相同的练习。

因此,建议重载应该有不同数量的参数,或至少不可互换的参数类型。

“解决编译时重载”的具体危险是这样的。假设我有:

void method(List a) { } 
void method(Collection a) { } 

然后,这两个调用会做不同的事情:

List list = new ArrayList(); 
method(list); 
method((Collection)list); 

这是非常直观的程序员(因此混乱,因而是错误的来源)。

+0

编辑该问题以进一步澄清。 – IUnknown 2013-04-06 03:10:16