una - Despacho del método Java con argumento nulo
metodos en java netbeans (4)
¿Por qué (aparentemente) hace una diferencia si paso null
como un argumento directamente, o paso un Object
que asigné el valor null
?
Object testVal = null;
test.foo(testVal); // dispatched to foo(Object)
// test.foo(null); // compilation problem -> "The method foo(String) is ambiguous"
public void foo(String arg) { // More-specific
System.out.println("foo(String)");
}
public void foo(Object arg) { // Generic
System.out.println("foo(Object)");
}
En otras palabras, ¿por qué la segunda llamada (comentada) a foo(...)
no se envía a foo(Object)
?
Actualización: uso Java 1.6. Pude compilar el código de Hemal sin problemas, pero el mío todavía no compila. La única diferencia que veo es que los métodos de Hemal son estáticos mientras que los míos no. Pero realmente no veo por qué esto debería hacer la diferencia ...?
Actualización 2: Resuelto. Tenía otro método foo (Runnable) en mi clase, por lo que el despachador no pudo seleccionar inequívocamente el método más específico. (Vea mi comentario en la segunda respuesta de Hemal.) Gracias a todos por su ayuda.
¿Alguien ha probado el ejemplo?
Con 1.6.0 foo (null) se envía al método más específico aplicable que es foo (String) ...
Si agrega un nuevo método, digamos foo (Entero) el compilador no puede elegir el método aplicable más específico y muestra un error.
-Patricio
¿Qué versión de Java estás usando? Con 1.6.0_11, el código (pegado a continuación) se compila y ejecuta.
Estoy seguro de que es obvio por qué foo(testVal)
va a foo(Object)
.
La razón por la cual foo(null)
va a foo(String)
es un poco compleja. La constante null
es de tipo nulltype
, que es un subtipo de todos los tipos. Entonces, este tipo nulltype
extiende String
, que extiende Object
.
Cuando llamas al compilador foo(null)
busca el método sobrecargado con el tipo más específico. Dado que String
es más específico, Object
es el método que se llama.
Si tuviera otra sobrecarga que fuera tan específica como String, digamos foo(Integer)
entonces obtendría un error de sobrecarga ambiguo.
class NullType {
public static final void main(final String[] args) {
foo();
}
static void foo()
{
Object testVal = null;
foo(testVal); // dispatched to foo(Object)
foo(null); // compilation problem -> "The method foo(String) is ambiguous"
}
public static void foo(String arg) { // More-specific
System.out.println("foo(String)");
}
public static void foo(Object arg) { // Generic
System.out.println("foo(Object)");
}
}
Perdón por usar una respuesta, para un comentario, pero necesito publicar un código que no se ajuste al comentario.
@Yang, también puedo compilar y ejecutar lo siguiente. ¿Puedes publicar un código completo que compila con una línea comentada de tal manera que si descomiento esa línea no se compilará?
class NullType {
public static final void main(final String[] args) {
foo();
new Test().bar(new Test());
}
static void foo()
{
Object testVal = null;
foo(testVal); // dispatched to foo(Object)
// foo(null); // compilation problem -> "The method foo(String) is ambiguous"
}
public static void foo(String arg) { // More-specific
System.out.println("foo(String)");
}
public static void foo(Integer arg) { // More-specific
System.out.println("foo(Integer)");
}
public static void foo(Object arg) { // Generic
System.out.println("foo(Object)");
}
}
class Test
{
void bar(Test test)
{
Object testVal = null;
test.foo(testVal); // dispatched to foo(Object)
test.foo(null); // compilation problem -> "The method foo(String) is ambiguous"
}
public void foo(String arg) { // More-specific
System.out.println("foo(String)");
}
public void foo(Object arg) { // Generic
System.out.println("foo(Object)");
}
}
Porque la segunda invocación comentada con nulo es ambigua para el compilador. El nulo literal podría ser una cadena o un objeto. Mientras que el valor asignado tiene un tipo definido. Necesita eliminar el nulo, por ejemplo, test.foo ((String) null) para eliminar la ambigüedad.