Metodo Sovraccarico per argomento null


133

Ho aggiunto tre metodi con parametri:

public static  void doSomething(Object obj) {
    System.out.println("Object called");
}

public static  void doSomething(char[] obj) {
    System.out.println("Array called");
}

public static  void doSomething(Integer obj) {
    System.out.println("Integer called");
}

Quando chiamo doSomething(null), il compilatore genera l'errore come metodi ambigui . Quindi il problema è perché Integere char[]metodi o Integere Objectmetodi?


3
Basta cambiare il Integera int.
Mudassir,

2
@Mudassir: e cosa risolverebbe esattamente?
Joachim Sauer l'

2
@Joachim Sauer: se modificato da Integer a int, allora null non si riferisce ai tipi primitivi in ​​Java, quindi il compilatore non genererà errori.
Phani,

@Joachim Sauer: non genererà l' reference to doSomething is ambiguouserrore.
Mudassir,

Risposte:


211

Java tenterà sempre di utilizzare la versione applicabile più specifica di un metodo disponibile (vedere JLS § 15.12.2 ).

Object, char[]E Integerpossono tutti prendere nullcome valore valido. Pertanto, tutte e 3 le versioni sono applicabili, quindi Java dovrà trovare quella più specifica.

Poiché Objectè il super-tipo di char[], la versione dell'array è più specifica della Objectversione. Quindi, se esistono solo questi due metodi, char[]verrà scelta la versione.

Quando entrambe le versioni char[]e Integersono disponibili, entrambe sono più specifiche di Objectma nessuna è più specifica dell'altra, quindi Java non può decidere quale chiamare. In questo caso dovrai menzionare esplicitamente quale vuoi chiamare lanciando l'argomento sul tipo appropriato.

Si noti che in pratica questo problema si verifica molto più raramente di quanto si possa pensare. La ragione di ciò è che succede solo quando chiami esplicitamente un metodo con nullo con una variabile di tipo piuttosto non specifico (come Object).

Al contrario, la seguente invocazione sarebbe perfettamente inequivocabile:

char[] x = null;
doSomething(x);

Anche se stai ancora passando il valore null, Java sa esattamente quale metodo chiamare, poiché prenderà in considerazione il tipo di variabile.


1
Questo è dichiarato per Java 7. Questo vale anche per le versioni precedenti di Java? Voglio dire: se hai diverse firme di metodo con parametri solo lungo una gerarchia di tipi, allora sei sul lato di salvataggio con null come valore effettivo? E se hai creato una "gerarchia per" come nell'esempio qui, allora non lo sei?
Christian Gosch,

2
Sono abbastanza sicuro che quelle regole siano le stesse per almeno tutto da Java 1.1 (tranne per l'aggiunta di generici, ovviamente).
Joachim Sauer,

Questo significa che se il compilatore dovesse scegliere tra doSomething (String str) e doSomething (Object obj) durante il runtime con doSomething (null), verrà chiamato doSomething (String str).
Sameer,

42

Ogni coppia di questi tre metodi è ambigua da sola quando viene chiamata con un nullargomento. Perché ogni tipo di parametro è un tipo di riferimento.

Di seguito sono i tre modi per chiamare un metodo specifico del tuo con null.

doSomething( (Object) null);
doSomething( (Integer) null);
doSomething( (char[]) null);

Posso suggerire di rimuovere questa ambiguità se in realtà si prevede di chiamare questi metodi con nullargomenti. Un tale progetto invita errori in futuro.


1
Only Integer- char[]pair è ambiguo, perché in altri due casi, il compilatore Java può scegliere la scelta più specifica, come descritto da @JoachimSauer.
Kajacx,

1
@kajacx: ​​la domanda originale di OP riguardava la chiamata di questi metodi nullcome parametro. In base a tale presupposto, tutte e tre le coppie sono ambigue. Per il caso generale, concordo sul fatto che solo la Integer - char[]coppia è ambigua.
jmg,

che dire doSomething(null)di public static void doSomething(String str) { System.out.println("String called"); } Questo restituirà una stringa chiamata.
Sameer

È possibile utilizzare un'anotazione come "nullable" o "non nullable" e impostare le dichiarazioni in modo che solo il metodo con cui si desidera ottenere un null in modo che un argomento esplicito "null" (ma implicito tipo null) selezioni sempre in modo univoco un sovraccarico specifico ??
Peter,

4

nullè un valore valido per uno dei tre tipi; quindi il compilatore non può decidere quale funzione usare. Usa qualcosa di simile doSomething((Object)null)o doSomething((Integer)null)invece.


Ho rimosso il metodo con il parametro Integer, sta invocando la funzione e restituendo l'output come "Array Called" , quindi qual è il contratto tra Array e Object ?
Phani,

2
Anche gli array Java sono oggetti.
Zds

2

Ogni classe in Java estende la classe Object. Anche la classe Integer estende anche Object. Quindi sia Object che Integer sono considerati come istanza Object. Quindi quando si passa null come parametro rispetto al compilatore viene confuso ciò che metodo oggetto chiamare, ad esempio Con parametro Object o parametro Integer poiché entrambi sono oggetto e il loro riferimento può essere nullo. Ma i primitivi in ​​Java non estende l'oggetto.


1

Ho provato questo e quando esiste esattamente una coppia di metodo sovraccarico e uno di essi ha un tipo di parametro Object, il compilatore selezionerà sempre il metodo con un tipo più specifico. Ma quando esiste più di un tipo specifico, il compilatore genera un errore metodo ambiguo.

Poiché si tratta di un evento di compilazione, ciò può accadere solo quando si passa intenzionalmente null a questo metodo. Se ciò viene fatto intenzionalmente, è meglio sovraccaricare nuovamente questo metodo senza parametri o creare un altro metodo del tutto.


0

c'è un'ambiguità a causa di doSomething (char [] obj) e doSomething (Integer obj).

char [] e Integer sono entrambi uguali superiori per null, per questo motivo sono ambigui.


0
class Sample{
  public static void main (String[] args) {
       Sample s = new Sample();
       s.printVal(null);

    } 
    public static void printVal(Object i){
        System.out.println("obj called "+i);
    }

    public static void printVal(Integer i){
        System.out.println("Int called "+i);
    }
}

L'output è Int chiamato null e quindi l'ambiguità è con char [] e Integer

Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.