Java重载-计算是在编译时还是在运行时进行?

Java重载-计算是在编译时还是在运行时进行?,java,overloading,Java,Overloading,下面是代码 package org.nagark; class baseClass{ public void callMtd(int i){ System.out.println("integer method"+i); } public void callMtd(double d){ System.out.println("double method"+d); } } public class OverRidingExa

下面是代码

package org.nagark;


class baseClass{

    public void callMtd(int i){
        System.out.println("integer method"+i);
    }

    public void callMtd(double d){
        System.out.println("double method"+d);
    }
}

public class OverRidingExample {

    /**
     * @param args
     */
    public static void main(String[] args) {
        baseClass bc = new baseClass();
        bc.callMtd(10/3);
    }

}

OverRidingExample
类中,我正在调用带有参数10/3的
baseClass.callMtd
方法(如代码中所示)。由于callMtd在基类中重载,默认情况下应该调用哪个版本?由于重载,方法绑定应该在编译时发生,但是10/3的计算会在编译时发生吗?

10/3
3
相同,因此将调用
int
版本

int
仅当不存在
int
参数化方法时才会转换为
double

10/3
的计算将在编译时进行,因为它满足常量表达式的要求(谢谢,)

方法及其完整签名(包括参数类型)始终在编译时解析。例如,如果您正在使用某个jar并从该jar中的任何类调用某个方法
methodName(String x)
,并且该方法更改了签名(展宽),同时将该jar替换为更现代的版本
methodName(Object x)
(没问题,不是吗?)

顺便说一句,如果您不确定,您总是可以查看生成的
覆盖示例的字节码

$ javap -c  OverRidingExample.class 
Compiled from "OverRidingExample.java"
public class org.nagark.OverRidingExample {
  public org.nagark.OverRidingExample();
    Code:
       0: aload_0
       1: invokespecial #1                  // Method java/lang/Object."<init>":()V
       4: return

  public static void main(java.lang.String[]);
    Code:
       0: new           #2                  // class org/nagark/baseClass
       3: dup
       4: invokespecial #3                  // Method org/nagark/baseClass."<init>":()V
       7: astore_1
       8: aload_1
       9: iconst_3
      10: invokevirtual #4                  // Method org/nagark/baseClass.callMtd:(I)V
      13: return
}
$javap-c OverRidingExample.class
从“OverRidingExample.java”编译而来
公共类org.nagark.OverRidingExample{
public org.nagark.OverRidingExample();
代码:
0:aload_0
1:invokespecial#1//方法java/lang/Object。“:()V
4:返回
公共静态void main(java.lang.String[]);
代码:
0:new#2//classorg/nagark/baseClass
3:dup
4:invokespecial#3//方法org/nagark/baseClass。”“:()V
7:astore_1
8:aload_1
9:iconst_3
10:invokevirtual#4//Method org/nagark/baseClass.callMtd:(I)V
13:返回
}
你可以看到,这是:

  • 没有除法,只是常数的加载(我想它等于3)
  • 调用
    int
    参数化方法。量化宽松

  • 如果您不熟悉字节码,可以阅读本文。

    10/3
    3
    相同,因此将调用
    int
    版本

    int
    仅当不存在
    int
    参数化方法时才会转换为
    double

    10/3
    的计算将在编译时进行,因为它满足常量表达式的要求(谢谢,)

    方法及其完整签名(包括参数类型)始终在编译时解析。例如,如果您正在使用某个jar并从该jar中的任何类调用某个方法
    methodName(String x)
    ,并且该方法更改了签名(展宽),同时将该jar替换为更现代的版本
    methodName(Object x)
    (没问题,不是吗?)

    顺便说一句,如果您不确定,您总是可以查看生成的
    覆盖示例的字节码

    $ javap -c  OverRidingExample.class 
    Compiled from "OverRidingExample.java"
    public class org.nagark.OverRidingExample {
      public org.nagark.OverRidingExample();
        Code:
           0: aload_0
           1: invokespecial #1                  // Method java/lang/Object."<init>":()V
           4: return
    
      public static void main(java.lang.String[]);
        Code:
           0: new           #2                  // class org/nagark/baseClass
           3: dup
           4: invokespecial #3                  // Method org/nagark/baseClass."<init>":()V
           7: astore_1
           8: aload_1
           9: iconst_3
          10: invokevirtual #4                  // Method org/nagark/baseClass.callMtd:(I)V
          13: return
    }
    
    $javap-c OverRidingExample.class
    从“OverRidingExample.java”编译而来
    公共类org.nagark.OverRidingExample{
    public org.nagark.OverRidingExample();
    代码:
    0:aload_0
    1:invokespecial#1//方法java/lang/Object。“:()V
    4:返回
    公共静态void main(java.lang.String[]);
    代码:
    0:new#2//classorg/nagark/baseClass
    3:dup
    4:invokespecial#3//方法org/nagark/baseClass。”“:()V
    7:astore_1
    8:aload_1
    9:iconst_3
    10:invokevirtual#4//Method org/nagark/baseClass.callMtd:(I)V
    13:返回
    }
    
    你可以看到,这是:

  • 没有除法,只是常数的加载(我想它等于3)
  • 调用
    int
    参数化方法。量化宽松

  • 如果您不熟悉字节码,可以阅读本文。

    编译器在决定调用哪个重载方法时,会查看参数的类型。您的类型是
    int
    。因此,方法签名

    public void callMtd(int i)
    

    将使用,在编译时确定。

    编译器在决定调用哪个重载方法时会查看参数的类型。您的类型是
    int
    。因此,方法签名

    public void callMtd(int i)
    

    将被使用,在编译时确定。

    可能重复的可能重复的可能重复的正是我写的。但是,可能存在一些Java实现,但它们不能做到这一点。您可以通过检查语句
    byte x=300/3来展示编译器的行为将被正确接受必须被拒绝。另一点是,即使是
    “+100/3==”+100/3
    也必须是
    true
    ,才能满足规范(并且将再次成为编译时常量,这意味着
    “+100/3==”+100/3?1:0
    开关
    语句中的有效
    大小写标签…@Holger好的,那么我的答案在某种程度上是错误的。将被修复。谢谢。@Dmitry Ginzburg:原则上,编译器可以在这种非常特殊的情况下发出指令进行计算,而不会产生任何影响。但是,还有很多其他的场景会产生影响。这正是我写的。但是,可能存在一些Java实现,但它们不能做到这一点。您可以通过检查语句
    byte x=300/3来展示编译器的行为将被正确接受必须被拒绝。另一点是,即使是
    “+100/3==”+100/3
    也必须是
    true
    ,才能满足规范(并且将再次成为编译时常量,这意味着
    “+100/3==”+100/3?1:0