¿Por qué el autoboxing de Java no se extiende a las invocaciones de métodos de los tipos autoboxed?

StackOverflow https://stackoverflow.com/questions/4242

  •  08-06-2019
  •  | 
  •  

Pregunta

Quiero convertir una primitiva en una cadena y probé:

myInt.toString();

Esto falla con el error:

int cannot be dereferenced

Ahora entiendo que los primitivos no son tipos de referencia (es decir, no son un objeto) y por lo tanto no pueden tener métodos.Sin embargo, Java 5 introdujo el autoboxing y unboxing (al estilo C#...que nunca me gustó en C#, pero eso no viene al caso).Entonces, con el autoboxing, esperaría que lo anterior convierta myInt en un Integer y luego llame a toString() en eso.

Además, creo que C# permite dicha llamada, a menos que no lo recuerde correctamente.¿Es esto sólo una desafortunada deficiencia de la especificación de autoboxing/unboxing de Java, o hay una buena razón para ello?

¿Fue útil?

Solución

El autoboxing/unboxing de Java no llega al extremo de permitirle desreferenciar una primitiva, por lo que su compilador lo impide.Tu compilador todavía lo sabe myInt como primitivo.Hay un artículo sobre este tema en jcp.org.

El autoboxing es principalmente útil durante la asignación o el paso de parámetros, permitiéndole pasar una primitiva como un objeto (o viceversa) o asignar una primitiva a un objeto (o viceversa).

Desafortunadamente, tendrías que hacerlo así:(felicitaciones Patrick, cambié a tu camino)

Integer.toString(myInt);

Otros consejos

Lo mismo ocurre con lo que dijo Justin, pero deberías hacer esto en su lugar:

Integer.toString(myInt);

Ahorra una o dos asignaciones y es más legible.

Otra forma de hacerlo es utilizar:

String.valueOf(myInt);

Este método está sobrecargado para cada tipo primitivo y Object.De esta manera ni siquiera tendrás que pensar en el tipo que estás usando.Las implementaciones del método llamarán al método apropiado del tipo dado para usted, p.e. Integer.toString(myInt).

Ver http://java.sun.com/javase/6/docs/api/java/lang/String.html.

me parece una deficiencia de la especificación

Hay más deficiencias y este es un tema sutil.Controlar este afuera:

public class methodOverloading{
   public static void hello(Integer x){
      System.out.println("Integer");
   }

   public static void hello(long x){
      System.out.println("long");
   }

   public static void main(String[] args){
      int i = 5;
      hello(i);
   }
}

Aquí se imprimiría "largo" (no lo he comprobado yo mismo), porque el compilador elige ampliar en lugar de autoboxing.¡Tenga cuidado al usar autoboxing o no lo use en absoluto!

La sintaxis válida más cercana a su ejemplo es

((Integer) myInt).toString();

Cuando el compilador finaliza, eso equivale a

Integer.valueOf(myInt).toString();

Sin embargo, esto no funciona tan bien como el uso convencional, String.valueOf(myInt), porque, excepto en casos especiales, crea una nueva instancia de Integer y luego la descarta inmediatamente, lo que genera más basura innecesaria.(Se almacena en caché una pequeña gama de números enteros y se accede a ellos mediante un acceso de matriz). Quizás los diseñadores de lenguaje querían desalentar este uso por razones de rendimiento.

Editar:Le agradecería que los votantes negativos comentaran por qué esto no es útil.

En C#, los números enteros no son tipos de referencia ni tienen que estar encuadrados para que Encadenar() ser llamado.Ellos son Sin embargo, se consideran objetos en el Framework (como ValueType, por lo que tienen semántica de valor).En CLR, los métodos de las primitivas se llaman cargándolos "indirectamente" en la pila (ldind).

Como todo el mundo ha señalado, el autoboxing te permite simplificar algo de código, pero no puedes pretender que los primitivos sean tipos complejos.

También interesante: "autoboxing es un truco a nivel de compilador" en Java.El autoboxing es básicamente un extraño error agregado a Java.Verificar esta publicación para más detalles sobre lo extraño que es.

Sería útil si Java definiera ciertos métodos estáticos para operar en tipos primitivos e incorporara en el compilador algo de azúcar sintáctico para que

5.asInteger

sería equivalente a

some.magic.stuff.Integer.asInteger(5);

No creo que una característica de este tipo cause incompatibilidad con ningún código que se compile según las reglas actuales y ayudaría a reducir el desorden sintáctico en muchos casos.Si Java autoboxeara las primitivas que fueron desreferenciadas, la gente podría asumir que estaba asignando la sintaxis de desreferenciación a llamadas a métodos estáticos (que es efectivamente lo que sucede en .NET) y, por lo tanto, que las operaciones escritas en esa forma no serían más costosas de lo que serían. las invocaciones de métodos estáticos equivalentes.Agregar una nueva característica de lenguaje que alentaría a las personas a escribir código incorrecto (p. ej.primitivas desreferenciadas de boxeo automático) no parece una buena idea, aunque permitir métodos de estilo de desreferenciación podría serlo.

Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top