Java 关于方法重写
对于下面的java代码段,“run”方法出现四次。我对这四次“跑”的关系感到相当困惑。原始代码相当长,我只保留了与我的问题相关的部分Java 关于方法重写,java,overriding,Java,Overriding,对于下面的java代码段,“run”方法出现四次。我对这四次“跑”的关系感到相当困惑。原始代码相当长,我只保留了与我的问题相关的部分 1. public final class Job extends AbstractJob { 2. private Job( ) { 3. } 4. public static void main(String[] args) throws Exception { 5. new
1. public final class Job extends AbstractJob {
2. private Job( ) {
3. }
4. public static void main(String[] args) throws Exception {
5. new Job( ).run(new Path("testdata"), output, 10 );
6. }
7.
8. @Override
9. public int run(String[] args) throws IOException, ClassNotFoundException, InterruptedException {
10. run(input, output, alpha0);
11. return 0;
12. }
13. public void run(Path input, Path output, double alpha0)
14. throws IOException, ClassNotFoundException, InterruptedException {
15. ClusterDriver.run(directoryInput, output, alpha0);
16. }
17. }
我可以如下理解这段代码的调用顺序吗
首先,调用第5行的run方法。由于其特殊的参数设置(3个参数),编译器会自动使用第13行中定义的run方法。(如果第5行中只有一个参数,那么编译器将使用第9行中定义的run方法
对于第9行中定义的run方法,它将在第10行调用run方法,这实际上是在第13行中定义的run方法
我的理解正确吗?是的,它是正确的,只是这是方法重载,而不是重写 此类中定义了两个
run
方法,分别位于第9行和第13行,具有不同数量的参数。因此方法run
被重载。(如果在子类中重新定义了一个虚拟基类方法,则会发生重写-很明显,在第9行定义的方法中会发生重写,正如其注释所证明的,但这在这个特定问题中不起作用。)
有两个对
run
(第5行和第10行)的调用,这两个调用都解析为使用3个参数(在第13行定义)调用方法。只有最后一个run方法定义起作用
另一个run方法(采用
String[]
)调用此方法,因此它的行为类似于某种“代理”,而main
方法中的另一个run
调用可以选择调用这两种方法中的任何一种——“代理”run方法(采用String[/code>)或者最后一个run方法,它实际上执行“running”操作。您大部分操作都是正确的,但我想更正的语句很少:
if we only have one parameter in line 5, then compiler will use the run method defined in line 9 instead.
这并不完全正确,第9行的方法接受String[]
类型参数,您需要传递一个数组来调用此方法
For the run method defined in line 9, it will call run method at line 10, which essentially is the run method defined at line 13.
在第10行,您将得到语法错误,因为该方法中未定义input、output、alpha0
。您需要获取传递的String[]args
参数,并将其转换为input、output、alpha0
参数,以调用run
的其他实现。您的基本分析是正确的
(为了澄清其他人提出的观点:重载是指方法具有相同的名称但签名不同,而重写是指方法与超类中的方法具有相同的名称和参数类型)
作为将来的参考,您应该知道,在重载方法的情况下,Java中的方法解析(名称+参数->方法选择)实际上可能很难理解。使用的确切行为在中有详细说明,并涉及一些基本细节:
- 重载方法解析是在编译时完成的,而不是在运行时完成的。(根据最具体的子类的方法,在运行时对具有相同签名的方法重写进行选择。)如果编译器知道某个参数是
Foo
的实例(例如,其类是Foo
或Foo
的子类)然后它将使用Foo
作为参数的类,而不是它的“真实”类
- 确定使用哪种方法的问题包括:
- 方法是否为varargs(将
..
作为最后一个参数,例如foo(对象a,字符串…b)
)
- 方法的声明参数是原语还是包装原语,例如
float
vsfloat
- 一个方法的声明参数是否比另一个“更具体”(子类比它们的超类更具体)
这很复杂,但您已经有了基本的理解。这是关于方法重载,而不是重写。是的,您的理解是正确的。您看起来并不困惑,对我来说听起来不错。也许您缺乏信心。;)