W3docs

Sobrecarga de métodos en Java

Define múltiples métodos con el mismo nombre pero distintas listas de parámetros en Java para ofrecer APIs flexibles.

La sobrecarga de métodos consiste en declarar dos o más métodos en la misma clase con el mismo nombre pero diferentes listas de parámetros. El compilador decide cuál invocar según los tipos de argumentos que se pasan.

Ya habrás utilizado métodos sobrecargados sin darte cuenta. System.out.println(...) tiene versiones que aceptan un int, un double, un String, un Object, un char[], etcétera. Todos se comportan de forma similar — imprimen el valor y un salto de línea — pero la implementación varía según el tipo.

Qué significa "lista de parámetros diferente"

Dos sobrecargas deben diferir en la aridad (número de parámetros) o en los tipos de esos parámetros en orden. No basta con que difieran únicamente en:

  • Los nombres de los parámetros
  • El tipo de retorno
  • Si los parámetros son final
public static int square(int n) { return n * n; }

// VALID overloads — different parameter types
public static double square(double n) { return n * n; }
public static long   square(long   n) { return n * n; }

// VALID overload — different arity
public static int sum(int a, int b)             { return a + b; }
public static int sum(int a, int b, int c)      { return a + b + c; }

// INVALID — only the return type differs
// public static long square(int n) { return (long) n * n; }   // won't compile

Cómo elige Java una sobrecarga

Cuando escribes square(3), el compilador sigue este orden:

  1. Coincidencia exacta. ¿Existe una sobrecarga cuyos parámetros coincidan exactamente con los tipos de los argumentos? square(3)square(int). Listo.
  2. Ampliación. Si no, ¿pueden ampliarse los argumentos (p. ej., int → long, int → double)? Se elige la sobrecarga que requiere la menor ampliación.
  3. Autoboxing / unboxing. En caso contrario, se intenta envolver o desenvolver (int ↔ Integer).
  4. Varargs. Como último recurso, se recurre a una sobrecarga varargs (ver el capítulo sobre varargs).

Si dos sobrecargas empatan en el mismo paso, la llamada es ambigua y no compilará.

public static void show(int n)    { System.out.println("int: " + n); }
public static void show(long n)   { System.out.println("long: " + n); }
public static void show(double n) { System.out.println("double: " + n); }

show(3);     // exact match → int
show(3L);    // exact match → long
show(3.0);   // exact match → double
show((short) 3);   // widens short → int (closest), picks show(int)

Ambigüedad

Cuando el compilador no puede decidir entre dos sobrecargas igualmente válidas, se produce un error:

public static void f(int a, long b)  { /* ... */ }
public static void f(long a, int b)  { /* ... */ }

f(1, 2);   // ERROR: reference to f is ambiguous

Ambas sobrecargas requieren ampliar un argumento de int a long. Ninguna es "mejor". La solución es desambiguar en el punto de llamada mediante una conversión explícita — f(1, 2L) o f(1L, 2) — o añadir una tercera sobrecarga f(int, int) que gestione el caso de forma exacta.

Sobrecarga con tipos de objeto

Los tipos de referencia se sobrecargan de la misma forma, pero usando relaciones de subtipo en lugar de ampliación:

public static void log(Object o) { System.out.println("Object: " + o); }
public static void log(String s) { System.out.println("String: " + s); }

log("hello");        // exact match → String
log(42);             // autobox to Integer, then Integer is-a Object → log(Object)
log((Object) "hi");  // forces the Object overload

Si pasas un String y la única sobrecarga acepta Object, Java lo admite sin problema — String es un Object. Pero si existe una sobrecarga más específica, Java la preferirá.

Cuándo es útil la sobrecarga

El objetivo de la sobrecarga es ofrecer a los consumidores una API limpia y natural para cada tipo. Los dos patrones más frecuentes son:

Valores predeterminados. Una sobrecarga corta llama a la larga con valores sensatos por defecto:

public static void greet(String name) {
  greet(name, 1);                 // delegate
}

public static void greet(String name, int times) {
  for (int i = 0; i < times; i++) {
    System.out.println("Hello, " + name);
  }
}

Conversores de conveniencia. Distintos tipos de entrada, misma operación lógica:

public static int lengthOf(String s) { return s == null ? 0 : s.length(); }
public static int lengthOf(int[] xs) { return xs == null ? 0 : xs.length; }
public static int lengthOf(int n)    { return Integer.toString(n).length(); }

El llamador escribe lengthOf(x) sin preocuparse; el compilador enruta al cuerpo correcto.

Cuándo no sobrecargar

Si dos sobrecargas harían cosas sustancialmente diferentes, es mejor darles nombres distintos. El lector de format(x, y) no debería tener que buscar qué sobrecarga se eligió para entender el significado de la llamada. Las sobrecargas deben ser variaciones de la misma idea, no ideas distintas que comparten un nombre.

Sobrecarga vs. sobreescritura

Estos dos términos suenan similares pero resuelven problemas distintos, y confundirlos es la fuente de confusión más habitual.

  • La sobrecarga es mismo nombre, distintas listas de parámetros, dentro de una misma clase. El método que se ejecuta lo decide el compilador, fijándose únicamente en los tipos estáticos (declarados) de los argumentos. Esto se llama enlace estático (en tiempo de compilación).
  • La sobreescritura es mismo nombre, misma lista de parámetros, en una subclase — reemplaza un método heredado. El método que se ejecuta lo decide la JVM en tiempo de ejecución, basándose en el tipo real del objeto. Esto es el enlace dinámico (en tiempo de ejecución).
Object x = "hello";
log(x);   // calls log(Object), NOT log(String) — chosen from x's DECLARED type

Aunque x contiene un String en tiempo de ejecución, el compilador solo ve Object x, por lo que elige la sobrecarga de Object. La selección de sobrecarga nunca examina el tipo en tiempo de ejecución — esa es la función de la sobreescritura. Consulta sobreescritura de métodos para ver el lado dinámico.

Un ejemplo desarrollado

java— editable, runs on the server

Qué viene a continuación

La sobrecarga permite que un nombre apunte a varios métodos. A veces querrás que un único método se llame a sí mismo — resolviendo un problema al separar una pequeña parte y pidiéndole a una versión menor del mismo problema que se encargue del resto. Eso es la recursión.

Práctica

Práctica
¿Qué diferencia entre dos métodos NO es suficiente para que sean sobrecargas válidas?
¿Qué diferencia entre dos métodos NO es suficiente para que sean sobrecargas válidas?
Was this page helpful?