2012-06-15 16 views
13

En dos días tengo un examen en Java, y no puedo encontrar la respuesta a esta pregunta:Sobrecarga de Java: Número, Número; int, Doble

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)); 
} 
} 

¿Cuál es la salida?

La respuesta es:

Number, Number Number, Number 

sé que Java siempre elige el método más específico, es por eso que se a.foo(null,null); envoke el Método Number,Number y no el método Object,Object. ¿Pero por qué a.foo(5,1.2f); también envían el método Number,Number y no el método int,Double?

Pero una cosa más que podría ser útil: Si quito el f después 1.2, por lo que la llamada es: a.foo(5,1.2); me sale un error de compilación, que no se puede elegir entre el Método Number,Number y int,Double .. .

sería de gran ayuda, si ustedes pudieran explicar que a mí :)

+0

http://stackoverflow.com/a/9362386/368544 (esto explica null, null). Float case es trivial. – mschonaker

Respuesta

17

1.2f no está envuelto por una Double, está envuelto por un Float. Como Float no es una subclase de Double (son distintas subclases de Number), la firma de método más específica que se puede usar es foo(Number,Number).

Una vez que elimine el f, 1.2 se tratará como double (la clase primitiva, no la clase contenedora) de manera predeterminada, que puede ser autoboxed a Double. Sin embargo, el 5 también puede ser autoboxado a un Integer, causando la ambigüedad.

+1

Ok, creo que lo he entendido :) Entonces, como '1.2f' se trata como flotante, solo se puede autoboxear a' Float' y no a 'Double'. Pero si cambio 'Doble' a' doble', funciona debido a widning a 'double' que no es posible con las clases contenedoras. – user1459010

4

Aquí hay dos factores importantes.

Primero, 1.2f no es un Double. Es un Float. La función (int, Double) no coincide en absoluto. (Number, Number) es la mejor opción.

En segundo lugar, incluso cuando lo cambie a 1.2, todavía no es un Double. Es un double. Es decir, es un primitivo, no un objeto. Ahora, Java seguirá siendo felizmente pasar una double a una función que quiere un Double sin mucha queja, pero en este caso usted ha confundido dándole dos conversiones válidos que podría hacer:

  1. Convierte 5 a un Integer y convertir 1.2 a un Double
  2. Dejar 5 como un primitivo pero int convertir 1.2 a un Double.

No existe una regla para cuál de estos es preferible. Java produce un error de compilación que tiene una llamada de función ambigua y te obliga a elegir cuál prefieres (envolviendo manualmente uno o ambos en objetos).

Como acotación al margen, si usted tenía un método que se llevó a (int, double) no habría ninguna ambigüedad en absoluto: el método en realidad coincide con los tipos existentes de 5 y 1.2, por lo que sería llamado. Es el hecho de que algunos de los argumentos aquí son objetos envoltorios que causan el caos.

1

respuesta genérica:

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