Java如何选择重载函数来调用? [英] How does Java pick which overloaded function to call?

查看:172
本文介绍了Java如何选择重载函数来调用?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述


$ b 给出三个简单的类:

  class Base {
}

class Sub extends Base {
}

class SubSub extends Sub {
}

另外还有一个函数用于处理这些类:

  public static void doSomething(Base b){
System.out.println(BASE CALLED);
}
public static void doSomething(Sub b){
System.out.println(SUB CALLED);
}

看来代码如下:

  SubSub ss = new SubSub(); 
doSomething(ss);

可以合法地打印BASE CALLED或SUB CALLED,因为SubSub可以转换为那些。实际上,删除函数的Sub版本会导致BASE CALLED被打印。实际发生的是打印SUB CALLED。这似乎意味着调用哪个函数并不取决于定义函数的顺序,因为首先调用Base版本。

Java是否只查看函数的所有不同版本并选择需要最小遍历继承堆栈的版本?这是标准化的吗?它是否写在任何文档中?

解决方案

正式的规范可以在 Java语言规范(JLS)的第15.12.2.5部分。由于泛型,这是非常复杂的,所以你可能想看看 JLS第一版的相同部分

基本上说,编译器试图找到一个版本的方法,其中所有参数包括方法被调用的对象是最具体的。如果不存在这样的方法(例如,因为您有方法(Base,Sub)方法(Sub,Base)但而不是方法(Sub,Sub)),那么编译失败。



注意,方法的实际选择取决于关于目标对象的动态类型的实例方法,而不是参数。您的示例在实例级别仍然可以使用。



您应该能够通过强制转换或重新声明 SS 。如果变量的声明类型与一个签名完全匹配,那么编译器和维护程序员也都清楚了。只要声明的类型匹配,您是否可以指定更具体的类型并不重要。


This is a purely theoretical question.

Given three simple classes:

class Base {
}

class Sub extends Base {
}    

class SubSub extends Sub {
}

And a function meant to operate on these classes:

public static void doSomething(Base b) {
  System.out.println("BASE CALLED");
}
public static void doSomething(Sub b) {
  System.out.println("SUB CALLED");
}

It seems that the followign code:

SubSub ss = new SubSub();
doSomething(ss);

could legitimately result in printing either BASE CALLED, or SUB CALLED, since SubSub can be casted to both of those. In fact, removing the Sub version of the function causes BASE CALLED to be printed. What actually happens is that "SUB CALLED" is printed. This seems to mean that which function is called doesn't depend on the order the functions are defined in, as the Base version was called first.

Does Java just look at all the different versions of the function and pick the one which requires the smallest traversal up the inheritance stack? Is this standardized? Is it written out in any documentation?

解决方案

The formal specification can be found in part 15.12.2.5 of the Java Language Specification (JLS). Thanks to generics this is pretty complicated, so you might want to look at same section of the first edition of the JLS.

It basically says that the compiler tries to find a version of the method where all parameters including the object the method is called upon are most specific. If no such method exists (e.g. since you have method(Base, Sub) and method(Sub, Base) but not method(Sub, Sub)), then the compilation fails.

Note that the actual choice of method depends on the dynamic type of the target object for instance methods, but not for the parameters. Your example would still work the same on the instance level.

You should be able to give the compiler a helping hand by casting or redeclaring the type of ss. If the declared type of the variable matches a signature exactly then everything is clear for the compiler and maintenance programmers as well. It doesn't matter if you then assign a more specific type as long as the declared type matches.

这篇关于Java如何选择重载函数来调用?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