当前位置: 首页 > 知识库问答 >
问题:

Java重载-长和浮点

步联
2023-03-14

我试图理解java重载规则。除了遵循之外,一切似乎都很好,

public static void main(String[] args) {
    long aLong = 123L;        
    foo(aLong);
}

private static void foo(double aDouble) {
    System.out.println("Foo aDouble");
}

private static void foo(Long aWrapperLong) {
    System.out.println("Foo Wrapper Long");
}

private static void foo(int anInt) {
    System.out.println("Foo Int");
}

private static void foo(float aFloat) {
    System.out.println("Foo Float");
}

为什么调用解析为foo(浮动)。我从JLS了解到以下内容,

此步骤使用方法的名称和参数表达式的类型来定位可访问和适用的方法。可能有多个这样的方法,在这种情况下,选择最具体的方法。

我有意在这里使用Wrapper Long,而不是primitive Long。大小为64位的原语long不会以foo(double)结束,而是以32位floatfoo(float-aFloat)结束。

问题是为什么Java隐式(不带强制转换)将“long”转换为“float”?进一步澄清了这个问题的答案。

共有3个答案

井洲
2023-03-14

转换具有优先规则。它将选择加宽而不是拳击。

因此,在这种情况下,编译器搜索可以接受比长基元数据类型更大(最接近可能更大)的参数作为参数的方法,即浮点。

如果您从发布的示例中删除方法foo(双aDouble)和foo(浮动aFloat),那么编译器将执行装箱并选择foo(Long aWrapperLong)

王扬
2023-03-14

引用JLS:

确定适用性的过程始于确定潜在适用的方法(§15.12.2.1)。

该过程的其余部分分为三个阶段,以确保与JavaSE 5.0之前的Java编程语言版本的兼容性。这些阶段是:

  1. 第一阶段(§15.12.2.2)执行重载解析,不允许装箱或拆箱转换,也不允许使用变量arity方法调用。如果在此阶段没有找到适用的方法,则处理继续到第二阶段

这保证了在Java SE 5.0之前的Java编程语言中有效的任何调用不会因为引入变量arity方法、隐式装箱和/或取消装箱而被视为不明确。然而,变量arity方法(§8.4.1)的声明可能会更改为给定方法方法调用表达式选择的方法,因为变量arity方法在第一阶段被视为固定arity方法。例如,声明m(对象…)在已经声明了m(Object)的类中,由于m(Object[])更具体,因此不再为某些调用表达式(例如m(null))选择m(Object)。

编辑:关于选择浮点而不是双精度:

如果一个方法调用可以访问并适用于多个成员方法,则需要选择一个成员方法来为运行时方法调度提供描述符。Java编程语言使用的规则是选择最具体的方法。

非正式的直觉是,如果第一个方法处理的任何调用都可以传递给另一个方法,而不会出现编译时错误,那么一个方法比另一个方法更具体。

过载解决的第一阶段将选择这四种方法中的两种

private static void foo(double aDouble) 
private static void foo(float aFloat) 

因为第一阶段不允许装箱/拆箱(Long)并且您不能在没有显式转换的情况下将long传递给具有int参数的方法。将选择最具体的方法。在这种情况下,浮动方法将被解释为比最具体。

彭建业
2023-03-14

这是因为JLS#15中的“最具体”规则,该规则依次指JLS#4.10,该规则依次指#4.10.1,其中规定:

以下规则定义了基元类型之间的直接超类型关系:

>

  • 浮动

    int

    int

    哪里”S

    因此,在这种情况下,在long上没有直接匹配的情况下,在查看自动装箱之前,编译器会根据上述规则选择最近的可用超类型,即浮动

  •  类似资料:
    • 问题内容: 假设我在课堂上说两种方法 和 那是什么感觉 重载还是重载? 问题答案: 重载是指两个或多个具有相同名称但参数不同的方法,就像您的示例一样。重载是从接口或抽象类实现一个方法的,因此超类中的方法具有实现,而子类中的方法具有不同的实现,它们仍然具有相同的方法名称和参数。

    • 问题内容: 在另一个Bruce Eckel练习中,我编写的代码采用一种方法并更改另一个类中的值。这是我的代码: 它抛出一个错误,提示“可能会丢失精度”。 无法S为S作为呢? 提前致谢 问题答案: 是的,但是您必须指定它们是浮点数,否则将它们视为双精度数: 数字末尾的“ f”使其成为浮点数而不是双精度数。 Java不会自动将double范围缩小为float。

    • 问题内容: 我有一个集合(或列表或数组列表),我想在其中放置String值和double值。我决定使其成为对象的集合,并使用重载ond多态性,但是我做错了什么。 我进行了一些测试: 在测试中,似乎参数类型是在编译时而不是在运行时决定的。这是为什么? 编辑: 确定要调用的方法是在编译时确定的。有避免使用操作员的解决方法吗? 问题答案: 这是voo的答案,并提供了有关后期绑定的替代方法的详细信息。 通

    • 问题内容: 我使用Groovy,JUnit和EasyMock为Java应用程序编写单元测试。在EasyMock中,有几种重载方法已被弃用,其注释为“由于执行更严格的擦除操作,因此无法在Java 7中编译”。这些方法将类型为的对象作为参数。除其他外,存在以下方法: … Java不再允许这样做,但是如果您直接从Java调用该代码,则会调用正确的方法。例如,当您执行此代码时 正确的方法(列表中的最后一个

    • 问题内容: 我之所以学习,是因为我参加了考试,而大多数Java并没有很多问题,但是我偶然发现了一个我无法解释的规则。这是一个代码片段: 返回: 1 3 1 3 虽然我希望它会返回: 1 3 1 4 为什么a2的类型确定在AX中调用哪种方法? 我一直在阅读有关重载规则和继承的文章,但这似乎晦涩难懂,以至于我无法找到确切的规则。任何帮助将不胜感激。 问题答案: 这些方法调用的行为由Java语言规范(参

    • 自增 和自减 都是一元运算符,它的前置形式和后置形式都可以被重载。请看下面的例子: 运行结果: s1: 00:00 s2: 00:01 s1: 00:01 s2: 00:01 上面的代码定义了一个简单的秒表类,m_min 表示分钟,m_sec 表示秒钟,setzero() 函数用于秒表清零,run() 函数是用来描述秒针前进一秒的动作,接下来是三个运算符重载函数。 先来看一下 run() 函数的实