Jun 06

Tipado fuerte y débil, dinámico y estático.

error tipado de datosTodo esto del tipado en los lenguajes de programación es algo que más o menos creía tener claro y que seguramente es lo más básico de cualquier carrera de informática actual, pero yo ya tengo mis añitos, no he estudiado estas cosas y al buscar lenguajes para aprender, he visto que hay una sutil diferencia entre estático/dinámico y fuerte/débil. Vamos a ello.

Estático vs Dinámico

En un lenguaje con tipado estático, las variables llevan asociado el tipo de dato y no se puede cambiar. En los lenguajes de tipado dinámico, el tipo va más bien asociado al valor de la variable y no a la variable en sí misma, por lo que una misma variable puede contener a lo largo de la ejecución distintos tipos de datos.

Con tipado estático, es el mismo compilador el que comprueba que se asignan valores correctos a las variables, ya que sabe de qué tipo son las variables y qué tipo de valores pueden admitir. 

Con tipado dinámico, esta comprobación debe hacerse en tiempo de ejecución. Podemos meter en cualquier variable cualquier tipo de dato, por lo que hasta la ejecución no se sabe qué tipo de valor tiene una variable.

La ventaja del tipado estático es que se pueden evitar muchos errores en tiempo de compilación, sin necesidad de esperar a la ejecución para verlos. La ventaja del tipado dinámico es su flexibilidad.

Fuerte vs Débil

No parece haber un consenso claro de lo que es fuertemente tipado y débilmente tipado, pero parece que la idea más general es si el lenguaje permite cambiar unos tipos por otros de forma más o menos automática o no lo permite, salvo quizás de forma explícita. Me explico.

En javascript podemos hacer esto sin problemas

var a=3;
var b="4";
var c=a+b;

es decir, guardamos un entero en a, una cadena en b y luego las sumamos. Javascript, sin consultar con nadie, hace una conversión del entero 3 en cadena "3" y suma las cadenas, dando como resultado en c la cadena "34". 

En java, también podemos hacer algo parecido

int a = 3;
String b = "4";
String c = a+b;

dando como resultado una cadena "34"

Vemos que ambos lenguajes son débilmente tipados (entre comillas), pero java es estáticamente tipado ya que es necesario declarar los tipos de las variables, y javascript es dinámicamente tipado, ya que no es necesario.

La afirmación de que ambos son "débilmente tipados", hay que tomarla entre comillas. Javascript es más débilmente tipado porque siempre intenta hacer las conversiones necesarias para que el código se ejecute sin problemas, aunque a veces los resultados son sorprendentes. Java en este caso de sumar entero y String es débilmente tipado, pero solo para cositas muy concretas. Convierte tipos a String cuando lo necesita, pero poco más. Por ejemplo, en javascript todo esto es válido

if ("0"==0)  // es true
if ("0")  // es true
if ("") // es false
if ("3"==3) // es true

es decir, convierte String a integer para hacer las comparaciones, convierte "" en false en el tercer caso, etc, etc. Java daría error con cualquiera de estos if, por lo que no es tan débilmente tipado como javascript.

La ventaja de un lenguaje dinámicamente tipado es evidente, ahorra muchas conversiones explícitas que en algunos casos pueden ser muy tediosas. Sin embargo, la pega es que requiere un conocimiento profundo de cómo se hacen esas conversiones, o podemos encontrarnos con errores inesperados al realizarse alguna conversión que no esperamos.

May 30

Autocompletar en los IDE

autocompletar en javascriptPara trabajar siempre me gustan más los lenguajes estáticamente tipados que los dinámicamente tipados y entre otras ventajas, una de ellas es la de autocompletar de los IDE. Pero siempre que digo esto, alguien me comenta que si el IDE está correctamente configurado, los dinámicamente tipados también tienen autocompletar.

Bien, esto es cierto, pero sólo parcialmente. Imagina el siguiente trozo de código en un lenguaje estáticamente tipado, como java

public void metodo ( UnaClase parametro) {
   parametro.???
}

Cuando empezamos a teclear en la zona de ???, el IDE sabe que parámetro es de tipo UnaClase, porque se ve claramente, así que es perfectamente capaz de darnos los métodos y atributos públicos de parámetro para que elijamos uno.

