¿Cómo hacer la sobrecarga de métodos para un argumento nulo?

6 minutos de lectura

Avatar de usuario de Phani
fani

He añadido tres métodos con parámetros:

public static  void doSomething(Object obj) {
    System.out.println("Object called");
}

public static  void doSomething(char[] obj) {
    System.out.println("Array called");
}

public static  void doSomething(Integer obj) {
    System.out.println("Integer called");
}

cuando estoy llamando doSomething(null) entonces el compilador arroja un error como métodos ambiguos. Así es el problema porque Integer y char[] métodos o Integer y Object ¿métodos?

  • Solo cambia el Integer a int.

    – Mudassir

    8 de marzo de 2011 a las 7:59

  • @Mudassir: ¿y qué resolvería eso exactamente?

    – Joaquín Sauer

    8 de marzo de 2011 a las 8:02

  • @Joachim Sauer: si se cambia de Integer a int, entonces nulo no se refiere a tipos primitivos en Java, por lo que el compilador no arrojará un error.

    – Fani

    8 de marzo de 2011 a las 8:05

  • @Joachim Sauer: No arrojará la reference to doSomething is ambiguous error.

    – Mudassir

    8 de marzo de 2011 a las 8:09

Avatar de usuario de Joachim Sauer
Joaquín Sauer

Java siempre intentará usar la versión aplicable más específica de un método que esté disponible (ver JLS §15.12.2).

Object, char[] y Integer todos pueden tomar null como un valor válido. Por lo tanto, las 3 versiones son aplicables, por lo que Java tendrá que encontrar la más específica.

Ya que Object es el supertipo de char[]la versión de la matriz es más específica que la Object-versión. Entonces, si solo existen esos dos métodos, el char[] se elegirá la versión.

Cuando tanto el char[] y Integer hay versiones disponibles, entonces ambas cosas de ellos son más específicos que Object pero ninguno es más específico que el otro, por lo que Java no puede decidir a cuál llamar. En este caso, deberá mencionar explícitamente a cuál desea llamar emitiendo el argumento al tipo apropiado.

Tenga en cuenta que, en la práctica, este problema ocurre con mucha menos frecuencia de lo que uno podría pensar. La razón de esto es que solo sucede cuando estás llamando explícitamente a un método con null o con una variable de un tipo poco específico (como Object).

Por el contrario, la siguiente invocación sería perfectamente inequívoca:

char[] x = null;
doSomething(x);

Aunque sigues pasando el valor nullJava sabe exactamente qué método llamar, ya que tendrá en cuenta el tipo de variable.

  • Esto se indica para Java 7. ¿Eso también se aplica a las versiones anteriores de Java? Quiero decir: si tiene varias firmas de métodos con parámetros solo a lo largo de una jerarquía de tipos, ¿entonces está en el lado de guardar con nulo como valor real? Y si ha creado una “jerarquía para” como en el ejemplo aquí, ¿entonces no lo es?

    – Christian Gosh

    13 de febrero de 2015 a las 12:29

  • Estoy bastante seguro de que esas reglas son las mismas para al menos todo desde Java 1.1 (excepto por la adición de genéricos, obviamente).

    – Joaquín Sauer

    13 de febrero de 2015 a las 15:04

  • ¿Significa esto que si el compilador tuviera que elegir entre doSomething(String str) y doSomething(Object obj) durante el tiempo de ejecución con doSomething(null), se llamará a doSomething(String str).

    – Sameer

    10 de noviembre de 2016 a las 9:22

avatar de usuario de jmg
jmg

Cada par de estos tres métodos es ambiguo por sí mismo cuando se llama con un null argumento. Porque cada tipo de parámetro es un tipo de referencia.

Las siguientes son las tres formas de llamar a uno de sus métodos específicos con nulo.

doSomething( (Object) null);
doSomething( (Integer) null);
doSomething( (char[]) null);

¿Puedo sugerir eliminar esta ambigüedad si realmente planea llamar a estos métodos con null argumentos Tal diseño invita a errores en el futuro.

  • Solamente Integerchar[] pair es ambiguo, porque en otros dos casos, el compilador de Java puede elegir la opción más específica, como describió @JoachimSauer.

    – kajacx

    11 de agosto de 2015 a las 6:54

  • @kajacx: ​​la pregunta original de OP era llamar a estos métodos con null como parámetro. Bajo esa condición previa, los tres pares son ambiguos. Para el caso general, estoy de acuerdo en que solo Integer - char[] el par es ambiguo.

    – jmg

    15 de septiembre de 2015 a las 5:51

  • qué pasa doSomething(null) por public static void doSomething(String str) { System.out.println("String called"); } Esto devolverá la cadena llamada.

    – Sameer

    7 de noviembre de 2016 a las 15:13


  • ¿Es posible usar una anotación como “anulable” o “no anulable” y configurar las declaraciones para que solo el método con el que desea obtener un nulo de modo que un argumento explícito “nulo” (pero de tipo nulo implícito) siempre seleccione sin ambigüedades? una sobrecarga especifica??

    – peterk

    18 de julio de 2017 a las 21:43

null es un valor válido para cualquiera de los tres tipos; por lo que el compilador no puede decidir qué función usar. Usa algo como doSomething((Object)null) o doSomething((Integer)null) en cambio.

  • Eliminé el método con el parámetro Integer, está invocando la función y devolviendo la salida como “Matriz llamada”entonces, ¿cuál es el contrato entre matriz y objeto?

    – Fani

    8 de marzo de 2011 a las 8:01

  • Las matrices de Java también son objetos.

    – Zds

    8 de marzo de 2011 a las 8:53

Cada clase en Java extiende la clase Object. Incluso la clase Integer también extiende Object. Por lo tanto, tanto Object como Integer se consideran instancias de Object. Entonces, cuando pasa nulo como parámetro, el compilador se confunde sobre qué método de objeto llamar, es decir, con el parámetro Objeto o el parámetro Integer, ya que ambos son objetos y su referencia puede ser nula. Pero las primitivas en Java no extienden Object.

Avatar de usuario de Jafar Ali
Jafar Alí

He intentado esto y cuando hay exactamente un par de métodos sobrecargados y uno de ellos tiene un objeto de tipo de parámetro, el compilador siempre seleccionará el método con un tipo más específico. Pero cuando hay más de un tipo específico, el compilador arroja un error de método ambiguo.

Dado que este es un evento de tiempo de compilación, esto solo puede suceder cuando uno intencionalmente pasa nulo a este método. Si esto se hace intencionalmente, es mejor sobrecargar este método nuevamente sin parámetros o crear otro método por completo.

avatar de usuario de nagarjuna chimakurthi
nagarjuna chimakurthi

class Sample{
  public static void main (String[] args) {
       Sample s = new Sample();
       s.printVal(null);

    } 
    public static void printVal(Object i){
        System.out.println("obj called "+i);
    }

    public static void printVal(Integer i){
        System.out.println("Int called "+i);
    }
}

La salida se llama Int nula y, por lo tanto, la ambigüedad es con char[] y entero

Avatar de usuario del Dr. Mido
doctor mido

Hay una ambigüedad debido a doSomething(char[] obj) y doSomething(Integer obj).

carbonizarse[] y Integer ambos son iguales superiores para nulo, por eso son ambiguos.

¿Ha sido útil esta solución?