2012-06-15 12 views
13

In due giorni ho un esame in Java, e io non riesco a capire la risposta a questa domanda:Sovraccarico di Java: numero, numero; int, double

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

Qual è l'uscita?

La risposta è:

Number, Number Number, Number 

So che Java sceglie sempre il metodo più indicato, è per questo che sarà a.foo(null,null); envoke il Number,Number metodo e non il metodo Object,Object. Ma perché a.foo(5,1.2f); invoca anche il metodo Number,Number e non il metodo int,Double ??

Ma una cosa che potrebbe essere utile: se mi tolgo la f dopo 1.2, in modo che la chiamata è: a.foo(5,1.2); ottengo un errore del compilatore, che non può scegliere tra il metodo Number,Number e int,Double .. .

sarebbe veramente utile, se voi ragazzi potrebbe spiegare che a me :)

+0

http://stackoverflow.com/a/9362386/368544 (questo spiega null, null). La cassa galleggiante è banale. – mschonaker

risposta

17

1.2f non è avvolto da un Double, è avvolto da un Float. Poiché Float non è una sottoclasse di Double (sono sottoclassi distinte di Number), la firma del metodo più specifica che è possibile utilizzare è foo(Number,Number).

Una volta rimosso lo f, 1.2 verrà considerato un double (primitivo, non la classe wrapper) per impostazione predefinita, che può essere autoboxato a Double. Tuttavia il 5 può anche essere autoboxed a Integer, causando così l'ambiguità.

+1

Ok penso di averlo capito :) Quindi, poiché '1.2f' è trattato come float, può essere solo autoboxato a' Float' non a un 'Double'. Ma se cambio 'Double' a' double' funziona a causa del widning con un 'double' che non è possibile con le classi wrapper. – user1459010

4

Ci sono due fattori importanti qui.

In primo luogo, 1.2f non è un Double. È un Float. La funzione (int, Double) non corrisponde affatto. (Number, Number) è la soluzione migliore.

In secondo luogo, anche se lo si modifica in 1.2 non è ancora un Double. È un double. Cioè, è un primitivo, non un oggetto. Ora, Java sarà ancora felicemente passare un double in una funzione che vuole una Double senza molta denuncia, ma in questo caso hai confuso dandole due conversioni valide si potrebbe fare:

  1. Convert 5 a un Integere convertire 1.2 ad un Double
  2. Lasciare 5 come un primitivo int ma convertire 1.2 ad un Double.

Non esiste una regola per quale di questi è preferibile. Java genera un errore del compilatore che ha una chiamata di funzione ambigua e ti costringe a scegliere quale preferisci (manualmente avvolgendo uno o entrambi in oggetti).

Per inciso, se si ha un metodo che ha preso (int, double) non ci sarebbe alcuna ambiguità a tutti: quel metodo corrisponde in realtà i tipi esistenti di 5 e 1.2, quindi sarebbe chiamato. È il fatto che alcuni degli argomenti qui sono oggetti wrapper che causano il caos.

1

risposta generica:

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