Wednesday 25 June 2008

Java null casting

This afternoon I was making a code review and I saw something in the code that drew my attention. It was a 'null' casting in the code I was checking.
It was something like:

(Object[]) null
Even if I remembered having seen that null casting in the past and knowing it wouldn't fail, I didn't realize immediately why the other developer had included this "unnecessary" (at first sight) casting in the code.
Looking for a quick explanation to this, I found nothing useful and it was then when I tried to remove the "unnecessary" code and I figured out what this was all about. I finally found the answer to my question: "When is it required to make such 'null' casting in the code?"

The reason is the result of a situation similar to this:


Suppose we have a method
myMethod(String a, String b)

and an the overloaded method
myMethod(String a, Object[] b)

When we call the method like this:
anObject.myMethod("WhatAPlate!", null)
;

the JVM will have no way of identifying which of the methods should be invoked for the message received since both of them match perfectly. As a consequence, that's the case where you could call the method using a null casting in this way:
anObject.
myMethod("WhatAPlate!", (Object[])null);


Spanish version...

Haciendo un Code Review hoy a la tarde me encontré con algo que me llamó la atención. Se trataba de un casteo de 'null' en la mitad del código Java que estaba revisando.
Algo así:
(Object[]) null
Si bien recordé que en algún momento había visto eso y sabía que no fallaba, no entendía por qué lo habían incluído en el código. A simple vista no parecía algo útil. Después de leer un poco y no encontrarle la vuelta rápido intenté quitar el casteo que para mí en ese momento estaba de más y me dí cuenta de lo que no veía hasta el momento: "¿En qué situación puede ser necesario castear 'null'?".
El tema era:
Supongamos que tengo un método:
miMetodo(String a, String b)
y una sobrecarga:
miMetodo(String a, Object[] b)

En la llamada al método, si realizo la llamada:
unObjeto.miMetodo("quePlato!", null);
la JVM no tendrá manera de darse cuenta a qué método invocar debido a ambos métodos podrían responder a ese mensaje.
En tal caso, puede realizarse la llamada enviando el mensaje:
unObjeto.miMetodo("quePlato!", (Object[])null);
que haría que la llamada pueda resolverse correctamente.

3 comments:

Hernán said...

Sin conocer demasiado el proyecto donde estás trabajando, creo que la interfaz no es la mejor, ya que si puede plantear ese problema y ese casting tan poco feliz, lo mejor sería hacer una 3era sobrecarga del metodo que solo reciba un parámetro (En caso de que puedas hacerlo). La verdad que se presta a confusión la firma de ese método

Daniel Zuazaga said...

Así como está en el ejemplo, el casteo de null tampoco me gusta demasiado.
Por lo que decís, entiendo que hablás de hacer un miMetodo(String a). Eso me parece bueno, porque la firma es mucho más entendible. Ahora, la implementación de ese método tendría que delegar la ejecución en alguno de los otros dos métodos, no? Y si hacemos esto, estaría pasando la 'decisión' de cuál de los dos métodos ejecutar del código cliente al nuevo método y cambiando un poco las cosas, ya que el código cliente ya no podría decidir qué lógica ejecutar.
De todas maneras estoy seguro de que se puede hacer un refactoring para sacar el casteo de null feo. Más allá de eso, lo que me interesaba encontrar era algún caso en que el casteo de null tuviera sentido.

JuanM said...

Es interesante...

Nunca se me hubiera ocurrido que existiese un caso con la necesidad de castear un NULL.

Digamos que se le podría buscar la vuelta para evitarlo... no tiene mucho sentido así.

Si si, es interesante...