2012-06-15 73 views
13

过两天我在Java中的考试,我不能回答弄清楚这个问题:Java重载:Number,Number; INT,双

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);将envoke的Number,Number方法,而不是Object,Object方法。 但为什么a.foo(5,1.2f);也启用Number,Number方法而不是int,Double方法?

但有可能会有所帮助件事: 如果我删除f1.2,使呼叫: a.foo(5,1.2); 我得到一个编译错误,它不能Number,Numberint,Double方法之间选择.. 。

将是非常有益的,如果你们能解释我:)

+0

http://stackoverflow.com/a/9362386/368544(这也解释了NULL,NULL)。浮动情况是微不足道的。 – mschonaker

回答

17

1.2f不是由Double包裹,它是由一个Float包裹。由于Float不是Double的子类(它们是Number的不同子类),因此可以使用的最具体的方法签名是foo(Number,Number)

一旦您删除了f,默认情况下,1.2将被视为double(原始类型,而不是包装类),该类型可以自动复制到Double。然而,5也可以自动装箱到Integer,从而造成歧义。

+1

好吧,我想我已经明白了:) 因此,因为'1.2f'被视为浮动,它只能被自动绑定到'Float'而不是'Double'。 但是,如果我把'Double'改成'double',它的工作原因是widge到一个'double',这对于包装类是不可能的。 – user1459010

4

这里有两个重要的因素。

首先,1.2f不是Double。这是一个Float(int, Double)功能根本不匹配。 (Number, Number)是最合适的。

其次,即使将其更改为1.2,它仍然不是Double。这是一个double。也就是说,这是一个原始的,而不是一个对象。现在,Java将仍然愉快地传递到double想要一个Double没有太多抱怨的功能,但在这种情况下,你已经给它两个有效转换混淆它它可以使:

  1. 转换5Integer转换1.2Double
  2. 离开5作为原始int但转换1.2Double

没有规则哪一个是最好的。 Java产生一个编译器错误,它有一个模糊的函数调用,并强制你选择你喜欢哪一个(通过手动将它们中的一个或两个包装在对象中)。顺便说一句,如果你有一个方法花了(int, double),那么根本没有什么不明确的地方:该方法实际上与51.2的现有类型相匹配,所以它会被调用。事实上,这里的一些论点是导致混乱的包装对象。

1

通用的答案:

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 
     */ 
    } 
}