【问题标题】:Java Overloading: Number,Number ; int,DoubleJava重载:数字,数字;整数,双
【发布时间】:2012-06-15 15:18:58
【问题描述】:

这两天我有一个Java考试,我想不出这个问题的答案:

class ClassA {
 public String foo(Integer x , int y) {
  return "Integer, int";
 }
 public String foo(int x, Double y) {
  return "int, Double";
 }
 public String foo(Number x, Number y) {
  return "Number, Number";
 }
 public String foo(Object x, Object y) {
  return "Object, Object";
 }
 public static void main(String... args) {
  ClassA a = new ClassA();
  System.out.print(a.foo(5, 1.2f) + " ");
  System.out.println(a.foo(null, null));
 }
}

输出是什么?

答案是:

Number, Number Number, Number

我知道java总是选择最指定的方法,这就是为什么a.foo(null,null);会调用Number,Number方法而不是Object,Object方法。 但是为什么a.foo(5,1.2f); 也调用Number,Number 方法而不是int,Double 方法呢??

但还有一件事可能会有所帮助: 如果我在1.2 之后删除f,那么调用是: a.foo(5,1.2); 我收到一个编译器错误,它无法在 Number,Numberint,Double 方法之间进行选择...

如果你们能向我解释一下,那将非常有帮助:)

【问题讨论】:

标签: java overloading


【解决方案1】:

1.2f 没有被Double 包裹,而是被Float 包裹。由于Float 不是Double 的子类(它们是Number 的不同子类),所以可以使用的最具体的方法签名是foo(Number,Number)

删除f 后,默认情况下,1.2 将被视为double(原语,而不是包装类),可以自动装箱为Double。但是 5 也可以自动装箱为 Integer,从而导致歧义。

【讨论】:

  • 好吧,我想我已经理解了 :) 所以因为 1.2f 被视为浮动,它只能自动装箱到 Float 而不是 Double。但是,如果我将 Double 更改为 double 它可以工作,因为它可以扩展到 double,这对于包装类是不可能的。
【解决方案2】:

这里有两个重要因素。

首先,1.2f 不是Double。这是Float(int, Double) 函数根本不匹配。 (Number, Number) 是最合适的。

其次,即使您将其更改为1.2,它仍然不是Double。这是一个double。也就是说,它是一个原始的,而不是一个对象。现在,Java 仍然很乐意将 double 传递给一个想要 Double 的函数,而没有太多抱怨,但在这种情况下,您通过给它两个可以进行的有效转换而混淆了它:

  1. 5 转换为Integer 1.2 转换为Double
  2. 5 保留为原始int,但将1.2 转换为Double

对于哪一个更可取,没有一个规则。 Java 会产生一个编译器错误,它有一个模棱两可的函数调用,并强制您选择您喜欢的那个(通过手动将它们中的一个或两个包装在对象中)。

顺便说一句,如果您有一个采用(int, double) 的方法,则完全没有歧义:该方法实际上匹配51.2 的现有类型,因此会调用它。事实上,这里的一些参数是导致混乱的包装对象。

【讨论】:

    【解决方案3】:

    通用答案:

    public class OverloadingNumeric {
    
        public void print(int x){
            System.out.println("int");
        }
    
        public void print(long x){
            System.out.println("long");
        }
    
        public void print(float x){
            System.out.println("float");
        }
    
        public void print(double x){
            System.out.println("double");
        }
    
        public void print(Integer x){
            System.out.println("Integer");
        }
    
        public void print(Long x){
            System.out.println("Long");
        }
    
        public void print(Float x){
            System.out.println("Float");
        }
    
        public void print(Double x){
            System.out.println("Double");
        }
    
        public void print(Number x){
            System.out.println("Double");
        }
    
        public void print(Object x){
            System.out.println("Object");
        }
    
        public static void main(String[] args) {
            OverloadingNumeric obj = new OverloadingNumeric();
            /*
             * Primitives will take more precedence
             * of calling instead of wrapper class arguments,
             */
            obj.print(10);
            obj.print(10l);
            obj.print(10f);
            obj.print(10d);
            obj.print(10.1);
            //obj.print(999999999999999); Error: this letral type int is out of range
            obj.print(999999999999999l); 
    
            /*
             * OUTPUT
             * int
             * long
             * float
             * double
             * double
             * long
             */
    
    
    
            /*
             * Assume all primitive argument methods
             *  are commented. then calling the same again
             */
            obj.print(10);
            obj.print(10l);
            obj.print(10f);
            obj.print(10d);
            obj.print(10.1);
    
            //obj.print((Double)10); //Cannot cast int to Double 
            obj.print((double)10); //Success 
            //obj.print((Float)10); //Cannot cast int to Float 
            obj.print((float)10); //Success 
            //obj.print(null); ERROR AMBIGUOUS
    
            /*
             * OUTPUT
             * Integer
             * Long
             * Float
             * Double
             * Double
             * Double
             * Float
             * 
             */
        }
    }
    
    
    
    
    interface SuperIfc {}
    
    class SuperClass implements SuperIfc{}
    
    class SubClass extends SuperClass {}
    
    public class OverloadingTest {
    
        public void print(SuperIfc x){
            System.out.println("SuperIfc");
        }
    
        public void print(SuperClass x){
            System.out.println("SuperClass");
        }
    
        public void print(SubClass x){
            System.out.println("SubClass");
        }
    
        public void print(Object x){
            System.out.println("Object");
        }
    
        public static void main(String[] args) {
            OverloadingTest obj = new OverloadingTest();
            SuperClass superObj = new SuperClass();
            SubClass subObj = new SubClass();
            obj.print(superObj);
            obj.print(subObj);
            obj.print(null);
    
            obj.print((SuperIfc)superObj);
            obj.print((SuperIfc)subObj);
            obj.print((SuperIfc)null);
            /*
             *  OUTPUT
             * SuperClass
             * SubClass
             * SubClass
             * SuperIfc
             * SuperIfc
             * SuperIfc
             */
        }
    }
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2012-07-10
      • 1970-01-01
      • 2017-10-17
      • 2013-05-18
      • 2012-10-09
      相关资源
      最近更新 更多