【问题标题】:Java Casting in Method Overloading方法重载中的 Java 强制转换
【发布时间】:2014-12-16 07:22:43
【问题描述】:

我有方法重载,例如:

 public int sum1(int a, int b)
{
    int c= a+b; 
    System.out.println("The method1");
    return c; 
}
public float sum1(int a, float b)
{
    float c=  a+b;
    System.out.println("The method2");
    return c; 
}
public double sum1(float a, float b)
{
    double c=  (double) a+b;
    System.out.println("The method3");
    return c; 
}

从main方法,假设我们有

 double x=10.10f;
 double y=10.20f; 

x 和 y 的表观类型是 double,但实际类型是 float。当我打电话时

System.out.println(" the output is :"+cc.sum1(x,y)); 

编译时的错误。

The method sum1(int, int) in the type Class is not applicable for the arguments double, double). 

通过将 double 转换为 float,它应该转到 sum1(即方法 3)的位置

【问题讨论】:

  • 我什至没有看到任何?
  • “x 和 y 的表观类型是 double,但实际类型是 float” – 不,类型只是 double。原始类型不是多态的。 float 不是double 的子类,即使它是:重载决议对 static 类型进行操作。此外,您的第二次超载是多余的。只需让编译器在调用时将int 隐式转换为float
  • @5gon12eder:intfloat 是无损转换吗?
  • @Thilo 是的。但是,longfloat 不是。
  • 看来他们只是简单地将其定义为无损/扩展。 § 5.1.2 JLS: “从intfloat,或从longfloat,或从longdouble 的扩大原语转换,可能会导致精度损失——即,结果可能会丢失一些值的最低有效位。在这种情况下,生成的浮点值将是整数值的正确舍入版本,使用 IEEE 754 舍入到最近模式。”

标签: java casting overloading


【解决方案1】:

TL;此答案的 DR 版本:

  • 原始类型的变量在执行时与编译时的类型永远不会不同。 (double 始终是 double,绝不是 float,等等)
  • 使用编译时类型的表达式执行重载解析(选择使用的方法签名)
  • 使用方法调用目标的执行时类型来执行选取签名的方法实现

x 和 y 的表观类型是 double,但实际类型是 float

不,不是。您刚刚将分配的 float 文字转换为 double 值。 实际值double

基元不像对象那样工作 - 例如,不知道 int 值仍然是 double 变量内的 int

以整数类型为例更简单。假设我们有:

byte b = 100;
int x = b;

x 的值是代表值 100 的 32 位整数。它不“知道”它最初是从 byte 值分配的……恰好是从 @ 的转换987654333@ 到 int 在分配点。

将其与 reference 类型进行比较:

String x = "hello";
Object y = x;

这里,y 的值确实String 对象的引用。正是因为有一个完整的对象可以包含它,并且变量本身的值只是一个引用,所以保留了该类型信息。 (作为分配的一部分,这些位本身不需要更改 - 至少在一个简单的 VM 中,它们将与 xy 中的位完全相同,因为它们指的是同一个对象。 )

然而,即使在这种情况下,重载决策也是基于参数的编译时类型,而不是它们在执行时的实际值。涉及变量的执行时类型的唯一方法是基于方法调用的目标覆盖。所以如果我们有:

Foo f = new X();
Foo g = new Y();
Foo h = new Z();

f.someMethod(g, h);

...然后编译器将在Foo 中查找具有两个Foo 参数(或Object 或其他超类/接口)的方法- 所涉及的对象的实际类型无关紧要。然而,在执行时,如果该方法已在 X 中被覆盖,则该覆盖将由于对象 f 的值所指的执行时类型而被调用。

【讨论】:

  • @Thilo:是的。将对此添加一些内容。
  • @TheLostMind:是的,方法签名是在编译时选择的。但不只是检查,然后将使用该签名(即使在运行时碰巧有一个“更好”的签名)。
  • @Thilo:看看我的编辑是否足够 - 如果您希望我更详细地介绍,请告诉我。 (考虑到问题只是在谈论原语,我有点不情愿。)
【解决方案2】:

将 double 转换为 float 可能会导致数据丢失,因为它是一种缩小转换,因此编译器不会自动完成。如果您希望它发生,您必须将变量显式转换为浮动。

【讨论】:

    【解决方案3】:

    不,变量的实际类型是double。您分配给double 变量的常量类型是float

    【讨论】:

      【解决方案4】:

      尝试添加新函数:public double sum1(double a, double b)。它会解决你的问题。 而且,这种强制转换会导致数据丢失。

      【讨论】:

        【解决方案5】:

        浮点数很有趣.. 他们总是尝试自动转换为双精度数。这段代码可以编译,每次都有浮点数。

            public class wood {
            public static void main(String[] args) {
                float x = 10.1f;
                float y = 10.2f;
                System.out.println("Sum of x and y = " + sum1((float)x, (float)y));
            }
            public static float sum1(float x, float y) {
                return (float)((float)x+(float)y);
            }
        }
        

        编辑;请注意,在括号外使用强制转换运算符将在计算括号内的内容之后进行强制转换。所以;

        System.out.println((int)(50.5 + 50.7));
        

        将打印出 101。

        在 java 中,一些数据转换是自动的,而另一些则需要强制转换运算符。简单地说,java 会自动进行扩大转换,而您必须使用强制转换运算符来缩小转换。

        原始数据类型的层次结构如下:

        byte //1 个字节(-128 到 127)

        short //2 个字节(从 0 开始超过 32,000 个给/取)

        int //4 个字节(超过 20 亿个从 0 的给/取)

        long //8 字节(超过 9 quintillion (10^18) 从 0 给/取)

        float //4 个字节(保留 7 个小数位)

        double //8 字节(保留 15 位小数)

        java 不会自动进行缩小转换,因为这样数据就有丢失的风险。 byte和short都会自动变成int。

        short s = 5;
        byte b = 5;
        short sum = s + b;  //this will cause an error!
        
        short sum = (short)(s + b);
        

        需要。

        【讨论】:

        • 很高兴这是有道理的。了解 java 如何进行数据类型转换很重要。
        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2023-03-22
        相关资源
        最近更新 更多