2015-01-27 14 views
8

Perché il seguente lancio di una NullPointerException? :NullPointerException nel metodo che restituisce il tipo Oggetto

public static Object myTest() { 
    boolean x = false; 
    boolean y = false; 
    return x && y ? new Object() : x ? x : y ? y : null; 
} 

public static void main(String [ ] args) { 
    myTest(); 
} 

so che se faccio una delle seguenti del codice non gettare un NullPointerException:

A)

public static Object myTest() { 
    boolean x = false; 
    boolean y = false; 
    return x && y ? new Object() : x ? x : y ? y : (Object) null; 
} 

public static void main(String [ ] args) { 
    myTest(); 
} 

B)

public static Object myTest() { 
    Boolean x = false; 
    Boolean y = false; 
    return x && y ? new Object() : x ? x : y ? y : null; 
} 

public static void main(String [ ] args) { 
    myTest(); 
} 

Inoltre, se cambio il cod e completamente e procedere come segue funziona:

public static Object myTest() { 
    boolean x = false; 
    boolean y = false; 

    if(x && y) { 
     return new Object(); 
    } else if(x) { 
     return x; 
    } else if(y) { 
     return y; 
    } else { 
     return null; 
    } 
} 

public static void main(String [ ] args) { 
    myTest(); 
} 

Credo che il compilatore sta facendo una sorta di un'ottimizzazione e in qualche modo rovinare le cose? Suppongo che si tratti di una sorta di problema di trasmissione, ma perché dovrebbe generare una NullPointerException in quel caso anziché una ClassCastException? Qualsiasi informazione sul perché questo sta accadendo sarebbe molto apprezzata!

Grazie in anticipo

+0

sta gettando un NullPointerException perché c'è un puntatore nullo da qualche parte in quel caos immenso. –

+0

Questo è quello che pensavo inizialmente, ma penso che valga la pena guardare, quindi +1 – Bathsheba

+0

@laune, lancia un 'NullPointerException'. –

risposta

6

se si aggiunge un po 'di parentesi per migliorare la leggibilità:

return (x && y) ? (new Object()) : (x ? x : (y ? y : null)); 

Si può vedere che al y ? y : null, il compilatore tenterà di unboxing null (in modo che i tipi di corrispondenza), causando un NPE da lanciare.

+2

da completare: il tipo di 'y: null' è impostato da' y' perché l'operando di sinistra è nullo. Se si aggiunge '(Object) null', si imposta il tipo, impedendo l'autounboxing a' boolean', e se si aggiunge 'Boolean y', l'unboxing non è necessario perché' null' si adatta al tipo 'Boolean'. – njzk2

+2

dopo il test, l'NPE apparentemente succede a '(x? X: ...)' perché il compilatore pensa che il risultato di '(y? Y: null)' deve essere un 'booleano' – njzk2

+1

@ njzk2 Questo potrebbe essere un http : //stackoverflow.com/questions/3882095/booleans-conditional-operators-and-autoboxing se considereremo '(y? y: null)' come equivalente di 'returnsNull()' (ma non l'ho ancora letto quindi potrei sbagliarmi). – Pshemo

1

(questo codice è illeggibile e probabilmente dovrebbe essere evitato.) Ma per rispondere effettivamente: Come sopra, il ragionamento ha a che fare con autoboxing e unboxing e il compilatore sta facendo i controlli. È come se avessi scritto boolean b = (Boolean) null che in fase di esecuzione genererà un NPE.

Nell'esempio A, lo si trasmette esplicitamente a un oggetto, quindi non è stata aggiunta alcuna autobox.

Nell'esempio B, tutto è già un oggetto (booleano è una primitiva, mentre Boolean è un oggetto), quindi ancora una volta, nessun boxing o unboxing.

Infine, nell'esempio C non c'è affatto unboxing, e invece il risultato è appena incassato quando viene restituito. (if-else branching consente al compilatore di controllare ogni ramo singolarmente, invece degli operatori ternari che richiedono di capire l'interezza dell'istruzione e quindi di assegnare l'intera istruzione a un tipo. Questo ha a che fare con le espressioni contro le espressioni e tutta una serie di stranezze nelle autoboxing e tipo-regole di controllo Java)

(problemi casting accadere al momento della compilazione, se si tenta un cast incompatibili come:. (Boolean) 7 o in fase di esecuzione se si fa qualcosa di simile:

int c = 7; 
Object co = (Object) c; 
Boolean bco = (Boolean) co; 
Problemi correlati