【问题标题】:Why widening beats both Boxing and var-args in Overloading of a method?为什么在方法重载中加宽比 Boxing 和 var-args 都好?
【发布时间】:2013-07-10 01:15:21
【问题描述】:

我正在准备 SCJP 考试,在学习扩展部分时,考虑到扩展在重载方面胜过拳击和 Var-args,但没有明确的解释。尝试搜索但没有得到更好的答案。

我得到的一个答案是因为编译器在选择新样式之前选择了旧样式。但我不相信。

编辑:我知道加宽比拳击和 var-args 更受欢迎。但为什么是我的问题。其中我知道一个。任何其他原因。

【问题讨论】:

  • 除了兼容性之外不需要任何其他原因。兼容性被认为是在 Java 中压制许多“更好”的东西的主要原因。例如,使用基于擦除的泛型而不是具体化的泛型完全是对兼容性的让步。
  • 告诉我们你知道的原因,这样我们就不会一遍又一遍地重复了。
  • 我在问题本身中已经提到的那个。风格。

标签: java


【解决方案1】:

是的,由于兼容性要求,编译器“选择旧样式而不是新样式”。想象一下,在 Java 5 出现之前编写的一些代码,在 Java 5 下编译时突然发生了行为变化!那会很糟糕。

自 Java 诞生之初就出现了扩展转换,但自动装箱和可变参数是 Java 5 的新功能。

【讨论】:

    【解决方案2】:

    这是一个例子:

    class Widen {
    
        private static void widen(long k) {
            System.out.println("Converted to long: " + k);
        }
    
        private static void widen(int ... k) {
            System.out.println("Converted to varargs: " + k);
        }
    
        private static void widen(Integer k) {
            System.out.println("Converted to Integer: " + k);
        }
    
        public static void main(String ... args) {
            int value = 3;
            widen(value);  // Output: Converted to long: 3
        }
    }    
    

    所以这一切意味着它会在自动装箱和使用可变参数之前变宽。如果我们拿出带long参数的widen方法,它会在可变参数之前选择自动装箱。

    【讨论】:

      【解决方案3】:

      编译器必须保持与 Java 早期版本的兼容性。最重要的是,编译器选择对参数的最高性能/最小更改。在内存使用和性能方面,提升到另一个原语优于创建包装对象,也优于创建数组。

      【讨论】:

        【解决方案4】:

        扩展性能更好的原因是它是一个简单的符号扩展操作,对于大多数 CPU 来说是一条指令。装箱需要堆分配,并且装箱的对象访问成本更高,至少需要额外的内存访问。

        即使没有兼容性问题,在我看来,只要这种行为不会造成任何更严重的问题,您还是希望该语言优先选择最快的重载。

        【讨论】:

          【解决方案5】:

          我不了解你,但我更希望编译器将我的byte 作为int 传递,而不是作为Byte。考虑开销。而且可变参数也需要装箱。

          换句话说,原因是效率。语言设计更喜欢更有效的调用机制,不需要分配盒装项目。

          '需要',你问?可变参数函数期望得到一个 Object 数组,并且不能包含原始类型。

          兼容性也不是坏事。

          【讨论】:

          • 这就是我要问的原因?任何理由。
          • 这是一个原因。让我再试一次。
          • @bmargulies - 为什么可变参数需要装箱?
          • @bmargulies - 我认为编译器会创建一个给定类型的数组,无论是对象还是原语。在method(long... var) var 是一个原始长数组...
          • @Carlos Heuberger 我没有想到这一点。我在想 (Object ...var)
          【解决方案6】:

          加宽击败拳击, 拳击击败仿制药, 泛型击败可变参数

          【讨论】:

            【解决方案7】:
            class Widen {
                private static widen(long k) {
                    System.out.println("Converted to long: " + k);
                }
                private static widen(int ... k) {
                    System.out.println("Converted to varargs: " + k);
                }
                private static widen(Integer k) {
                    System.out.println("Converted to Integer: " + k);
                }
                public static void main(String ... args) {
                    int value = 3;
                    widen(value);  // Output: Converted to long: 3
                }
            } 
            

            解决以上问题:

            加宽击败拳击,拳击击败可变参数

            输出将是 转换为 long:3

            【讨论】:

            • 这不是答案,只是mangoDrunk's answer 的脏副本,并附有应作为评论的附加声明。请不要提供此类答案,并等待至少 50 名代表发布有关问题/答案的 cmets。
            猜你喜欢
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 2014-01-18
            • 1970-01-01
            • 2020-12-24
            相关资源
            最近更新 更多