Tag : Java

Lo que no es Java

«Java != javascript»


Tips para Comparación de Cadenas en Java

Hay algunas consideraciones que debes tomar en cuenta a la hora hacer comparación de cadenas en Java. Te mostraremos algunos ejemplos. Puede parecer que algunas formas son correctas o incorrectas, pero si sabes como funcionan todas pueden ser útiles dependiendo de las circunstancias.

"cadena" == "cadena"
"cadena" == "cad" + "ena"
"cadena" == "-cadena".substring(1)
new String("cadena").equals("cadena")
new String("cadena") == new String("cadena")
"cadena".equals(variableCadena)

La siguiente expresión compara dos direcciones, el compilador se encarga de hacer que ambos objetos sean el mismo y por lo tanto tengan también la misma dirección.

"cadena" == "cadena"
Da como resultado true.  Porque el operador «==» compara direcciones.


Cuando se concatenan cadenas usando el operador «+» el compilador se encarga de la concatenación y la comparación que resulta es sobre la dirección de dos objetos que en realidad son el mismo, el resultado es igual al del ejemplo anterior.
"cadena" == "cad" + "ena"
La expresión devuelve true.  En tiempo de ejecución se trata del mismo objeto.
Cuando el método substring es usado se genera un objeto diferente (aunque tenga el mismo valor).
"cadena" == "-cadena".substring(1)
La expresión devuelve false.
No solo substring devuelve objetos diferentes, también se pueden obtener objetos diferentes (pero conteniendo los mismos caracteres) cuando la cadena proviene de una fuente externa como un archivo.

En la siguiente expresión el método equals compara el valor de dos objetos String.

new String("cadena").equals("cadena")
El resultado es true.
Sin embargo, no se trata de dos objetos con la misma dirección, si se comparan con el operador «==» el resultado es false.
new String("cadena") == "cadena"
Por la misma razón la siguiente expresión también devuelve false.
new String("cadena") == new String("cadena")

Una forma de comparar cadenas con variables y que evita que el riesgo de lanzar un NullPointerException si la variable a comparar es nula es de la siguiente forma:

"cadena".equals(variableCadena)

Donde el valor  de la variable variableCadena puede asignarse de otra sección de código, si su valor es null, la expresión devolverá false si el valor de la variable variableCadena es «cadena», devolverá true.

 


No importa

¡No importa si funciona en tu máquina! ¡No vamos a enviar tu máquina!


10 Consejos para programadores que empiezan

10 Consejos para programadores que empiezan.
  • Recuerda siempre lo que te enseñaron tus maestros.
  • No emplees nuevas tecnologías solo por que son nuevas.
  • Pero si debes probar nuevas técnicas y tecnologías.
  • Lee Mucho.
  • No acumules errores o malas prácticas de programación.
  • Comparte tu conocimiento.
  • Ten en cuenta la concurrencia.
  • Prueba tu código.
  • Cuídate.
  • Diviértete.

Los gurús y el trabajo en equipo

Sin duda, siempre existen personas brillantes que se distinguen por su buen sentido común, curiosidad y capacidad para resolver problemas difíciles. Pero siempre he sospechado que la imagen del gurú está sobrevalorada.

Algunas malas experiencias me dicen que esto podría ser así.  En cierta ocasión, durante el desarrollo de un proyecto mas o menos grande y en una demostración de capacidades, el líder del equipo, que se sabía muy bueno en el desarrollo de software (el gurú), comenzó a utilizar una serie de tecnologías y frameworks de moda para impresionar al cliente y al administrador de proyecto.  Como resultado, los que tenían menos experiencia comenzaron a sufrir con la curva de aprendizaje y se enfocaron mas a conocer las nuevas tecnologías que al modelo de negocio. El desarrollo se terminó con una aplicación robusta tecnológicamente, pero poco amigable para el cliente y por supuesto en mas tiempo del que se esperaba. Un pequeño desastre.

En otras ocasiones, me he topado con el típico personaje que es capaz de resolver problemas difíciles, pero que cuando tienes que dar mantenimiento a su código o simplemente necesitas usarlo, este te parece tan desordenado que te dan ganas de hacerlo de nuevo.

Otro de los riesgos de tener a una persona que tiene todo el dominio sobre cierta tecnología, herramienta o el conocimiento mas crítico de un proyecto, es que puede simplemente irse, con el todo su conocimiento.

Me agradan mas los equipos de trabajo donde los problemas difíciles o algunas decisiones tecnológicas se resuelven entre varios.

Los gurús se equivocan como cualquier otro.

Además, cuando te autoproclamas gurú, puedes quedarte solo a la hora de resolver problemas difíciles.  Creo que no hay necesidad de que esto sea así, porque el criterio para resolver un problema crítico se reduce al de una sola persona y no creo que esto sea muy conveniente.

Cuando alguien te hace una pregunta complicada sobre algún problema o error, es probable que ella misma tenga mas capacidad para responderla, ya que conoce mejor el contexto del problema.  Por lo que mas que tratar de dar una solución es mejor dar un punto de vista o pistas sobre como resolver el problema.

