... siempre traen problemas.
Ejemplo:
class Autoboxing
{
public void prueba()
{
Integer i = 4;
if (4 instanceof Integer)
System.out.println("Yes!");
else
System.out.println("No chango");
}
}
Error de compilacion:
[macpablo:~/tmp] pablo% javac Autoboxing.java
Autoboxing.java:7: unexpected type
found : int
required: reference
if (4 instanceof Integer)
^
1 error
Palabras clave: autoboxing, irregularidades, ortogonalidad
Comentarios
Ese es un problema!!!
Ya que no existe una forma armonica de utilizar el hecho de que en algunos casos es posible utilizar 4 para instanciar un objeto de la clase Integer y en otros contextos no se considera una instancia.....
una pregunta ingenua, como se hace para darle ese formato (como de un editor) a un texto que introduzcamos en el Ajayu? es que quiero colocar algunas cosas de programacion con Java3D pero me gustaria presentarlas en ese formato.
i no se usa sino para ilustrar que a veces 4 es Integer a veces es int, donde radica el problema.
Para escribir codigo: [ c o d e = l e n g u a j e ] y para cerrar [ / c o d e ]
Hay que escribir las etiquetas sin espacios.
Supongo que es lo mismo que cuando harías:
int i = 4;
double d = i; //acepta perfectamente
pero si te preguntarías: "¿4 es double?" la respuesta es "no, 4 es int".
La verdad es que el autoboxing de Java es bastante artificial y parece encajado "a la fuerza" en el lenguaje; pa mí el autoboxing de C# es muucho más natural y mejor implementado.
Aunque "fuera de tópico", todas las mejoras incluídas al Java desde la versión 5 (jdk1.5) son sólo eso, mejoras al lenguaje (lo que incluye tipos genéricos, tipos enumerados, anotaciones, autoboxing y las otras cosas que no me acuerdo ahorita) y no mejoras a la máquina virtual en sí. Por tanto, en Java:
ArrayList<int> list1;
ArrayList<Integer> list2;
ArrayList<Object> list3;
son exactamente lo mismo a nivel de bytecode, mientras que en C#, cada uno es un tipo diferente y un ArrayList<int> tiene mucho mejor rendimiento que un ArrayList<Integer> porque el primero no necesita instanciar ningún wrapper para almacenar los números enteros (es decir, la misma implementación del ArrayList<int> maneja int[] internamente).
esto si compila por que instanceof es un comparador de objetos pero por algun motivo los int no son tratados como objetos y el compilador te dice "oye quiero una referencia y me pasas un int, que pasa pues?"
class Autoboxing { public void prueba() { Integer i = (int)4; if (i instanceof Integer)/*(i instanceof int) esto no compila*/ System.out.println("Yes!"); else System.out.println("No chango"); } }Por supuesto, int es un tipo primitivo. Una excepción a la regla para ser un lenguaje orientado a objetos.
Un literal es de tipo sobrecargado ... a veces. Por ejemplo
float f = 4 + 0.5;da lo siguiente:
Entonces, ¿los literales son sobrecargados o no (si quieren llamarle autoconversión implícita)?
No se puede hacer parametrización de tipos primitivos
ArrayList<int> lista = .... => ERROREn su lugar:
ArrayList<Integer> lista = .... => ERRORTodos los tipos primitivos tienen sus equivalente en tipos de dato clase, y al parecer los literales no son totalmente sobrecargados. Lo correcto para el ejemplo del Dr. Pablo sería:
float f = 4 + 0.5f; //especificamos que 0.5 es un floatComo dice #7(willy), no se si esto sea una ventaja o una desventaja, habría que analizar...
Fue un error mio, decir que lo siguiente es un ERROR.
ArrayList<Integer> lista = ....Jeje... mil disculpas
y quieres instanciar un mugre punto en 3D haces
Point3f point3f = new Point3f(1.0, 1.0, 1.0);pero el compilador te dice "cannot find symbol constructor Point3f(double, double, double)"Y dices pero por que? si son numeros pequeños.
y entonces debes hacer
Point3f point3f = new Point3f(1f, 1f, 1f);o haciendo un horrible castingPoint3f point3f = new Point3f( (float)1, (float)1, (float)1);Pero porque? si es un Point3f es obvio que recibe floats no podian haber hecho un metodo para que haga la conversion internamente sin fregarnos a los programadores, me gustaria agarrar al que programo esto.#10, tienes toda la razón, pensé que funcionaba. De todas formas, me parece que no es nada consistente para el lenguaje proveer sólo genericidad en tipos de referencia y no en tipos primitivos.
#13, lo ideal hubiera sido que provean un constructor tipo:
Point3f(double x, double y, double z);
así llamar a
new Point(1, 1, 1);
new Point(1f, 2f, 3f);
ó new Point(1.0, 2.0, 3.0);
funcionarían igual (aunque tendrías una representación interna demasiado grande).
No lo veo como un gran inconveniente y seguramente está escrito en algún lugar cual es el orden para inferir el tipo de literales. Sino lo escribimos a groso modo:
En tipos de datos numéricos al parecer:
Nunca he tenido ni se me ha hecho problema diferenciar un double de un float. Ni aun viendo el ejemplo de mi Tocayo pienso que es algo por lo que deberíamos sacarnos los cabellos...
Quisiera resaltar algo, veo que estan cometiendo un error de programación y no es un error del lenguaje
Por ejemplo: (Tomando el ejemplo anterior)
Si el API dice new Point(double p1, double p2, double p3)
y tu le pasas new Point (3, 4, 5) -> 3, 4 ,5 son enteros es un error de programacion no del lenguaje
no existe una auto conversion de enteros a doubles se debe usar 3.0 , 4.0 y 5.0
Lo mismo con instanceof sus argumentos son objetos no primitivos, no existe una regla de autoboxing para int a object
Por que usar floats? para ahorar memoria y procesador pero se pierde exactitud si se tienen que hacer muchas operaciones.
# 15 no es un problema de entender o no entender cuando usar floats o doubles es un problema de elegancia (entiendase codigo legible) por ejemplo el siguiente segmento de codigo crea un tetraedro en base a la longitud de un lado, antes de usar los puntos hay que hacer un casting (osea el programador debe controlar mas aspectos no relacionados con el algoritmo) lo cual claramente no es una ventaja.
public static Shape3D crearTetraedro(float lado_, Appearance appearance) { Shape3D s3d_tetra_=new Shape3D(); s3d_tetra_.setUserData("Tetraedro:"+lado_); float alto_parcial = (float) Math.sqrt(3.0)/2*lado_; float alto_parcial_3 = alto_parcial / 3.0f; float alto_total = (float) Math.sqrt( 3*2*Math.pow(lado_,2) ) / 3.0f; float ycentro = 0.5f * alto_total; float zcentro = alto_parcial_3; Point3f p1 = new Point3f(-(float)(lado_/2), -ycentro, +zcentro); Point3f p2 = new Point3f((float)(lado_/2), -ycentro, +zcentro); Point3f p3 = new Point3f(0.0f, -ycentro, -alto_parcial + zcentro); Point3f p4 = new Point3f(0.0f, alto_total - ycentro, 0.0f); Point3f[] verts = {p1, p2, p4, // cara frontal p1, p4, p3, // cara atras izquierda p2, p3, p4, // cara atras derecha p1, p3, p2, // cara de abajo }; .................................................................Te evitarías hacer el casting si al constructor le pasas una expresión float y no una expresión que por defecto es double.
Point3f p1 = new Point3f(-lado_/2f, -ycentro, +zcentro);Point3f point3f = new Point3f(-lado_/Math.sqrt(2f), 1f, 1f);/*No compila*/ Point3f point3f = new Point3f((float)(lado_/Math.sqrt(2f)), 1f, 1f);/*Si compila*/No es correcto que haya una auto conversión de double a float, estás perdiendo precisión y eso puede generar un error.
Cuando se trata de operaciones matemáticas no es muy recomendable usar casting, deberías probar algo parecido a esto:
Double dLado=new Double(lado); Double result= dLado / Math.sqrt(2.0); // la división debe ser entre doubles Point3f point3f = new Point3f(result.floatValue(), 1.0f, 1.0f);En operaciones matemáticas es aconsejable que trabajes sobre un solo tipo de números
y el resultado final lo expreses recién en el tipo requerido, no forzar resultados intermedios porque perderás precisión