Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/java/401.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Java 当存在';没有可以接受长时间的方法吗?_Java_Type Conversion_Overloading - Fatal编程技术网

Java 当存在';没有可以接受长时间的方法吗?

Java 当存在';没有可以接受长时间的方法吗?,java,type-conversion,overloading,Java,Type Conversion,Overloading,下面是一个演示所描述(IMHO,怪异)行为的示例: public class Test { public static void print(int param) { System.out.println("int"); } public static void print(float param) { System.out.println("float"); } public static void print(Long para

下面是一个演示所描述(IMHO,怪异)行为的示例:

public class Test {

   public static void print(int param) {
       System.out.println("int");
   }

   public static void print(float param) {
       System.out.println("float");
   }

   public static void print(Long param) { //<--Wrapper type
       System.out.println("Long");
   }
   public static void main(String[] args) {
       long param = 100L;
       print(param);  // output == float
   }
} 
公共类测试{
公共静态无效打印(int参数){
System.out.println(“int”);
}
公共静态无效打印(浮动参数){
系统输出打印项次(“浮动”);
}
公共静态void print(Long param){/在这一点上非常清楚(我的重点):

15.12.2编译时步骤2:确定方法签名 [……]

  • 第一阶段(§15.12.2.2)在不允许的情况下执行过载分辨率 装箱或取消装箱转换[…]如果在此阶段未找到适用的方法,则继续处理 进入第二阶段。[…]

  • 第二阶段(§15.12.2.3)执行过载解决,同时允许 装箱和拆箱[…]

  • 第三阶段(§15.12.2.4)允许过载与变量相结合 算术方法、装箱和拆箱

  • 也就是说,在第一步中,只有
    print(int)
    print(float)
    是合适的。后者匹配,不做进一步的调查


    JLS中也解释了制定此类规则的原因:

    这保证了在Java SE 5.0之前的Java编程语言中有效的任何调用都不会因为引入变量arity方法、隐式装箱和/或取消装箱而被认为是不明确的

    假设您的
    Test
    类是针对Java 1.4编译的(在自动装箱之前)。在这种情况下,很明显:
    print(float)
    必须被选择(假设我们同意为什么
    long
    float
    被认为是安全的,并且可以是隐式的…)
    long
    参数完全不兼容

    稍后,您将针对Java 5+编译相同的代码。编译器可以:

    • 选择
      print(Long)
      作为此上下文中更“明显”的选项

    • 由于调用不明确,因此产生编译错误。因此,以前正确的代码不再在Java 5下编译(AFAIR从未出现过这种情况)

    • …或保留旧语义并调用与Java 1.4下相同的方法

    现在,您应该了解为什么要使用
    print(float)
    ,因为它是在Java1.4下选择的。Java必须向后兼容。

    请参阅文档

    5.1.2.加宽原语转换

    19基元类型上的特定转换称为 原语转换:

    • 字节到短、int、long、float或double
    • 短到整数、长到浮点或双精度
    • 字符到int、long、float或double
    • int到long、float或double
    • 长到漂浮或翻倍
    • 浮动至双倍

    因此,从
    long
    float
    的转换符合规则。

    Tomasz Nurkiewicz指向规范的相关部分(),但为什么要这样做呢?为了向后兼容,针对1.4和更早版本的源代码应该继续调用相同的重载方法。因此,必须忽略1.5的功能,并且只有在代码无法编译的情况下,才应考虑自动装箱


    <为什么>代码>长<代码> >代码>浮点< /代码>可能是隐式的,这只是一个值得怀疑的设计选择。

    < P>为什么选择<代码>浮点< /代码>超过<代码>长是后来添加自动装箱的原因,为了向后兼容,它必须进行相同的调用。第一个重载比最后两个重载更匹配(除了第一个重载可以通过适当的向下转换执行)FYI如果从示例中删除
    float
    重载,它会选择
    Long
    而不是
    int
    :@PaulBellora:感谢这一有趣的观察,它证明了上述规则是有效的。
    print(int)
    单独与
    long
    完全不兼容(请尝试删除
    print(long)
    -编译错误),因此编译器进入第2阶段。+1这似乎表明它之所以如此,是因为它确实如此。你能澄清一下为什么你认为它如此吗?@PeterLawrey:你正确地指出了向后兼容性,我包括了一些更彻底的解释,谢谢!根本上有问题的设计选择是决定隐式转换永远是av即使重载方法或运算符可以采用多种类型,ailable也必须是合法的(没有诊断)。这种设计选择导致Java需要对
    float f=(float)(1.0/10.0);
    ,但对
    double d=1.0f/10.0f;
    if(f==d)进行愚蠢的强制转换…
    。第一个表达式中的强制转换既不能提高可读性,也不能引起对潜在错误的注意;相反,如果我正在进行代码检查,并且代码应该具有……后两个表达式所隐含的语义,我希望第二个表达式写为
    double f=(double)(float)(1.0f/10.0f)第三个是
    if((double)f==d)
    ,因为在前一种情况下,*预期的*含义可能是将除法作为
    double`(而转换为double本身并不能澄清这一点);在后一种情况下,如果没有类型转换,则不清楚比较是否旨在测试
    f
    是否保留从
    d
    复制时将保留的值,或者
    d
    是否保留从
    f
    复制时将保留的值。限制使用带重载的隐式转换……会让编译器在有意义的时候执行隐式转换,在没有意义的地方发出嘎嘎声。我认为如果选项同时起作用,在不破坏兼容性的情况下,行为可能会得到改进