El protagonismo es algo que nos puede seducir a todos, pero yo me lo pensaría mucho antes de adoptar una postura de este tipo. Sobre todo cuando de lo que se trata es hacer mas agradable y profesional tu trabajo.  Desde luego no estoy diciendo que todos los gurús son malos, de hecho también he conocido a algunos muy buenos. Pero son los menos.

Un hábito que recomiendo a todos es que cuando encuentras la solución a un problema difícil, la comentes a tus demás compañeros. Esto permite tener una base de conocimiento colectiva y evita tener que investigar demasiado sobre un problema que ya se ha sido resuelto con anterioridad.

Tómate con calma eso de ser gurú, puedes serlo sin hacer alarde.  🙂


Suele pasar…


«Suele pasar»


Talento

«Para ser un buen programador, se requiere 3% de talento y 97% de esfuerzo para no distraerse con Internet»


10 de las Mejores Prácticas en Java

1.- Evitar la creación innecesaria de objetos, Lazy Initialitation

La creación de objetos en Java es una de las operaciones mas costosas en términos de uso de memoria e impacto en el performance.  Esto es evitable creando o inicializando objetos solo en el momento en que serán requeridos en el código.

1
2
3
4
5
6
7
8
9
10
11
12
public class Paises {
 
    private List paises;
 
    public List getPaises() {
        //se inicializa solo cuando es requerido
        if(null == paises) {
            paises = new ArrayList();
        }
        return paises;
    }
}



2.- Nunca hacer variables de instancia públicas

Hacer una variable de instancia pública puede ocasionar problemas en un programa.  Por ejemplo si tienes una clase MiCalendario. Esta clase contiene un arreglo de cadenas diasDeLaSemana.  Pero es una arreglo público y este puede ser accedido por cualquiera.  Tu asumes que este arreglo contiene siempre los 7 nombres de los días de la semana.  Alguien por error puede cambiar el valor e insertar un error!

1
2
3
4
5
6
7
8
public class MiCalendario {
 
    public String[] diasDeLaSemana =
        {"Domingo", "Lunes", "Martes", "Miércoles", "Jueves", "Viernes", "Sábado"};
 
    //mas código
 
}

La mejor práctica como mucho de ustedes saben, es definir siempre estas variables como privadas y crear los métodos accesores, “setters“ y “getters”

1
2
3
4
5
6
private String[] diasDeLaSemana =
    {"Domingo", "Lunes", "Martes", "Miercoles", "Jueves", "Sabado", "Domingo"};
 
public String[] getDiasDeLaSemana() {
    return diasDeLaSemana;
}

Pero escribir los métodos accesores no resuelve el problema del todo.  El arreglo sigue siendo accesible.  La mejor forma de hacerlo inmodificable es devolviendo un arreglo clonado en lugar del arreglo mismo.  Esto se logra modificando el método get de la siguiente forma.

1
2
3
public String[] getDiasDeLaSemana() {
    return diasDeLaSemana.clone();
}

3.- Trata siempre de minimizar la Mutabilidad de las clases

Hacer una clase inmutable es hacerla inmodificable.   La información de la clase se preservará durante el tiempo de vida de la clase.  Las clases inmutables son simples y fáciles de manejar.  Son “thread safe”.  Normalmente son los bloques que permiten formar otros objetos más grandes.

No obstante, crear objetos inmutables pueden golpear significativamente el rendimiento de una aplicación.  Así que elije cuidadosamente si quieres que una clase sea o no inmutable.  Trata siempre de tener clases pequeñas con el menor número de clases inmutables.

Para hacer una clase inmutable puedes definir sus constructor de forma privada y luego crear un método estático para inicializar al objeto y devolverlo.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
public class Empleado {
 
    private String primerNombre;
    private String segundoNombre;
 
    // constructor private default
    private Empleado (String primerNombre, String segundoNombre) {
        this. primerNombre = primerNombre;
        this. segundoNombre = segundoNombre;
    }
 
    public static Empleado valueOf (String primerNombre, String segundoNombre) {
        return new Empleado (primerNombre, segundoNombre);
    }
}

4.- Trata de usar más las Interfaces sobre las Clases Abstractas

No es posible la herencia múltiple en Java, pero definitivamente puedes implementar múltiples interfaces.  Esto hace que cambiar la implementación de una clase existente sea fácil y que puedas implementar una o mas interfaces en lugar de cambiar la jerarquía completa de la clase.

Pero si tu estás cien por ciento seguro de que métodos de una interface tendrás, entonces solo implementa esa interfaz.   Es bastante difícil agregar un nuevo método en una interfaz existente sin alterar todo el código que se está implementando.  Por el contrario un nuevo método puede ser fácilmente agregado en una clase abstracta sin alterar la funcionalidad existente.

5.- Limita siempre el alcance de una variable local