Sin embargo, en un lenguaje dinámicamente tipado, si tenemos el código equivalente

function unaFuncion (parametro) {
   parametro.???
}

aquí el IDE no tiene ni idea de qué tipo es parámetro y de hecho, no puede saberlo, porque parámetro puede ser de cualquier tipo cuando el código se esté ejecutando, se puede llamar a unaFuncion() pasándole un entero, una cadena de texto, un objeto propio que hayamos creado o cualquier otro tipo que se nos ocurra. Así que el IDE aquí es totalmente incapaz de ofrecernos opciones, salvo que el lenguaje tenga algo común en todos sus tipos.

¿Cómo se apaña entonces para autocompletar?. Bien, un caso como el que acabamos de mostrar es imposible, pero los IDEs tienen sus trucos para ofrecernos opciones de autocompletar cuando es posible. Por ejemplo, en el caso anterior, si tenemos

function unaFuncion (parametro) {
   parametro.funcion1();
   parametro.funcion2();
   var a = parametro.atributo1;
   parametro.???
}

aquí el IDE ve qué cosas usamos de parámetro, así que cuando lleguemos a los ??? nos ofrecerá las funciones y atributos que ya hemos usado (funcion1, funcion2, atributo1), sean o no correctos y de hecho, pueden no ser correctos porque nos hemos equivocado al teclear o simplemente porque en tiempo de ejecución alguien nos pasa como parámetro algo que no tenga esas funciones ni atributos.

Otro truco usado por los IDE es el siguiente

function unaFuncion () {
   var b = new UnaClase()
   b.???
}

en este caso, se ve claramente qué contiene la variable b, aunque no tenga tipo definido, ya que estamos haciendo un new de una clase concreta y metiéndola en la variable. Si el IDE es capaz de encontrar en nuestro código la definición de UnaClase, será capaz de ofrecernos sus métodos/funciones y atributos … es justo el caso de la imagen.

Así que sí, los IDE pueden autocompletar en lenguajes dinámicamente tipados, pero con ciertas limitaciones.

May 23

Cuidado al sincronizar Boolean

 Depurando código de otra persona, encontré que hacía synchronized(variable) siendo variable un Boolean con mayúscula. Me llamó la atención de que dentro del bloque synchronized cambiaba el valor de la variable, algo así

synchronized(variable) {
   …
   variable = false;
   …
}

Me sonaba mal. Eso de cambiar la variable con la que estás sincronizando no parece limpio. Si otro hilo intenta sincronizar con la variable, puede estar sincronizando con otro objeto distinto y la idea no suele ser esa. De todas formas, decidí hacer una búsqueda en google y me encontré con esta pequeña joya de por qué no debemos sincronizar con Boolean.

Por un lado menciona lo que acabo de comentar, no es buena idea cambiar dentro (ni en general en ningún lado), el objeto sobre el que se está sincronizando. Si lo cambiamos, nunca tendremos garantía de que los hilos estén sincronizando sobre el mismo objeto, que es el objetivo de un synchronized. El objeto debe ser fijo. El enlace da varias alternativas correctas, como crear un Object lock = new Object() fijo para sincronizar con él o ver si nos valdría un AtomicBoolean con el que no tendríamos que sincronizar 

Sin embargo, lo que realmente me ha llamado la atención, es el comentario de que el Boolean es además especialmente problemático. Cuando hacemos esto

Boolean variable = false;

Java hace una conversión automática de false a Boolean.FALSE, ya que la variable es Boolean con mayúscula. Y java es listo, así que no crea instancias de Boolean.FALSE según hacen falta, sino que siempre reutiliza un mismo Boolean.FALSE. Y ahí viene el problema. ¿Qué pasa si sincronizamos dos grupos de hilos que son independientes cada uno con una variable Boolean que no tiene que ver con la otra?. Pues que podemos tener problemas porque sólo hay un objeto en todo java Boolean.TRUE y solo uno Boolean.FALSE, así que esos hilos que no tienen nada que ver están en realidad sincronizándose sobre el mismo objeto. En el siguiente código

// Hilo 1
Boolean unaVariable = true;
synchronized (unaVariable) {
   …
}

