RSS

Las clases de cadena: String, StringBuffer y StringBuilder

Java proporciona tres clases diferentes para tratar con cadenas de caracteres:

Los objetos String son cadenas de caracteres estáticas, al crearse e inicializarse no pueden cambiar su valor. Es porque son inmutables que pueden ser compartidas por varias referencias.

Los objetos StringBuffer y StringBuilder, por el contrario, son cadenas de caracteres dinámicas, pueden cambiar su contenido y su capacidad.

La diferencia entre los objetos StringBuffer y StringBuilder es que los primeros pueden ser utilizados de forma segura por varios hilos, siendo sus métodos sincronizados mientras que los objetos StringBuilder no.

La clase StringBuilder se añadió en la versión J2SE 1.5.

Read the rest of this entry »

 
5 comentarios

Publicado por en 27 marzo, 2012 en Tema 6

 

Etiquetas: , , , , , , , , , ,

30 preguntas sobre Assertions

He recopilado las siguientes 30 preguntas sobre Assertions de diferentes
fuentes, citadas al final del post.

Las primeras son más teóricas, preguntando sobre las características de las Assertions y su uso adecuado o no, mientras que las siguientes se concentran en que el aspirante conozca el resultado de la ejecución.

He creído mejor esta vez no colocar las respuestas, si alguna la encontráis difícil o dudosa, podemos hablar de ella en los comentarios.

1. Suponiendo que están habilitadas las assertions, ¿cúales de las siguientes sentencias lanzarán un error?

  1. assert true : true;
  2. assert true : false;
  3. assert false : true;
  4. assert false : false;

2. ¿Cuáles de las siguientes opciones son válidas?

  1. -ae
  2. -enableassertions
  3. -source 1.4
  4. -disablesystemassertions
  5. -dea

3. ¿Cuál es el nombre de la excepción lanzada por una sentencia assertion?

  1. Depends on the assertion statement.
  2. FailedAssertion
  3. AssertionException
  4. RuntimeException
  5. AssertionError
  6. Error

4. ¿Qué puede provocar que una sentencia assert sea ignorada?

  1. Nada.
  2. Usando las opciones de compilación correctas.
  3. Usando las opciones de tiempo ejecución correctas.
  4. Usando las opciones de compilación y tiempo de ejecución correctas.

5. Suponiendo que las assertions están habilitadas, dado el siguiente método, ¿qué sentencias lanzarán una excepción?


static int inv(int value) {
assert value > -50 : value < 100;
return 100/value;
}

  1. inv(-50)
  2. inv(0)
  3. inv(50)
  4. inv(100)
  5. inv(150)
 
2 comentarios

Publicado por en 24 marzo, 2012 en Preguntas

 

Etiquetas: , , , , , ,

Soluciones – Assertions

Solución Ejercicio 1:

Creamos la clase Assert_Identificador.java

public class Assert_Identificador
{
        //Código Anterior a la J2SE 1.4
        //assert como identificador.
	public static void main(String[] args)
	{
		boolean assert;
		assert = Integer.parseInt(args[0]) % 5 == 0;
                if (assert) {
			System.out.println("Correcto");
		}
		else{
			System.out.println("No Correcto");
		}
	}
}

Compilamos normalmente y observamos el error:

Compilamos ahora indicando la versión 1.3 y observamos los warnings:

Ejecutamos:


Solución Ejercicio 2: 

Creamos la clase Assert_PalabraClave.java.

Definimos un constructor con la longitud del array de edades como parámetro.

Creamos un método público setEdad(int pos, int valor) para dar valores a las posiciones del array.
En este método público setEdad, validamos los argumentos lanzando excepciones si no son correctos. Quitaremos estas comprobaciones para provocar que salte la assertion posteriormente.

Creamos el método privado mediaEdades() que calcula la media e incluye la assertion que supone que la media siempre será >0.

public class Assert_PalabraClave{
    private int[] edades;

    public Assert_PalabraClave (int tam){
       edades = new int[tam];
    }

