使用重载vs重写,编译时间与运行时间

时间:2013-04-06 02:29:00

标签: java overloading

有效:在编译时选择要调用的重载。 例如:

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。 并且行为也与方法重载方法相同。

因此,在任何一种情况下,调用哪个重载方法的决定是在运行时而不是编译时(它总是'秒'调用的'getdouble')。

因此,“有效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));
...

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

2 个答案:

答案 0 :(得分:2)

声明的s类型是parentsecond所以当编译器运行代码时,它将分配以parentsecond作为参数的方法

public static void calloverload(parentsecond s)...

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

引用this answer:

JLS声明§8.4.9重载:

  1. 调用方法时(第15.12节),在编译时使用实际参数的数量(以及任何显式类型参数)和参数的编译时类型来确定方法的签名。被调用(§15.12.2)。
  2. 如果要调用的方法是实例方法,则将在运行时使用动态方法查找(第15.12.4节)确定要调用的实际方法。
  3. 参数为getdouble,其编译时类型为s。其运行时类型为parentsecond

    编辑要回答问题的补充,请参阅上面的第1点。没有什么需要在运行时进行评估。编译器在两次调用中都使用编译时类型second

答案 1 :(得分:0)

关键不在于编译器无法弄明白;重点是程序员过载会让人感到困惑,因此可能会导致错误。

如果您需要提取JLS以确定哪种方法与您调用它的方式最具体匹配,那么每个查看该代码的维护程序员都必须进行相同的练习。

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

“在编译时解决重载”的特定危险就是这个。假设我有:

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

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

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

对于程序员来说,这是非常不直观的(因此令人困惑,因此也是错误的来源)。

相关问题