// Hilo 2 que no tiene nada que ver con Hilo 1
Boolean otraVariableQueNoTieneNadaQueVerConUnaVariable = true;
synchronized (otraVariableQueNoTieneNadaQueVerConUnaVariable) {
   …
}

hay dos hilos que no tienen que ver el uno con el otro y usan variables que no tienen que ver la  una con la otra….. están sicronizándose sobre el mismo y único objeto Boolean.TRUE que hay en java. Como mínimo, es una espera inútil. En el peor de los casos, puede dar lugar a abrazos mortales.

 

May 01

Jugueteando con Scala

Tras el último post "Eligiendo lenguaje … ¿Scala?" me he puesto manos a la obra. Estoy leyendo el libro "Programming Scala" de la foto y, naturalmente, jugueteando con el IDE para Scala.

En una semana de leer y juguetear en tiempos libres, por supuesto, no he avanzado mucho, pero lo que estoy viendo me gusta bastante.

El compilador de Scala genera ficheros .class compatibles con la máquina virtual java y por tanto, es posible usar librerías compiladas con java (.jar) en Scala y es posible generar librerías (.jar) con Scala para usar en java. A mí, como programador Java, esto me facilita enormemente la vida, porque puedo introducir parcialmente Scala en mis proyectos. No, no mezclar en un mismo proyecto fuentes Java y fuentes Scala, porque no me parece elegante, pero sí crear librerías Scala que utilizaré en mis proyectos Java o viceversa.

En cuanto a la sintaxis de Scala, me da la impresión de que trata de resolver muchos de los problemas que tiene la sintaxis de Java. Aparte de ser menos verboso que Java, yo creo que lo más importante es que permite hacer cosas que Java no permite de forma fácil o simplemente no permite. Hay muchos detalles y todavía no he terminado el libro, menciono sólo algunos.

En Java la estructura de directorios tiene que coincidir con la de paquetes. En Scala no es necesario para los fuentes, aunque los .class que genera sí lo necesitan por compatibilidad. ¿Esto contribuye a desorganizar el código?. Depende de nosotros, pero de mano elimina la necesidad de crear los directorios habituales correspondientes al "dominio". Quiero decir, en mi caso todas mis clase están en el paquete "com.chuidiang" y eso en Java me obliga a meter los fuentes en un directorio "chuidiang" debajo de un directorio "com". Dos directorios "inútiles" que en Scala me puedo cepillar sin problemas.

En Java hay public, protected y private con características determinadas. En Scala se amplían estas posibilidades, ya que se permiten poner cosas como private[package] que haría el atributo/método visible no solo para la clase que lo contiene, sino para cualquier clase en el paquete, o cosas como private[this] que hace que el atributo/método sólo sea visible para esa clase, y no como en Java, que también sería visible para las clases anónimas o internas declaradas dentro de esa clase.

En Scala basta declarar una clase poniéndole parámetros en la declaración. Esto crea automáticamente el constructor con esos parámetros, los atributos privados para esos parámetros y los setter y getter (aunque sin seguir la convención java de setParametro() y getParametro()) correspondientes para esos parámetros. Desde luego, mucho menos código que en java

class Point (x:Int, y:Int) {
   // No es necesario declarar atributos x,y ni sus setter y getter
   // Scala lo hace automáticamente
   …
}

Y todo esto no dejan de ser pequeños detalles, Hay otras características muy interesantes. Por ejemplo, el switch-case en Java está bastante limitado, sólo sabe de tipos primitivos (int, char, etc), enumerados y de clases que están asociadas a estos tipos (Char, Integer, …). En los case, además, sólo se pueden poner valores constantes. El equivalente en Scala al switch-case es match, que es como el switch-case, pero a lo bestia. En el match podemos poner cualquier tipo de variable, incluidas colecciones. En los case se ponen "expresiones" predefinidas pero muy potentes. Pueden ver si la variable del "match" es de un tipo u otro, si es una colección con n elementos, si el elemento número 3 es un elemento concreto, etc, etc. Los programadores Java muchas veces hemos tenido que liarnos a if-elseif porque switch-case no es lo suficientemente potente. Otro detalle interesante de match es que devuelve un valor, el que devuelva el case correspondiente.

Otro punto muy interesante de Scala son los "trait". Un "trait" no es más que una clase que se puede añadir como "pegote" a otra clase

