juin
2010
Java Quiz #39
If you're not getting your athletic body's tanned on a beach this week, here is a small quiz to keep your brain fit.
What does this code snippet do ?
public class Quiz39 { public static void main(String[] args) { int[] array = null; try { array[0] = array[(array = createArray())[array.length - 1]]; } finally { System.out.println("Array = " + Arrays.toString(array)); } } public static int[] createArray() { return new int[]{1, 2, 3, 4}; } }
Answer :
This code raises a NullPointerException (NPA) but... still initializes the int array !
Array = [1, 2, 3, 4] Exception in thread "main" java.lang.NullPointerException at net.thecodersbreakfast.quiz.quiz39.Quiz39.main(Quiz39.java:11) at (...)
The key to understanding this surprising behavior is given (as often) in the Java Language Specification JLS, §15.13 :
If the array reference expression produces null instead of a reference to an array, then a NullPointerException is thrown at run time, but only after all parts of the array access expression have been evaluated and only if these evaluations completed normally.
In our quiz, the left-hand expression "array0
" raises the NPE as expected, but only after the right-hand expression is fully evaluated ; and the fact that this right-hand expression could effectively eliminate the NPE problem (by assigning a non-null reference to the array
local variable) is not taken into account...
This quiz show clearly one of the rare cases of delayed exception raising in Java.
Commentaires
Petit indice, il faut lire les spécifications du langage Java (alias jls)
http://java.sun.com/docs/books/jls/...
Ça plantouille, non ? (tentative d'accès à array4 il me semble)
Hum, sympa ce quiz... Alors, essayons voir :
1/ array est initialisé à null (ligne 4)
2/ ligne 6, la référence à array à droite du = est évaluée. Elle vaut null.
3/ le contenu du premier crochet à droite du = est évalué :
4/ on évalue donc (résultat de 2/)[résultat de 3/] soit null [4] => NullPointerException
5/ le bloc finally est appelé, il imprime la valeur de array, qui vaut {1,2,3,4}depuis 3a/
J'espère que je n'ai rien manqué...
l'idée est de découper :
au lieu de lire :
array0 = array(array = createArray())[array.lengt...];
On lira :
array = createArray();
int i = arrayarray.length - 1;
array0 = arrayi;
la dernière ligne levra une exception :
java.lang.ArrayIndexOutOfBoundsException parceque i=4
En fait expression array(array = createArray())[array.lengt...] peut être découpé en 2 expressions :
- aarray.length - 1
- array = createArray()
mais elles sont exécutés dans l'ordre suivant :
d'abord aarray.length - 1 puis array = createArray() donc on a un java.lang.ArrayIndexOutOfBoundsException car array est à null.
c'est peut-être plutôt un NullPointerException ^^
Moi je dirais aussi NullPointerException en tenant compte de l'ordre d'exécution de la ligne.
Mais sinon, si le tableau est créé avant, i est bien égal à 4.
Je suis plus d'accord avec Jerôme
array[0] = array[(array = createArray())[array.length - 1]];
Mais je n'aurais pas parié dessus si je n'avais pas lu cette section de la spec du langage!
on l'attend toujours cette réponse !