Home » java
Calcula la diferencia de días entre dos fechas

Calcula la diferencia de días entre dos fechas
/**
* Se calcula la diferencia de días entre dos fechas.
* @param primerFecha que se va a calcular
* @param segundaFecha que se va a calcular
* @return número de días de diferencia entre fechas
*/
private BigDecimal calcularDiferenciaFechas(final Calendar primerFecha,
final Calendar segundaFecha) {
BigDecimal diferencia = BigDecimal.ZERO;
diferencia = new BigDecimal((primerFecha.getTimeInMillis()
- segundaFecha.getTimeInMillis()) / MILISEGUNDOS_DIAS);
return diferencia;
}

Clonar Objetos en Java

Clonar Objetos en Java
La clonación es el proceso de duplicación de un objeto para que en memoria existan dos objetos idénticos en el mismo instante de tiempo. Usualmente el objeto se clona directamente llamando al método:cualquierObjeto.cualquierMetodo(miObjetoImportante.clone());

Al igual que en muchos lenguajes orientados-a-objeto, en Java los objetos son pasados por referencia. Esto implica que cualquier acción tomada por el método “llamado” afectará el objeto que tiene el método “que llamó”, esto debido a que ambos objetos son el mismo.

La clase java.lang.Object contiene una implementación native y protected del métodoclone. Esta implementación (que depende de la máquina sobre la que se ejecute el código) determina cuanta memoria está siendo usada por el objeto a ser clonado, reserva la misma cantidad de memoria para el objeto clon, y copia los valores de memoria de la vieja dirección de memoria a la nueva. Y al final se devuelve un java.lang.Object el cual es la referencia al nuevo objeto (el clon).

Para implementar la clonación en una clase, se deben hacer dos cosas:
La clase debe implementar la interfaz Cloneable, esta interfaz no tiene métodos que implementar. El propósito de Cloneable es indicar al método clone dejava.lang.Object que el programador ha dado permiso explícito a la clase para permitir que los objetos instanciados a partir de ella sean clonados.
El método clone de la clase java.lang.Object debe ser sobrescrito con un acceso de tipo public en vez de protected. Es en este método que se implementará el código que clona del objeto.

La excepción CloneNotSupportedException es arrojada por el método clone de la clase java.lang.Object para prevenir que la operación de clonación se ejecute si no se ha otorgado el permiso para ello (es decir, se implemente la interfaz Cloneable).

En términos sencillos el método clone de la clase java.lang.Object crea un nuevo objeto mediante la copia exacta de los bytes de memoria y devolviendo una referencia, de esto se tiene que los objetos miembros de un clon apuntan a los mismos objetos que los objetos miembros del objeto original.

Cuando un objeto de la clase CloneTest es creado y a su atributo miembro se le asigna un valor, por ejemplo, “prueba”, la memoria de este objeto realmente solo contiene los bits que representan una referencia a un objeto String que contiene “prueba”. Cuando el métodoclone es ejecutado, el objeto es duplicado byte por byte y el clon contendrá una copia de la misma referencia que apunta al mismo objeto Stringque contiene “prueba”. El resultado final es que existe solamente una copia de “prueba” y que una llamada sobre el objeto o su clon para modificar su valor resultará en cambios para ambos. Esto es conocido como ‘shallow copy’, donde solamente los miembros primitivos (y referencias a objetos) del objeto que están completamente contenidos en la memoria del objeto son duplicados, pero el resto de los objetos miembros en el objeto no lo son.

Este enfoque no es suficientemente bueno para algunos casos, ya que en general los objetos no están compuestos solamente de tipos primitivos. String, Hashtable, Vector y otras clases que residen en el objeto a ser clonado, necesitan a su vez ser clonados, para que el proceso de clonación sea efectivo, esto es el que se conoce como clonación “profunda” (‘deep cloning’).

