使用 var-args 的重载方法 - 结合装箱和加宽

发布于 2024-11-29 06:31:14 字数 1255 浏览 1 评论 0原文

当重载包含不匹配参数的方法时,JVM 将始终使用具有比参数宽的最小参数的方法。

我通过以下两个示例确认了上述内容:

加宽:字节加宽为 int

class ScjpTest{

    static void go(int x){System.out.println("In Int");}
    static void go(long x){System.out.println("In long");}

    public static void main (String[] args){

        byte b = 5;

        go(b);

    }

}

装箱:int 装箱为整数

class ScjpTest{

    static void go(Integer x){System.out.println("In Int");}
    static void go(Long x){System.out.println("In Long");}

    public static void main (String[] args){

        int b = 5;

        go(b);

    }

}

上面的两个示例都输出“In Int”,这是正确的。但是,当情况涉及 var-args 时,我很困惑,如下例所示。

class ScjpTest{

    static void go(int... x){System.out.println("In Int");}
    static void go(long... x){System.out.println("In lInt");}

    public static void main (String[] args){

        byte b = 5;   //or even with:  int b = 5

        go(b);

    }

}

上面会产生以下错误:

ScjpTest.java:14: reference to go is ambiguous, both method go(int...) in ScjpTest and method go(long...) in ScjpTest match
                go(b);
                ^
1 error

为什么它不应用与前面的示例中相同的规则?即,将字节加宽为 int,因为它是大于字节的最小字节?

When overloading methods that contain parameters that dont match, the JVM will always use the method with the smallest argument that is wider than the parameter.

I have confirmed the above with the following two examples:

Widening: byte widened to int

class ScjpTest{

    static void go(int x){System.out.println("In Int");}
    static void go(long x){System.out.println("In long");}

    public static void main (String[] args){

        byte b = 5;

        go(b);

    }

}

Boxing: int boxed to Integer

class ScjpTest{

    static void go(Integer x){System.out.println("In Int");}
    static void go(Long x){System.out.println("In Long");}

    public static void main (String[] args){

        int b = 5;

        go(b);

    }

}

Both the above examples output "In Int" which is correct. I am confused though when the situation involve var-args as shown in the following example

class ScjpTest{

    static void go(int... x){System.out.println("In Int");}
    static void go(long... x){System.out.println("In lInt");}

    public static void main (String[] args){

        byte b = 5;   //or even with:  int b = 5

        go(b);

    }

}

The above produces the following error:

ScjpTest.java:14: reference to go is ambiguous, both method go(int...) in ScjpTest and method go(long...) in ScjpTest match
                go(b);
                ^
1 error

Why does it not apply the same rule as in the previous examples? i.e. widen the byte to an int as it is the smallest that is larger than byte?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(3

楠木可依 2024-12-06 06:31:14

var-args 语法只是将数组作为参数传递的别名:

foo(int ... arg) 等于 foo(int[] arg)

但数组是不分等级。 String[] 不是 Object[] 的子类。完全相同的规则也适用于方法参数。因此,当您传递 byte 时,编译器无法区分接受 long[]int[] 的 2 个重载方法。

var-args syntax is just a alias to passing array as an argument:

foo(int ... arg) is equal to foo(int[] arg)

But arrays are not hierarchical. String[] is not a subclass of Object[]. Exactly the same rule is relevant for the method arguments. Therefore compiler cannot distinguish between 2 overloaded methods that accept long[] and int[] when you are passing byte.

安稳善良 2024-12-06 06:31:14

正如 AlexR 指出的,var-args 就像一个数组。基元数组(例如 byte[] Short[] int[] long[] float[] double[] 似乎在内部编译为同一个类。这就是您的重载方法不明确的原因。但是以下代码完全有效:
static void go(int... x){System.out.println("In Int");}
static void go(Long... x){System.out.println("In lInt");}

编译成功(因为 int[]Long[] 是不同的类型),并生成输出 In Int
如果您正在准备 SCJP,我强烈建议您阅读SCJP Sun 认证程序员一书Java 6 考试 310-065。本书中的重载部分涵盖了混合拳击和可变参数的所有技巧。

As AlexR pointed out, var-args is just like an array. Arrays of primitives (such as byte[] short[] int[] long[] float[] double[] seem to be internally compiled to the same class. That's why your overloaded methods are ambiguous. However the following code is perfectly valid:
static void go(int... x){System.out.println("In Int");}
static void go(Long... x){System.out.println("In lInt");}

This compiles successfully (since int[] and Long[] are different types), and produces the output In Int.
If you're preparing for SCJP, I would highly recommend you reading book SCJP Sun Certified Programmer for Java 6 Exam 310-065. The section Overloading in this book covers all the tricks with mixing boxing and var-args.

黑凤梨 2024-12-06 06:31:14

它实际上在 Java 7 中工作:它也为 varargs 示例返回“In Int”。我想这只是以前版本中缺少的功能。我不知道你正在使用什么 Java 版本,但也许它也适用于 Java 6。

但是我必须说,我很惊讶即使你的第一个示例也能工作(没有可变参数)。我不知道原始扩展转换。
顺便说一句,如果您改用 Byte、Integer 和 Long,您的第一个和最后一个示例就会失败,因为这些类型之间没有层次结构(除了它们都是 Number 的子类)。

It actually works in Java 7: it returns "In Int" for the varargs example too. I guess it was just a missing feature in previous versions. I don't know what Java version you are using but maybe it is also working for Java 6.

However I must say that I was surprised that even your first example works (without the varargs). I was not aware of primitive widening conversions.
By the way, your first and last examples fail if you instead use Byte, Integer and Long since there is no hierarchy between those types (except that they are all subclasses of Number).

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文