class UnaClase extends UnPadre with UnTrait {

}

Podemos poner varios with con varios trait en la definición de la clase, con lo que la clase tendrá como "pegotes" los métodos y atributos de los traits. No es una herencia, puesto que en la clase no haríamos llamadas estilo super.metodoDelTrait(), sino que simplemente podemos llamar a metodoDelTrait() como si fuera un método de nuestra propia clase. Esto es realmente útil y un ejemplo muy claro con el que estoy harto de tropezarme es el siguiente : Patrón Observador. Hago clases Java que tiene suscriptores a eventos que pasan dentro de esa clase. En todas esas clases tengo que poner un atributo con la lista de observadores, método addObserver(), removeObserver() y fireEvent() para avisar a los observadores. No puedo meter ese código en una clase y heredar de él porque Java no admite herencia múltiple y a veces necesito que esa clase herede de otra cosa. Ayuda algo meter esa clase que mantiene la lista de observadores como un atributo de mi clase principal, así en mi clase principal sólo debería añadir métodos addObserver() y removeObserver() que llamen a los del atributo. Pero la solución del trait es la ideal. Me basta con añadir with Observers en la declaración de mi clase para tener todo listo. Por supuesto, los trait pueden ser genéricos, de forma que la interface del observador puede ser la que queramos en cada caso, en el siguiente ejemplo, esa interface sería ButtonListener