    public void setEdad(int i, int valor){
    /* En un método público no podemos usar assertions para comprobar los
       argumentos, se deben lanzar excepctions si no son válidos. Comentar
       los ifs y exceptions para dejar solo this.edades[i] = valor y
       poder poner en el main un valor negativo que haga saltar
       la assertion en mediaEdades. */

        if (iedades.length-1){
            throw new IllegalArgumentException("\nPosicion: " + i + " fuera de rango del array");
        }
        else if (valor < 0){
            throw new IllegalArgumentException("\nValor: " + valor + " menor de 0");
        }
        else{
    	    this.edades[i] = valor;
        }
    }

    private float mediaEdades(){
        int suma = 0;
        float media = 0;
        int i;
        for (i=0; i 0): "La media no es mayor que cero, es: " + media;
        return media;
    }

    public static void main (String[] args)
    {
          Assert_PalabraClave apc = new Assert_PalabraClave(5);
          apc.setEdad(0, 10);
          apc.setEdad(1, 3);
          apc.setEdad(2, 4);
          apc.setEdad(3, 7);
          apc.setEdad(4, 23);
          //apc.setEdad(4, -100); //para provocar excepción por valor menor de cero.
          //apc.setEdad(5, 39); //para provocar excepción por posición fuera de rango.

	  System.out.println("La media de edad es: " + apc.mediaEdades());

    }
Compilamos con -source 1.3 para observar el error:
Compilarmos normalmente y ejecutamos habilitando assertions:
Modificamos el código fuente para hacer saltar la assertion, compilamos y ejecutamos:

Solución Ejercicio 3:
En el constructor no se puede utilizar un assertion para comprobar los argumentos, ya que es público y esencial que al construirse el objeto se garantice que sus atributos tengan valores válidos. Modificar con excepciones.

Los asserts en los métodos públicos subir(int personas) y bajar(int personas) son correctos ya que no están comprobando los valores del argumento personas, sino el estado final de los atributos del objeto bus.

El assert que comprueba los argumentos pasados en la línea de comandos al programa también es un uso inapropiado. Modificar con excepciones.

Solución Ejercicio 4:

Escribimos un switch sencillo que según el entero nos imprima el día de la semana que le correspondería.

public class AssertSwitch{

  public static void mostrarDiaSemana(int dia)
  {
       switch(dia){
           case 1: System.out.println("Lunes");
           break;

           case 2: System.out.println("Martes");
           break;

           case 3: System.out.println("Miercoles");
           break;

	   case 4: System.out.println("Jueves");
           break;

	   case 5: System.out.println("Viernes");
           break;

           case 6: System.out.println("Sabado");
           break;

	   case 7: System.out.println("Domingo");
           break;

	   default:
		assert(false): "Int Dia pasado: " + dia;
        }
    }

    public static void main (String[] args){
        mostrarDiaSemana(3);
        mostrarDiaSemana(9); //Se supone que este valor nunca se daria
    }
}


 
1 comentario

Publicado por en 23 marzo, 2012 en Deberes

 

Etiquetas: , , , , ,

Deberes – Assertions

Algunos ejercicios para practicar Assertions:

  • Ejercicio 1: 

Crear una clase Assert_Identificador.java que utilice assert como identificador y que imprima “Correcto” si el argumento pasado en la línea de comandos es divisible por 5 y “No Correcto” en caso contrario.

Compilar normalmente para observar el fallo.
Compilar y ejecutar para que tome el código antiguo sin problemas.

  • Ejercicio 2: 

Crear una clase Assert_PalabraClave.java que tenga como atributo un array de enteros llamado edades y crear un método privado mediaEdades que devuelva la medida de las edades en el array y se asegure con una assertion que la media será siempre > 0.

Compilar indicando -source 1.3 para observar el fallo.
Compilar normalmente y ejecutar habilitando assertions.
Introducir valores incorrectos para provocar un AssertionError

  • Ejercicio 3:

Corregir la siguiente clase para que todos los assertions estén usados apropiadamente:

public class Bus {
    private int capacidad;
    private int asientosDisponibles;
    private int asientosOcupados;

    //Constructor para elegir capacidad y asientos iniciales ocupados.
    public Bus(int capacidad, int asientosOcupados){
       assert(capacidad>0);
       assert(asientosOcupados<capacidad);
       this.capacidad = capacidad;
       this.asientosDisponibles = this.capacidad - asientosOcupados;
       this.asientosOcupados = asientosOcupados;
    }

