java overloading unboxing

Método de resolución de sobrecarga en java



overloading unboxing (5)

Esto es lo que sé sobre la resolución de sobrecarga en Java:

El proceso de compilación que intenta resolver la llamada al método a partir de definiciones de método sobrecargadas se denomina resolución de sobrecarga. Si el compilador no puede encontrar la coincidencia exacta, busca la coincidencia más cercana mediante el uso de actualizaciones (las descargas nunca se realizan).

Aquí hay una clase:

public class MyTest { public static void main(String[] args) { MyTest test = new MyTest(); Integer i = 9; test.TestOverLoad(i); } void TestOverLoad(int a){ System.out.println(8); } void TestOverLoad(Object a){ System.out.println(10); } }

Como se esperaba, el resultado es 10.

Sin embargo, si cambio ligeramente la definición de clase y cambio el segundo método sobrecargado.

public class MyTest { public static void main(String[] args) { MyTest test = new MyTest(); Integer i = 9; test.TestOverLoad(i); } void TestOverLoad(int a){ System.out.println(8); } void TestOverLoad(String a){ System.out.println(10); } }

La salida es 8.

Aquí estoy confundido. Si nunca se iba a usar el downcasting, ¿por qué se imprimió 8? ¿Por qué el compilador TestOverLoad método TestOverLoad que toma int como argumento que es un downcast de Integer a int ?


El compilador considerará no un downcast, sino una conversión de unboxing para la resolución de sobrecarga. Aquí, el Integer i se descomprimirá en un int éxito. El método de String no se considera porque un Integer no se puede ampliar a una String . La única sobrecarga posible es la que considera unboxing, por lo que se imprime 8 .

La razón por la que la salida del primer código es 10 es que el compilador considerará una conversión de referencia de ampliación ( Integer to Object ) sobre una conversión de unboxing.

La Sección 15.12.2 de la JLS , al considerar qué métodos son aplicables, establece:

  1. La primera fase (§15.12.2.2) realiza la resolución de sobrecarga sin permitir la conversión de boxeo o unboxing, o el uso de la invocación del método de aridad variable. Si no se encuentra ningún método aplicable durante esta fase, el procesamiento continúa a la segunda fase.

  1. La segunda fase (§15.12.2.3) realiza la resolución de sobrecarga mientras permite el boxeo y el desempaquetado [...]

En Java, la resolución de métodos en caso de sobrecarga de métodos se realiza con la siguiente prioridad:

1. Ampliación
2. Auto-boxeo
3. Var-args

El compilador de Java cree que ampliar un parámetro primitivo es más deseable que realizar una operación de boxeo automático.

En otras palabras, como el auto-boxeo se introdujo en Java 5, el compilador elige el estilo más antiguo ( ensanchamiento ) antes de elegir el estilo más nuevo ( auto-boxeo ), manteniendo el código existente más robusto. Lo mismo es con var-args .

En su primer fragmento de código, se produce un ensanchamiento de la variable de referencia, es decir, Integer to Object lugar de un-boxing, es decir, Integer to int . Y en su segundo fragmento, el ensanchamiento no puede ocurrir de Integer a String por lo que ocurre el desempaquetado.

Considere el siguiente programa que prueba todas las declaraciones anteriores:

class MethodOverloading { static void go(Long x) { System.out.print("Long "); } static void go(double x) { System.out.print("double "); } static void go(Double x) { System.out.print("Double "); } static void go(int x, int y) { System.out.print("int,int "); } static void go(byte... x) { System.out.print("byte... "); } static void go(Long x, Long y) { System.out.print("Long,Long "); } static void go(long... x) { System.out.print("long... "); } public static void main(String[] args) { byte b = 5; short s = 5; long l = 5; float f = 5.0f; // widening beats autoboxing go(b); go(s); go(l); go(f); // widening beats var-args go(b, b); // auto-boxing beats var-args go(l, l); } }

El resultado es:

double double double double int,int Long,Long

Solo como referencia, aquí está mi blog sobre la sobrecarga de métodos en Java .

PD: Mi respuesta es una versión modificada de un ejemplo dado en SCJP.


En realidad, en el segundo ejemplo, no se produce downcasting. Ocurrió lo siguiente:

1. El entero se desenvuelve / desempaqueta al tipo primitivo int .
2. Luego se llama al método TestOverLoad(int a) .

En el método principal, declaras Integer como -

Integer i = 9;

Luego llame -

test.TestOverLoad(i);

Mientras que, tienes 2 versiones sobrecargadas de TestOverLoad() -

TestOverLoad(int a); TestOverLoad(String a);

Aquí la segunda versión sobrecargada de TestOverLoad() toma una String argumento completamente diferente. Es por eso que Integer i está sin caja en un tipo primitivo int y luego se llama a la primera versión sobrecargada.


Todos los objetos en Java extienden la clase Object, incluida la clase Integer. Estas dos clases tienen la siguiente relación: Integer "es un objeto (n)" porque Integer extiende Object. En su primer ejemplo, se utiliza el método con el parámetro Object.

En el segundo ejemplo, no se encuentran métodos que acepten un número entero. En este caso, Java utiliza lo que se denomina auto-unboxing para resolver la clase de contenedor Integer en un int primitivo. Por lo tanto, se utiliza el método con el parámetro int.


ensanchamiento late boxeo, boxeo late var-args. En su ejemplo, el ensanchamiento no puede suceder, por lo que se aplica el boxeo y se desempaqueta Integer. Nada extraordinario