class UnaClase extends UnPadre with Observers[ButtonListener] {

Otro detalle curioso e interesante. Si una clase tiene un método con un parámetro, en la sintaxis no es obligatorio poner el punto para llamar al método ni los paréntesis para poner el parámetro. Eligiendo adecuadamente los nombres, podemos "acercarnos" mucho a un lenguaje natural. Por ejemplo, serían equivalentes cosas como

if ( unaVariable.is(7) ) {
   …
}

if ( unaVariable is 7 ) {
   …
}

Si además ese método en vez de un boolean como en el ejemplo, devuelve otra clase que a su vez tiene un método con un parámetro, podemos encadenar llamadas y así, no es raro ver en las suite de test de Scala (similares a JUnit), cosas como 

"An empty collection" should "have size 0" in ….

En fin, sigo en ello, pero de momento es un lenguaje interesante donde los haya, con muchas posibilidades, tanto "anecdóticas" en el sentido de que sólo facilitan no escribir tanto, como de "ampliación" de lo que no es fácil o posible en Java.

Apr 25

Buscando lenguaje … ¿Scala?

scala programming language Llevo muchos años trabajando con java y llevo ya un tiempo pensando que va siendo de comenzar a aprender algún lenguaje de programación  nuevo. He jugueteado algo con python, también con groovy, trabajo con javascript con cierta frecuencia, le he echado un ojo por encima a ruby … pero son lenguajes que no me acaban de convencer.  ¿El motivo? Que no son lenguajes estáticamente tipados. Eso hace que los IDEs sean bastante deficientes a la hora de autocompletar lo que estás escribiendo, que puedas cometer errores de tecleo en las variables o métodos y no los descubras hasta tiempo de ejecución.

Dicen que son menos verbosos que java y que eso ahorra tiempo, pero tengo serias dudas si el tiempo que ahorras en escribir código no lo pierdes luego corrigiendo errores tontos de tecleo arrancando una y otra vez tu programa para descubrirlos en tiempo de ejecución. Sobre todo si el programa es un programa grande que requiera todo un montaje para arrancarlo y llegar a la zona de código que quieres probar. Sí, se que existen cosas como los test unitarios, pero también tendrías los mismos problemas de tecleo al escribir test unitarios y también sé que hay cosas que son muy difíciles de probar con test unitarios.

Por la curiosidad de aprender el lenguaje sí. Javascript, que pensaba antes de conocerlo que era un lenguaje "tonto",  me ha asombrado con sus cosas y su potencia. Entiendo que groovy, ruby, python también lo son, al menos en lo poco que he visto. Pero forma parte de mi objetivo, aparte de satisfacer mi propia curiosidad por el lenguaje, el poder darle luego una utilidad práctica en el trabajo, y la experiencia de trabajar en javascript me hace ver lo importante que es usar un lenguaje estáticamente tipado.

Ayer leí Why should I learn Scala, y creo que me ha decidido a darle una oportunidad a Scala.

Es un lenguaje del que se oye bastante últimamente y que ves que se está usando. En mis proyectos maven, cuando uso plugins o librerías de terceros, veo que rápidamente van bajándose plugins de scala y que lo usan, aunque sea por debajo. Además, es compatible con java en el sentido de que genera código compilado para la máquina virtual java, por lo que podría integrarlo fácilmente en nuestros proyectos. Sé que queda feo mezclar unos módulos en java y otros en Scala, pero es una opción para que el cambio no sea brusco.

El artículo además apoya (o al menos da importancia) mi punto de vista de la necesidad de lenguajes estáticamente tipados. Siempre es mejor encontrar errores mientras se escribe en el IDE o mientras se compila, que encontrarlos a base de probar en tiempo de ejecución.

Y el artículo además menciona un pequeño detalle con el que también tengo manía: Los setter y getter. Aunque no recuerdo dónde lo leí, decían que una ventaja de groovy era que no era necesario poner setter y getter, ya que el lenguaje los generaba automáticamente y los usaba por debajo. Pero los setter y getter tienen un motivo de existir y no son sólo para que estén. Es importante poder meter lógica más adelante en el setter o en el getter, o incluso mantenerlos tal cual aunque el atributo al que referencian cambie de tipo y/o nombre. Y parece que scala tiene contemplado ese caso. Aunque no sea necesario poner getter y setter, si es posible añadir lógica cuando se asigna un atributo e, imagino, que también cuando se lee.

Así que ayer me bajé un IDE de scala y voy a juguetear unos días a ver qué tal.

Jul 13

Seguir las reglas a ciegas

Veo esta duda en StackOverflow en la que preguntan si hay alguna forma de que los getter y setter en java se puedan generar automáticamente desde código, igual que muestra cómo se hace en Javascript. Mirando las respuestas, se llega por ejemplo a proyectos como Project Lombok, en el que poniendo anotaciones @Getter y @Setter en el atributo, los genera automáticamente.

Si vamos un poco más allá, también el lenguaje Groovy hace automáticamente estas cosas, pone en los bytecodes compilados métodos getter y setter para los atributos, de forma que podemos usarlos desde otros lenguajes como java.

Maravilloso, todos sabemos que hacer los atributos privados y poner setter y getter es una de las buenas costumbres de programación y es pecado no hacerlo, así que todas estas maravillosas herramientas lo hacen AUTOMATICAMENTE por nosotros, ahorrándonos escribir el tedioso código.

Pero creo que nos olvidamos del fondo. ¿Por qué es bueno hacer los atributos privados y poner getter y setter?. La respuesta todos la sabemos: encapsulación. Pero, ¿nos hemos parado a pensar realmente qué es eso?

Imagina un atributo privado "chisme" con su correspondiente getter y setter

private double chisme;
public void setChisme(double chisme) {
   this.chisme=chisme;
}
public double getChisme() {
   return this.chisme;
}

La ventaja de la encapsulación es que si más adelante decido que en vez "chismes" tengo "trvilorios" (todos sabemos que los "chismes" y los "trivilorios" son equivalentes y podemos obtener unos de otros) y que en vez de double, es un BigDecimal, podemos hacer esto

private BigDecimal trivilorio;
public void setChisme(double chisme) {
   this.trivilorio = getTrivilorioAPartirDeChisme(chisme);
}
public double getChisme() {
   return getChismeAPartirDeTrivilorio(this.trivilorio);
}

Y esta es la verdadera ventaja, hemos cambiado el atributo, pero mantenemos los setter y getter de chisme, haciendo las cuentas necesarias en esos métodos. De esta forma, todo el código que use nuestra clase seguirá usando setChisme() y getChisme() y seguirá trabajando con chismes y no con tirvilorios, no necesitamos cambiar nada, posiblemente ni siquiera recompilar ese otro código,  y todo seguirá funcionando.

Pero si usamos maravillosas herramientas que generan automáticamente los getter y setter, perdemos el encapsulamiento, que es precisamente el único motivo de la existencia de esos setter y getter. En el momento que cambie "chisme" por "trivilorio", aparecerán automáticamente getTrivilorio() y setTrivilorio(), pero desaparecerán, también automáticamente, getChisme() y setChisme(), por lo que todo el código que hay por ahí usando setChisme() y getChisme() se debe rehacer, recompilar…. y posiblemente hacer las conversiones de chisme a trivilorio y viceversa, o bien tocar el código que usaba chismes y ahora tiene que usar trivilorios.

Así que ojo con estas herramientas. Si queremos que el código que usa nuestra clase no tenga que cambiar y usamos estas herramientas, después de cambiar chisme  por trivilorio, debemos escribir manualmente los métodos getChisme() y setChisme() con su correspondiente conversión, manteniendo así la compatibilidad y la encapsulación. Por supuesto, setTrivilorio() y getTrivilorio() pueden y deben añadirse, automática o manualmente.

Mar 29

He leído “JavaScript, The Definitive Guide”

Hace un mes aproximadamente terminé de leer "JavaScript, The Definitive Guide". Un libro sobre JavaScript y alrededores que me ha encantado. Aparte de JavaScript, trata bastante bien temas como JavaScript en un navegador web, una introducción a node.js y rhino en el lado del servidor, AJAX, jQuery, almacenamiento local en el navegador, Canvas de HTML5, …

Son un montón de páginas, 1100 nada menos, pero aproximadamente la segunda mitad son una guía de referencia de las funciones de JavaScript, por lo que de lectura es aproximadamente la mitad.

Comienza con los principios de programación en JavaScript desde cero, el típica capítulo de introducción al lenguaje que no aporta demasiado a casi nadie, demasiado rápido para el que no sabe nada de programación, pero demasiado trivial para el que sabe programar en otros lenguajes. Aun así, dentro de esta parte, he encontrado una pequeña joya para alguien como yo acostumbrado a otros lenguajes y es todo el tema de cómo se hacen conversiones de tipos automáticas, sobre todo en los condicionales, es decir, cuándo una variable independientemente de su tipo (string, numérico, un objeto,…) se considera que es true o false.

Sin embargo, luego empieza a meterse en profundidad en montones de temas variados de JavaScript y aquí es donde algún programador experto en otro lenguaje pero sin demasiado conocimiento de JavaScript, empieza a disfrutar del libro. Por supuesto, hay temas demasiado farragosos como para que sea agradable leerlos, pero hay otros que me han parecido geniales, tanto por lo que supone aprender cosas que no sabes, como por la forma de exponerlas.

Entre los primeros, los farragosos, está la parte de orientación a objetos en JavaScript, clases, herencias, polimorfismo a base de tipado tipo pato, También la parte de eventos en los navegadores web es pesadita, más que nada porque cada navegador es de su padre y de su madre y no hay acuerdo en los eventos que se producen, cómo se llaman y cuándo se producen. El libro no puede hacer mucho más que dar una lista con una breve descricpción de cada uno de ellos.

Sin embargo, entre las partes geniales, me ha encantado la forma de explicar las expresiones regulares, tanto, que he hecho mi propio tutorial de expresiones regulares en JavaScript siguiendo esa forma de explicación, por supuesto, donde esté el libro que se quite cualquier tontería que haya podido hacer yo. También me ha encantado la forma de explicar jQuery, todos sus apartados, desde los selectores para buscar y modificar elementos de nuestro HTML, como la parte de AJAX, efectos especiales como fadeIn() y fadeOut(), …

En fin, totalmente recomendado para aquel que ya ha empezado a programar cosas en JavaScript pero necesita profundizar y comprender más el tema.

Jan 09

“Duck Typing”

En un lenguaje fuertemente tipado y orientado a objetos, se comprueban las clases de los objetos antes de asignarlos a variables, de forma que sólo se pueden asignar a una variable objetos que son de la misma clase que la variable o hijas de la misma. Por ejemplo, si la clase Hija herada de la clase Padre, se puede hacer esto

Padre p = new Hija();

Una vez hecho, sólo pueden llamarse a métodos o atributos que estén declarados en la clase Padre. Si Padre tiene metodo1() e hija tiene metodo2(), sólo podemos hacer p.metodo1(), mientras que p.metodo2() dará error. Todo esto da sentido a cosas como las interfaces, definiendo a priori que métodos necesitan tener las clases hijas para que luego estas lo implementen.

Hay otros lenguajes, como javascript, que usan lo que se llama "Duck typing" o como lo traduzco yo "tipado tipo pato". La idea básica de este tipado es que si algo anda como un pato, grazna como un pato y nada como un pato, pues entonces es un pato. Los lenguajes que usan este tipado no miran los tipos ni las herencias de los objetos, simplemente permiten asignar cualquier cosa a cualquier variable. De esta forma, podemos hacer

p = new Hija();

y luego llamar tranquilamente a p.metodo1() o p.metodo2(), pero también podemos hacer

p = new Padre();

y llamar a p.metodo1(), dando error p.metodo2(). Es decir, no importa el tipo, el error saltará a la hora de hacer la llamada si "el pato no es capaz de granzar".

 

Mar 16

google-gson para manejar json desde java

jsongoogle-gson es una pequeña librería java que nos permite convertir una clase java en un String con formato JSON y viceversa. Es útil si hacemos una aplicación web con java en el lado del servidor y usamos el formato JSON para enviar y recibir datos al navegador.

Un pequeño ejemplo, hagamos un par de clases java sencillitas, dos bean sin necesidad de métodos set y get, pero con un constructor sin parámetros. Una de ellas tiene como atributo, entre otros, a la otra clase.

class Dato {
   private double numero;
   private int array[];
   private String texto;
   private LinkedList<Boolean> lista;
   private DatoInterno dato;