Las variables locales son grandiosas.  Pero algunas veces pueden insertar mas bugs durante el copiado y pegado de código viejo. Minimizar el alcance de una variable local hace que el código sea mas legible, menos propenso a errores  y mas mantenible.

Por lo tanto, debemos declarar variables justo antes de ser usadas.

Procura inicializar una variable desde su declaración.  Si eso no es posible asígnale el valor nulo.

6- Trata de usar librerías estándar en lugar de hacer las tuyas desde cero

Escribir código es divertido.  Pero no reinventes la rueda.  Es bastante recomendable usar librerías estándar que ya han sido probadas, debugeadas y usadas por otros.    Esto no sólo mejora la eficiencia de un programador sino que reduce las posibilidades de tener errores en el código.  Además, usar una librería estándar  hace al código mas legible y mantenible.

Por ejemplo Google tiene liberada la nueva librería Google Collections que puede ser usada para agregar mas funcionalidad a tu código.

7.- Siempre que sea posible trata de usar tipos primitivos en lugar de las clases Wrapper

Las clases Wrapper son buenas, pero también son lentas.  Los tipos primitivos son como clases, sin embargo las clases wrapper almacenan la información completa acerca de una clase.

Algunas veces un programador puede agregar un error en el código usando una wrapper por un descuido.  Por ejemplo:

1
2
3
4
5
6
7
8
int x = 10;
int y = 10;
 
Integer x1 = new Integer(10);
Integer y1 = new Integer(10);
 
System.out.println(x == y);
System.out.println(x1 == y1);

El primer System.out.println imprimirá true mientras que el segundo imprimirá false.  El problema cuando comparas dos clases wrapper es que no se puede usar el operador ==, porque en realidad se están comparando referencias y no sus valores actuales.

Además si estás usando una clase wrapper no debes olvidar inicializarla.  Porque el valor por default de las variables wrapper es null.

1
2
3
4
5
6
7
8
9
Boolean bandera = null;
 
        //más código
 
if(bandera == true) {
    System.out.println("Se establece el valor de bandera");
} else {
    System.out.println("No se establece el valor de bandera");
}

El código lanzará un NullPointerException cuando se trate de comparar con true y el valor sea nulo si en el código intermedio no fue inicializada.

8.- Usa los Strings con mucho cuidado

Usa siempre las cadenas con mucho cuidado en tu código.  Una simple concatenación de cadenas puede reducir el rendimiento de tu programa.  Por ejemplo si queremos concatenar cadenas usando el operador “+” en un ciclo for entonces todo el tiempo se estará creando un objeto String.  Esto afecta tanto a la memoria como al rendimiento.

Además en lugar de que instancies una objeto String no uses su constructor, sino que debes instanciarlo directamente. Por ejemplo:

1
2
3
4
5
//instanciación lenta
String lenta = new String("solo otro objeto string");
 
//instanciación rápida
String rapida = "solo otro objeto string";

9.- Siempre regresa colecciones vacías en lugar de nulas

No importa que tu método regrese una colección o un arreglo, siempre asegúrate de que cuando sea necesario se regrese vacío y no nulo, en aquellos casos en los que no contendrá elementos porque la lógica de tu programa lo requiera.  Esto te ahorrará un montón de tiempo cuando hagas pruebas para valores nulos.



10.- El copiado defensivo es salvador

El copiado defensivo hace que los objetos creados estén libres de la mutación.  Por ejemplo en el código siguiente tenemos definida la clase Estudiante la cual a su vez tiene una variable con la fecha de nacimiento que es inicializada cuando el objeto es construido.

1
2
3
4
5
6
7
8
9
10
11
public class Estudiante {
    private Date fechaNacimiento;
 
    public Estudiante(Date fechaNacimiento) {
        this. fechaNacimiento = fechaNacimiento;
    }
 
    public Date getFechaNacimiento () {
        return this.fechaNacimiento;
    }
}

Ahora podríamos tener el siguiente código que use al objeto Estudiante.

1
2
3
4
5
6
public static void main(String []arg) {
    Date fechaNacimiento = new Date();    
    Estudiante estudiante = new Student(fechaNacimiento);
    fechaNacimiento.setYear(2019);
    System.out.println(estudiante.getFechaNacimiento ());
}

En el código siguiente creamos tan solo al objeto Estudiante con algunas fechas de nacimiento por default.  Pero entonces cambiamos el valor del año de nacimiento.  Después imprimimos el año de nacimiento, este año fue cambiado por 2019!

Para evitar estos casos, se puede utilizar el mecanismo defensivo copias. Cambie el constructor de la clase del estudiante a lo siguiente.

1
2
3
public Estudiante(Date fechaNacimiento) {
    this.fechaNacimiento = new Date(fechaNacimiento);
}

Esto para asegurarnos de tener otra copia de la fecha de nacimiento que usamos en clase Estudiante.

11.-  Nunca dejes salir una excepción de un bloque finally

12.- Nunca lances «Exception» directamente.

tomado de: http://viralpatel.net


Depuración


Una carrera con el Universo