   public void subir(int personas)
    {
        try{comprobarPlazasDisponibles(personas);
        }catch(IllegalArgumentException e){
             System.out.println(e.getMessage());
             personas = this.asientosDisponibles;
        }
        this.asientosDisponibles = this.asientosDisponibles - personas;
        this.asientosOcupados = this.asientosOcupados + personas;
        assert(this.capacidad == this.asientosDisponibles + this.asientosOcupados);
    }

    private void comprobarPlazasDisponibles (int personas) throws IllegalArgumentException{
      if (personas > this.asientosDisponibles){
          throw new IllegalArgumentException("No hay asientos para " + personas + " personas");
      }
    }

    public void bajar(int personas)
    {
        try{ comprobarPlazasOcupadas(personas); //Llama a método privado.
        }catch(IllegalArgumentException e){
            System.out.println(e.getMessage());
            personas = this.asientosOcupados;
        }
    this.asientosDisponibles = this.asientosDisponibles + personas;
        this.asientosOcupados = this.asientosOcupados - personas;
        assert(this.capacidad == this.asientosDisponibles + this.asientosOcupados);
    }

    private void comprobarPlazasOcupadas (int personas) throws IllegalArgumentException{
      if(this.asientosOcupados < personas){
        throw new IllegalArgumentException("No hay " + personas + " personas ocupando asientos");
      }
    }

    public void mostrar()
    {    System.out.println("Capacidad: " + this.capacidad + ".\n" +
                "Ocupados: " + this.asientosOcupados + ".\n" +
	        "Disponibles: " + this.asientosDisponibles + ".\n");
    }

    public static void main (String [] args)
    {
     assert(Integer.parseInt(args[0])>0 && Integer.parseInt(args[1])>0);
     Bus b = new Bus(Integer.parseInt(args[0]), Integer.parseInt(args[1]));     b.mostrar();

    System.out.println("Suben 6");  b.subir(6);  b.mostrar();
    System.out.println("Bajan 3");  b.bajar(3);  b.mostrar();
    System.out.println("Sube 1");   b.subir(1);  b.mostrar();
    System.out.println("Bajan 42"); b.bajar(42); b.mostrar();
    }
}

  • Ejercicio4:

Escribir un bloque switch en el que usemos una assertion para comprobar un caso que no debe producirse.

Soluciones en la siguiente entrada para no alargar mucho el post.

 
Deja un comentario

Publicado por en 22 marzo, 2012 en Deberes

 

Etiquetas: , , , , ,

Assertions: Habilitacion Selectiva, Usos Apropiados

Sobre versiones:

En el examen siempre estaremos usando la versión 6 del compilador (javac) y la versión 6 del lanzador (java). Si existen preguntas sobre código de versiones anteriores siempre serán en el contexto de compilar y ejecutar código antiguo con la versión 6 de Java.

A partir de la versión J2SE 1.4 assert es una palabra clave.
En versiones anteriores assert podía ser utilizada como identificador al no existir todavía las assertions.

Si quisiéramos compilar código antiguo en el que assert se utiliza como identificador hemos de indicar la versión al compilar con la opción -source:

javac -source 1.3 Assert_Identificador.java

Compilaría ok, aunque con warnings, indicando que assert se utiliza como identificador y ejecutaría ok.

Si ese código antiguo lo compiláramos con la versión 1.4 o con la versión por defecto, 1.6, nos daría error:

javac -source 1.4 Assert_Identificador.java
javac Assert_Identificador.java
javac -source 1.6 Assert_Identificador.java
javac -source 6 Assert_Identificador.java

De la misma forma, si un código que utiliza assert como palabra clave se compilara indicando la versión antigua en la que existía como identificador, también se produciría un error de compilación:

javac -source 1.3 Assert_PalabraClave.java


Habilitación e Inhabilitación selectiva:

En la entrada anterior vimos en un ejemplo cómo habilitabamos las assertions en tiempo de ejecución para un fichero .class en concreto:

java -ea Triangulo

Sin embargo, la habilitación o deshabilitación se puede hacer también:

  • Para todas las clases:
    java -ea           //habilita assertions.
    java -da           //deshabilita assertions.
    java -ea -dsa    //habilita assertions en todas las clases menos las clases de sistema.
  • Para todas las clases de un paquete y sus subpaquetes:
    java -ea: proyecto.utiles… //habilita clases del paquete proyecto.utiles y subpaquetes.
    java -da: proyecto.utiles… //deshabilita clases del paquete y subpaquetes.
  • Usando combinaciones:
    java -ea -da: proyecto.utiles.Calendario //Habilita assertions menos la clase Calendario
    java -da -ea: proyecto.utiles… //Deshabilita assertions menos las clases del paquete y
    //subpaquetes


Usos Inapropiados: 

  • Comprobar argumentos de método público.
    Al ser públicos y poder ser utilizados por terceros se debe garantizar con un control más estricto que las assertions, ya que si las assertions están deshabilitadas no se produce ninguna comprobación. Si los valores de los argumentos de un método público son incorrectos se debe lanzar una excepción.
  • Comprobar argumentos de línea de comandos.
    De la misma forma si los valores pasados como argumentos a un programa se necesitan validar no deben ser comprobados con assertions sino con excepciones.
  • Provocar efectos colaterales.
    Las assertions no deberían provocar cambios en el estado del programa. No deben modificarse datos dependiendo de si están habilitadas o no.


Usos Apropiados: 

  • Comprobar argumentos de método privado.
    Los métodos privados serán llamados desde algún código público en el que ya se haya garantizado la correción de los argumentos pasados. Por lo tanto sí se pueden realizar suposiciones con assertions dentro del código privado.
  • Comprobar casos que nunca se producirán (incluso en métodos públicos).
    En bloques if o switch para verificar que ciertas ramas o casos no se deben alcanzar nunca se coloca un assert(false) para que si estamos equivocados en nuestra suposición falle.

En el siguiente post veremos algunos ejercicios y preguntas sobre assertions.

 
Deja un comentario

Publicado por en 20 marzo, 2012 en Tema 5

 

Etiquetas: , , , , ,

Assertions: Introducción y Ejemplo

Una aserción es una expresión lógica que el programador supone que siempre será verdadera cuando se ejecute. Es una forma de confirmar que esta suposición es cierta durante el desarrollo y así evitar tener que programar código que compruebe o controle casos que no se producirán.

Tenemos dos formas de utilizar las assertions:

assert(expresion_logica);
assert(expresion_logica): expresion_valor;

La segunda sintaxis nos permite además establecer una expresión que nos dará más información sobre el error. Esta expresion_valor será cualquier expresión que pueda ser convertida a String, es decir puede ser un valor primitivo, una cadena, un objeto, una función que devuelva alguna de las anteriores, etcétera.

Características:

  • Se incorporaron en la versión J2SE 1.4
  • Siempre se afirma que algo será verdadero.
  • Las assertions están deshabilitadas por defecto.
  • Para habilitar las assertions añadir al comando java el parámetro -ea (ó -enable assertions).
  • Para deshabilitar las assertions añadir al comando java el parámetro -da (ó -disableassertions).
  • La clase java.lang.AssertionError desciende de java.lang.Error y ésta a su vez de java.lang.Throwable.

Ejemplo:
En este programa vamos a construir una clase Triangulo. Tendremos un constructor con los lados como parámetros. En la función esRectangulo que devuelve true si el triángulo es rectángulo y false en caso contrario, colocamos una aserción sobre los lados del triángulo.

import java.lang.Math;
public class Triangulo {

    private float ladoa;
    private float ladob;
    private float ladoc;

    public Triangulo(float ladoa, float ladob, float ladoc){
        this.ladoa = ladoa;
        this.ladob = ladob;
        this.ladoc = ladoc;
    }

    public boolean esRectangulo(){
        //Sabemos un lado de un triangulo debe ser menor que la suma
        //de los otros dos lados.
        assert(ladoa < ladob + ladoc): "\nladoa: " + ladoa
                                     + " no es < que:  "
                                     + ladob + " + " + ladoc;
        return(Math.pow(ladoc,2) == Math.pow(ladoa,2) + Math.pow(ladob,2));
    }

