-1

有效:在编译时选择调用哪个重载。例子:

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)。

所以在“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));
...

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

4

2 回答 2

2

声明的类型sparentsecond这样的,当编译器运行代码时,它将分配parentsecond作为参数的方法

public static void calloverload(parentsecond s)...

但是,覆盖是一个不同的主题。实例的实际类型ssecondsosecondgetdouble方法将被执行。这是一个多态的例子。在java中,多态是通过后期绑定来实现的。

引用这个答案:

JLS 在 §8.4.9 重载中声明:

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

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

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

于 2013-04-06T02:42:34.647 回答
0

关键不是编译器无法弄清楚;关键是重载会让程序员感到困惑,因此很可能会导致错误。

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

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

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

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

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

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

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

于 2013-04-06T02:38:14.557 回答