A pesar que la clonación puede ser necesaria, tambien existen situaciones (usualmente de seguridad) donde se desea prohibir la clonación de una clase, para esto existen varias alternativas, de las cuales las dos más importantes son:
Declarar la clase como final. Haciendo esto se previene que se puedan definir subclases para esta clase, e impedir que cualquiera pueda llamar al método clone desde dentro de la clase (usando el alcance protected). Si se usa esta alternativa para impedir la clonación se debe verificar que ninguna de las superclases se pueda clonar. En el caso que esto sea asi, se debe sobreescribir el método clone en la clase final y arrojar unaCloneNotSupportedException. A pesar que esta es la alternativa efectivamente impide la clonación, establece restricciones acerca de las capacidades de extender la clase, las cuales pueden no ser aceptable.
Implementar Cloneable y sobreescribir el método clone con un alcance public, y hacer que arroje una CloneNotSupportedException. A pesar que esto impide que la clase sea clonada, cualquier subclase puede hacer su propia implementación del métodoclone e implementar la clonación copiando los atributos uno por uno.

Existe otra forma (considerada como “oscura”) de clonar un objeto, que es la serialización (‘serializing’) del objeto. La serialización usa un método nativo externo al objeto, es similiar a la clonación en el sentido en que el estado binario del objeto es capturado desde memoria, pero en vez de copiarlo hacia otra dirección de memoria es copiado hacia un ‘stream’. En un futuro post pienso conversar un poco acerca de la serialización.

Ejemplo de Clonación en Java:

Clase Punto:

package clonico;

public class Punto implements Cloneable{
    private int x;
    private int y;
   public Punto(int x, int y) {
        this.x = x;
     this.y = y;
    }
    public Punto() {
        x=0;
        y=0;
    }
    public Object clone(){
        Object obj=null;
        try{
            obj=super.clone();
        }catch(CloneNotSupportedException ex){
            System.out.println(" no se puede duplicar");
        }
        return obj;
    }
    public void trasladar(int dx, int dy){
        x+=dx;
        y+=dy;
    }
    public String toString(){
        String texto="origen: ("+x+", "+y+")";
        return texto;
    }
}

Clase Rectángulo

package clonico;

public class Rectangulo implements Cloneable{
    private int ancho ;
    private int alto ;
    private Punto origen;

    public Rectangulo() {
     origen = new Punto(0, 0);
     ancho=0;
     alto=0;
    }
    public Rectangulo(Punto p) {
     this(p, 0, 0);
    }
    public Rectangulo(int w, int h) {
     this(new Punto(0, 0), w, h);
    }
    public Rectangulo(Punto p, int w, int h) {
     origen = p;
     ancho = w;
     alto = h;
    }
    public Object clone(){
        Rectangulo obj=null;
        try{
            obj=(Rectangulo)super.clone();
        }catch(CloneNotSupportedException ex){
            System.out.println(" no se puede duplicar");
        }
        obj.origen=(Punto)obj.origen.clone();
        return obj;
    }
    public void mover(int dx, int dy) {
     origen.trasladar(dx, dy);
    }
    public int area() {
     return ancho * alto;
    }
    public String toString(){
        String texto=origen+" ancho: "+ancho+" alto: "+alto;
        return texto;
    }
}

Ejecutar la clonación

package clonico;
public class ClonicoApp {
    public static void main(String[] args) {
        Punto punto=new Punto(20, 30);
        Punto pCopia=(Punto)punto.clone();
        System.out.println("punto "+ punto);
        System.out.println("copia "+ pCopia);

        Rectangulo rect=new Rectangulo(new Punto(0, 0), 4, 5);
        Rectangulo rCopia=(Rectangulo)rect.clone();
        System.out.println("rectángulo "+ rect);
        System.out.println("copia "+ rCopia);

        try  {
//espera la pulsación de una tecla y luego RETORNO
            System.in.read();
        }catch (Exception e) {  }
    }
}

Formatear una fecha y Obtener un String

Formatear una fecha y Obtener un String
Algo que siempre nos da mucho problema es el trabajo con fechas en java, hoy me encontré con un problema, les dejo la solución que encontré para que la tomen en cuenta si se topan con lo mismo. Se trata de formatear una fecha de forma simple para poder mostrar simplemente el texto mediante programación en java, eliminando la complejidad de los objetos GregorianCalendar o Date, mediante la clase SimpleDateFormat