    public static void main (String[] args){
        //Triangulo con valores de lados correctos.
        Triangulo t1 = new Triangulo(6,8,10)
        If t1.esRectangulo(){
            System.out.println("El triangulo t1 es rectangulo");
        }
        //Creamos un triangulo cuyos lados harán saltar la assertion.
        Triangulo t2 = new Triangulo(10,3,2);
        if t2.esRectangulo(){
           System.out.println("El triangulo t2 es rectangulo");
        }
    }
}

Resultado:
Vemos en la captura que primero hemos compilado el fichero fuente.
En segundo lugar, hemos ejecutado el programa, pero al estar deshabilitadas las assertion por defecto no ocurre ningún error.
Por último ejecutamos el programa habilitando las assertions y vemos que la condición no se cumple al comprobar los lados del segundo triángulo.
Nos añade a la traza del error la cadena “ladoa: 10.0 no es < que: 3.0 + 2.0”

 
Deja un comentario

Publicado por en 17 marzo, 2012 en Tema 5

 

Etiquetas: , , , , ,

Control del Flujo: Excepciones

Excepción

Es un evento excepcional que altera el flujo normal del programa. Cuando esto ocurre decimos que se ha lanzado una excepción.

Una excepción se puede generar:

  • en la JVM, como respuesta a una condición inesperada (Caso 1).
  • en el código, lanzadas explícitamente por el programador utilizando la sentencia throw (Caso 2).

Las excepciones del primer caso se llaman no comprobadas (unchecked) y las del segundo comprobadas (checked).

Ejemplo Caso 1: No comprobadas.
Por ejemplo, al intentar acceder a una posición inválida en un array.

public class PruebaOutOfBounds {
    public static void main (String[] args){
        int[] notas = new int[5];
        for (int i = 0; i<=5; i++){
            notas[i] = i*2;
            System.out.println("notas["+i+"]=" + notas[i]);
        }
    }
}

Otras excepciones no comprobadas son: ArithmeticException, ClassCastException, NullPointerException, …
En general son aquellas que descienden de la clase RuntimeException.


Ejemplo Caso 2: Comprobadas.

Cuando lanzamos explícitamente una excepción.

...
 public void reverse() throws Exception{
    if (nombre == null){
       throw new Exception ("El nombre es nulo.\n Lanzamos excepcion al intentar hacer
                             reverse().");
    }
    else
    {
        for (int i = nombre.length()-1; i >=0; i --)
            System.out.println(nombre.charAt(i));
    }
}
...

En general son aquellas que descienden de la clase Exception, excluyendo RuntimeException.


Regla del Manejo o la Declaración
Las excepciones comprobadas que un método pueda lanzar se deben declarar.

Si se produce una excepción comprobada en el código, el método debe:

  • manejar la excepción utilizando el bloque try-catch-finally
  • ó declarar la excepción y pasar la responsabilidad de declaración o gestión al método llamante.

Para declarar la excepción se utiliza la sentencia throws.

Manejando Excepciones
El manejo de excepciones en Java se lleva a cabo principalmente mediante las sentencias: try, catch y finally.

try{
.... //Código que puede provocar una excepcion
}
catch (Excepcion1){   //Puede haber 0, 1 o muchos bloques catch.
       //En caso de haber 0 debe existir bloque finally.
....
}
finally{  //Puede haber 0 o 1 bloque finally.
....   //En caso de haber 0 debe existir bloque catch.
}

En el bloque try encerramos el código que puede lanzar una excepción.
En el bloque catch definimos qué excepción y con qué código tratarla.
En el bloque finally escribimos código que siempre se ejecuta se produzca o no la excepción.

Ejemplo:

public class Alumno{
//...
   public static void main (String[] args){
        try{
         Alumno a = new Alumno("Ana", 12, 6);
         System.out.println(a);
         a.reverse();

         Alumno c = new Alumno();
         System.out.println(c);
         c.reverse();

       }
       catch (Exception e) {
           System.out.println("--> Hemos capturado la excepcion!!.");
       }
       finally {
           System.out.println("--> Siempre se ejecuta se produzca o no excepcion.");
       }
  }
}

Restricciones de los bloques try-catch-finally:

  • Un bloque try debe tener un bloque catch o un bloque finally asociado.
  • Entre un bloque try y catch no puede escribirse código.
  • Si hay varios bloques catch las excepciones más específicas deben colocarse antes que las más generales.
 
2 comentarios

Publicado por en 10 enero, 2012 en Estudio, Tema 5

 
 
A %d blogueros les gusta esto: