2010-10-26 22 views

risposta

82

Il problema è che quando si utilizza il valore letterale null, Java non sa quale tipo deve essere. Potrebbe essere un oggetto nullo o potrebbe essere un array di oggetti nullo. Per un singolo argomento assume quest'ultimo.

Hai due possibilità. Trasmetti il ​​null esplicitamente a Object o chiama il metodo usando una variabile fortemente tipizzata. Vedere l'esempio di seguito:

public class Temp{ 
    public static void main(String[] args){ 
     foo("a", "b", "c"); 
     foo(null, null); 
     foo((Object)null); 
     Object bar = null; 
     foo(bar); 
    } 

    private static void foo(Object...args) { 
     System.out.println("foo called, args: " + asList(args)); 
    } 
} 

uscita:

foo called, args: [a, b, c] 
foo called, args: [null, null] 
foo called, args: [null] 
foo called, args: [null] 
+0

Sarebbe utile per gli altri se avessi elencato il metodo 'asList' nell'esempio e il suo scopo. –

+4

@ArunKumar 'asList()' è un'importazione statica dalla classe 'java.util.Arrays'. Ho appena dato per scontato che fosse ovvio. Anche se ora ci sto pensando, probabilmente avrei dovuto usare 'Arrays.toString()' dato che l'unica ragione per cui viene convertito in una lista è che verrà stampato in modo carino. –

18

È necessario un cast esplicito a Object:

foo((Object) null); 

In caso contrario, l'argomento si presume essere l'intera matrice che la varargs rappresenta.

+0

Non proprio, vedi il mio post. –

+11

beh, penso che tu abbia torto :) – Bozho

+0

Oops, lo stesso qui ... scusa, olio di mezzanotte. –

3

Questo perché un metodo varargs può essere chiamato con una matrice effettiva anziché una serie di elementi di matrice. Quando lo si fornisce con l'ambiguo null da solo, si presuppone che lo null sia un Object[]. La trasmissione di null a Object risolverà questo problema.

5

un banco di prova per illustrare questo:

Il codice Java con una dichiarazione di metodo vararg assunzione (che risulta essere statica):

public class JavaReceiver { 
    public static String receive(String... x) { 
     String res = ((x == null) ? "null" : ("an array of size " + x.length)); 
     return "received 'x' is " + res; 
    } 
} 

Questo codice Java (un banco di prova JUnit4) chiama il sopra (stiamo usando il banco di prova di non testare qualsiasi cosa, solo per generare un output):

import org.junit.Test; 

public class JavaSender { 

    @Test 
    public void sendNothing() { 
     System.out.println("sendNothing(): " + JavaReceiver.receive()); 
    } 

    @Test 
    public void sendNullWithNoCast() { 
     System.out.println("sendNullWithNoCast(): " + JavaReceiver.receive(null)); 
    } 

    @Test 
    public void sendNullWithCastToString() { 
     System.out.println("sendNullWithCastToString(): " + JavaReceiver.receive((String)null)); 
    } 

    @Test 
    public void sendNullWithCastToArray() { 
     System.out.println("sendNullWithCastToArray(): " + JavaReceiver.receive((String[])null)); 
    } 

    @Test 
    public void sendOneValue() { 
     System.out.println("sendOneValue(): " + JavaReceiver.receive("a")); 
    } 

    @Test 
    public void sendThreeValues() { 
     System.out.println("sendThreeValues(): " + JavaReceiver.receive("a", "b", "c")); 
    } 

    @Test 
    public void sendArray() { 
     System.out.println("sendArray(): " + JavaReceiver.receive(new String[]{"a", "b", "c"})); 
    } 
} 

L'esecuzione di questo come i rendimenti di test JUnit:

 
sendNothing(): received 'x' is an array of size 0 
sendNullWithNoCast(): received 'x' is null 
sendNullWithCastToString(): received 'x' is an array of size 1 
sendNullWithCastToArray(): received 'x' is null 
sendOneValue(): received 'x' is an array of size 1 
sendThreeValues(): received 'x' is an array of size 3 
sendArray(): received 'x' is an array of size 3 

per rendere questo più interessante, chiamiamolo la funzione da Groovy 2.1.2 e vediamo cosa accade. Si scopre che i risultati non sono gli stessi! Questo potrebbe essere un bug però.

import org.junit.Test 

class GroovySender { 

    @Test 
    void sendNothing() { 
     System.out << "sendNothing(): " << JavaReceiver.receive() << "\n" 
    } 

    @Test 
    void sendNullWithNoCast() { 
     System.out << "sendNullWithNoCast(): " << JavaReceiver.receive(null) << "\n" 
    } 

    @Test 
    void sendNullWithCastToString() { 
     System.out << "sendNullWithCastToString(): " << JavaReceiver.receive((String)null) << "\n" 
    } 

    @Test 
    void sendNullWithCastToArray() { 
     System.out << "sendNullWithCastToArray(): " << JavaReceiver.receive((String[])null) << "\n" 
    } 

    @Test 
    void sendOneValue() { 
     System.out << "sendOneValue(): " + JavaReceiver.receive("a") << "\n" 
    } 

    @Test 
    void sendThreeValues() { 
     System.out << "sendThreeValues(): " + JavaReceiver.receive("a", "b", "c") << "\n" 
    } 

    @Test 
    void sendArray() { 
     System.out << "sendArray(): " + JavaReceiver.receive(["a", "b", "c"] as String[]) << "\n" 
    } 

} 

L'esecuzione di questo test JUnit produce quanto segue, con la differenza di Java evidenziata in grassetto.

 
sendNothing(): received 'x' is an array of size 0 
sendNullWithNoCast(): received 'x' is null 
sendNullWithCastToString(): received 'x' is null 
sendNullWithCastToArray(): received 'x' is null 
sendOneValue(): received 'x' is an array of size 1 
sendThreeValues(): received 'x' is an array of size 3 
sendArray(): received 'x' is an array of size 3 
1

preferisco

foo(new Object[0]); 

per evitare eccezioni puntatore nullo.

Spero che aiuti.

+8

Bene, se è un metodo vararg, perché non chiamarlo semplicemente come 'foo()'? –

+0

@ BrainStorm.exe la risposta dovrebbe essere contrassegnata come risposta. Grazie. –

Problemi correlati