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:
- 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.
- 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
toObject
lugar de un-boxing, es decir,Integer
toint
. Y en su segundo fragmento, el ensanchamiento no puede ocurrir deInteger
aString
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