Ejemplo:
    SimpleDateFormat sdf = new SimpleDateFormat("dd - MM - yyyy");
    Calendar cal = Calendar.getInstance(); // hoy
    System.out.println("Hoy es " + sdf.format(cal.getTime()));

La clase SimpleDateFormat es muy sencilla de utilizar en java. Simplemente al constructor hay que pasarle cómo se deben formatear las fechas. dd es el día, MM es el mes y yyyy es el año. Se puede ver una lista de los posibles valores que admite en la API de SimpleDateFormat.

Una vez inicializada la clase, el método format devuelve un StringBuffer con la fecha debidamente formateada. Se le debe pasar un objeto de tipo Date, que se puede extraer del GregorianCalendar mediante el método getTime()…y ya está este sencilla rutina de programación en java.

Errores comunes en programación en Java

Errores comunes en programación en Java

  • Una Clase no está en el directorio correcto
    Este error de sintaxis ocurre si el comando javac no puede encontrar un archivo .java en el directorio esperado. Si una Clase está en el paquete por defecto (no tiene la declaración del package en la primera línea), entonces esta Clase pertenece al directorio actual de trabajo o al directorio donde apunta el flag sourcepath del javac. Si una Clase está a un paquete, entonces pertenece a un subdirectorio debajo del directorio actual de trabajo o a un subdirectorio debajo del directorio donde apunta el flan sourcepath del javac. Por ejemplo, si existe una Clase llamada com.hello.HelloWorld entonces su nombre es HelloWorld y su paquete es com.hello. Si el flan sourcepath está configurada a c:src, entonces el archivo HelloWorld.java debe estar ubicado en el subdirectorio: c:srccomhello.
  • El nombre de la Clase pública no coincide con el nombre del archivo
    Cada archivo .java puede contener sólo una Clase pública. El nombre de esa Clase pública debe coincidir exactamente con el nombre del archivo antes de la extensión .java, respetando incluso las mayúsculas y minúsculas. Por ejemplo, una Clase pública llamada MyClass debe estar en un archivo MyClass.java y no en myclass.java. Este es un error de sintaxis.

  • Error en mayúsculas y minúsculas. Java es un lenguaje case sensitive, esto es que debemos respetar las mayúsculas y minúsculas. (miVar no es igual a mivar). Si hacemos referencia a un identificador que no está bien escrito entonces obtendremos un error de sintaxis.

    • Usando equals contra la asignacion
    • En Java este error puede ser incluso un error de lógica o sintaxis. Para comparar 2 referencias para igualarlas se usa el operador == (el operador de igualdad). Para asignar el valor de la derecha a la variable de la izquierda se usa el operador = (operador de asignación). Los programadores novatos a veces escriben: if (miValor = valorEsperado) Este código intenta evaluar el valor Esperado como un valor booleano en lugar de intentar la evaluación de igualdad entre mi Valor y valorEsperado. Si valorEsperado es del tipo booleano, entonces el código tendrá un error de lógica y probará si el valor Esperado es verdadero o falso. Si valorEsperado no es del tipo booleano, entonces el código lanzará un error de compilación debido a que la estructura if requiere un valor booleano que sea retornado de la comparación (miValor = valorEsperado), pero en Java el operador = siempre retorna el valor de la derecha.
  • Olvidar que los índices en Java empiezan en 0.
    Los índices de los arreglos de Java y las listas empiezan en 0, myArray[0], o myList.get(0). Asegurarse que su loop for no cause errores por este motivo. Si hacemos más loops de los que son posibles, entonces obtendremos el error: ArrayIndexOutBounds exception. Si hacemos menos loops de los requeridos, entonces tendremos un error de lógica.

  • NullPointerException
    El NullPointerException, la maldición de los programadores en Java. Los NullPointerExceptions son errores de lógica causados cuando un programa intenta acceder a métodos o atributos en una referencia que está nula. Si nuestro objeto no ha sido inicializado o ha sido establecido a null con el operador =, entonces la llamada el método o el acceso a uno de sus atributos no es válido.

Entradas populares