   public String toString() {
      return texto + " " + numero + " " + Arrays.toString(array) + " "
        + Arrays.toString(lista.toArray()) + " " + dato;
   }
}

class DatoInterno {
   private float valor;

   public String toString() {
      return "" + valor;
   }
}
 

Le hemos puesto unos métodos toString() para ver por pantalla fácilmente su contenido

Una vez instalada la librería en nuestro proyecto (es un solo jar), podemos hacer un código como este

Gson gson = new Gson();

Dato dato = gson.fromJson("{numero:1.4,texto:dos,array:[1,2,3,4],lista:[true,false],dato:{valor:11.22}}",
        Dato.class);
System.out.println(dato.toString());

 

que da de resultado algo como esto

dos 1.4 [1, 2, 3, 4] [true, false] 11.22

es decir, la salida de nuestro System.out.println() en el que hemos obtenido una clase dato rellena con los datos del texto json. Por otro lado, también tenemos la posibilidad inversa. Si una vez relleno el dato llamamos a

System.out.println(gson.toJson(dato));

obtendremos la siguiente salida

{"numero":1.4,"array":[1,2,3,4],"texto":"dos","lista":[true,false],"dato":{"valor":11.22}}

es decir, el texto JSON correspondiente a lo que tenemos dentro del dato, pero perfectamente formateado y no la "guarrería" que había puesto yo inicialmente en el código.

En fin, sencilla de usar y bastante potente.

 

Jan 17

Constantes en los beans y JSTL

A veces, en una aplicación web con JSTL nos vendría bien tener una constante definida en uno de los beans de java, estilo

public class UnaClase {
   public static final String UNA_CONSTANTE = "algo";
   …
}

y luego poder llamarla desde JSTL con algo como

<jsp:useBean id="bean" class="com.chuidiang.UnaClase"></jsp:useBean>

<c:out value="${bean.UNA_CONSTANTE}" />

Desgraciadamente, eso no funciona. JSTL presupone que UNA_CONSTANTE es un atributo del bean y va a convertir ese ${bean.UNA_CONSTANTE} en una llamada al método bean.getUNA_CONSTANTE() que no existe.

La solución es fácil, basta con crear un método getUNA_CONSTANTE() en el bean que devuelva el valor de la constante. Unicamente tenemos que tener en cuenta que ese método no puede ser static, puesto que si no JSTL tampoco lo llamará (por debajo, probablemente usa la introspección de java y no busca métodos estáticos). El bean quedaría así

public class UnaClase {
   public static final String UNA_CONSTANTE = "algo";

   public String getUNA_CONSTANTE () {
      return UnaClase.UNA_CONSTANTE;
   }

}

que sí funciona como esperamos.