RSS

Archivo de la etiqueta: Programacion

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 »

Anuncios
 
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: , , , , , ,

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: Bucles II (break, continue, etiquetas)

Una vez que hemos visto los bucles en Java vamos a ver cómo les afectan las siguientes sentencias: break y continue.

Escribimos un bucle anidado y vemos la diferencia entre break y continue:

public class BucleConBreak{
    public static void main(String[] args){
        for (int i = 0; i< 6; i++){
            for (int j=0; j<5; j++){
                if (j==3){
                    break;
                }
                else{
                    System.out.println("iteracion [i,j]: " + i + ", " + j);
                }
            }
        }
    }
}

El resultado es:

La sentencia break hace que se salga completamente del bucle más interno y proseguimos con la siguiente iteración del bucle externo.

El mismo código pero con continue:

public class BucleConContinue{
     public static void main(String[] args){
         for (int i = 0; i< 6; i++){
             for (int j=0; j<5; j++){
                 if (j==3){
                     continue;
                 }
                 else{
                      System.out.println("iteracion [i,j]: " + i + ", " + j);
                 }
             }
         }
      }
 }

Devuelve:

La sentencia continue hace que pasemos a la siguiente iteración del bucle más interno.

Etiquetas

Es común utilizar las etiquetas con bucles for o while y en conjunción con las sentencias break y continue.

Una etiqueta se coloca antes de la sentencia a etiquetar seguida de ‘:’
Son útiles cuando tenemos bucles anidados y queremos especificar en cuál de ellos queremos hacer un break o continue.

En el siguiente ejemplo tenemos un ejemplo de break etiquetado:
El funcionamiento normal del break sería salir del bucle más interno, el while en este caso.
Sin embargo, el break etiquetado hace que rompa el bucle etiquetado, es decir el for.

public class BucleBreakLabeled{
    public static void main (String[] args){
        boolean esVerdadero = true;
        externo: //etiqueta la siguiente sentencia, es decir el for.
        for (int i = 0; i<5; i++){
            while (esVerdadero){
                System.out.println("Hola!");
                break externo; //break con etiqueta, hace que rompa la sentencia de la etiqueta, el for.
            }
            System.out.println("Despues del while!");
        }
        System.out.println("Despues del for!");
    }
}

Devuelve:

Las sentencias break y continue con etiquetas deben estar dentro de un bucle con la misma etiqueta, si no dará error de compilación.

 
5 comentarios

Publicado por en 8 diciembre, 2011 en Estudio, Tema 5

 

Etiquetas: , , , , , ,

Los Operadores en Java (II)

Operador Resto: %

Devuelve el resto de una división.

class Resto{
    public static void main (String[] args){
        int dividendo = 15;
        int divisor = 2;
        int resto = dividendo % divisor;
        System.out.println("Resto: " + resto);

        int expresion = 3 + dividendo % divisor;
        System.out.println("Expresion: " + expresion);
    }
}

Hay que recordar que los operadores *, /, % tienen una prioridad mayor que los operadores + y -, como se puede comprobar en el ejemplo.

Recordamos también que las expresiones se evalúan por defecto de izquierda a derecha y que para cambiar la prioridad en las evaluaciones se pueden utilizar paréntesis.


Operador Concatenador: +
Con este operador se realiza una concatenación de objetos String y resulta en un nuevo objeto String.

String sujeto = "Ellos";
String predicado = "estudiaban Java";
String frase = sujeto + " " + predicado;
System.out.println(frase); //Devuelve "

Si uno de los argumentos del operador + es String el otro argumento se convierte en objeto String.

Por ejemplo, entre números y String:

class PruebaConcatenador{
    public static void main (String[] args){
        String nombre = "Virginia";
        int a = 10;
        int b = 20;

        System.out.println(nombre + a + b);
        System.out.println(a + b + nombre);
        System.out.println(a + b + nombre + a + b);
    }
}

Devolvería:

Todos los objetos pueden convertirse en objeto String de forma automática, pero el resultado puede tener poco significado. Es por esto que para dar una representación significativa de un objeto en String se suele sobrecargar el método toString().


Operadores de Incremento y Decremento: ++, —
Estos operadores se pueden colocar delante de la variable (notación prefjia) o después de la variable (notación sufija) y realizan un incremento o decremento en 1 en el valor de la variable.

Cuando tenemos la notación prefija (++i ó –i), primero se realiza el aumento o decremento en el valor y luego se evalúa.
Cuando tenemos la notaciión sufija (i++ ó i–), primero se evalúa y luego se realiza el aumento o decremento en el valor.

Por ejemplo:

class OperadoresIncrDecr{
    public static void main (String[] args){
        int a = 10;
        int b = 10;
        System.out.println("a++: " + a++); //1º Evalua con a y luego la incrementa.
        System.out.println("++b: " + ++b); //1º Incrementa y luego evalua con el nuevo valor.

        System.out.println(a); //Comprobamos que el valor se ha incrementado.
        System.out.println(b); //Comprobamos que el valor se ha incrementado.
    }
}

Devuelve:


Operador Condicional: ?:
El siguiente operador evalúa una condición y asigna un valor si es verdadera u otro valor si es falsa.

x = (expresion logica) ? valorSiVerdadero : valorSiFalso

Por ejemplo:

int nota = 80;
String resultado = (nota >= 65)? "Aprobado!!!" : "Suspenso";



Operadores Lógicos: &, |, &&, ||, ^, !

& y | son los operadores And y Or lógicos. Evalúan siempre ambas condiciones. No tienen evaluación perezosa.

&& y || son los operadores And y Or lógicos con evaluación perezosa.
Quiere decir que si pueden dar el resultado evaluando solo la primera condición no evaluarán la segunda.

Esto se da cuando:

  • La primera condición en || es cierta, independientemente de la segunda condición el resultado ya es cierto.
  • La primera condición en && es falsa, independientemente de la segunda condición el resultado es falso.

Un ejemplo con operadores de incremento para comprobar los diferentes resultados que podemos obtener si usamos un operador con evaluación normal o perezosa:

class Logicos{
    public static void main (String[] args){
        int a = 0; //Valores para operadores &, |
        int b = 5;
        int c = 0; //Valores para operadores perezosos &&, ||
        int d = 5;

        if ( a == 0 | b++ > 2) //Evalúa las dos condiciones y b se incrementa.
        {    System.out.println("Cierto (a==0 |  b++ > 2)-> a: " + a + " b: " + b);  }

        if (c == 0 || d++ > 2) //Evalúa solo la 1ª condición al ser cierta (c==0), b no incrementa.
        {    System.out.println("Cierto (c==0 || d++ > 2)-> c: " + c + " d: " + d);  }

        System.out.println();

        if (a > 0 & b++ < 5) //Evalúa las dos condiciones, b se incrementa de nuevo.
        {  }
        else
        {    System.out.println("Falso (a>0 &  b++  a: " + a + " b: " + b);  }

        if (c > 0 && d++ < 5) //Evalúa solo la 1ª condición por ser falsa (c > 0), d no incrementa.
        {    }
        else
        {    System.out.println("Falso (c>0 && d++ <5) -> c: " + c + " d: " + d);  }
    }
}

Devuelve:

^ es el operador Xor. Devueve cierto cuando una de las condiciones es falsa y la otra verdadera.
Siempre evalúa ambos operandos.

! es el operador Not. Si la condición es cierta devuelve falso y si es falsa devuelve cierto.
Con esto terminamos el tema de Operadores.
Recordaros que los operadores de desplazamiento de bits no entran en el examen para la versión 6. Os podéis encontrar preguntas sobre desplazamiento de bits en cuestionarios por ser de versiones anteriores.

En este post tenéis algunos ejercicios resueltos sobre Operadores.

 
6 comentarios

Publicado por en 4 noviembre, 2011 en Tema4

 

Etiquetas: , , , , , , , , ,

Los Operadores en Java (I)

Operadores

Los operadores son símbolos especiales que producen un nuevo valor a partir de uno o varios operandos.
Los valores producidos son, en la mayoría de los casos, booleanos o numéricos.


En la imagen tendríamos un ejemplo de un operador binario, que a partir de dos operandos produciría un nuevo valor.

En la siguiente tabla mostramos los operadores en Java, su orden de precedencia y su asociatividad.
(I-D: de izquierda a derecha, D-I: de derecha a izquierda).



Operador de Asignación: =
Cuando asignamos valor a variables de tipo primitivo hay casos en los que se produce un casting implícito, otros en los que es necesario un casting explícito y casos en los que se puede producir un truncamiento.
Cuando asignamos valores a variables de tipos de referencia debemos tener cuidado con el tipo.

Esto lo podemos ver en los posts del Tema3.



Operadores de Asignación Compuestos: +=, -=, *=, /=
Se tratan en el examen los cuatro anteriores por ser los más usuales.

Algunos ejemplos:

x += 10; //sería igual a  x = x + 10;
y -= 50; //sería igual a  y = y - 50;
z *= 7;  // equivale a  z = z * 7;
w /= 100; // equivale a w = w/100;

En los operadores compuestos la expresión de la derecha siempre se evalúa primero.

x *= 3 + 5; //sería equilvalente a x *= (3+5), es decir x = x * (3 + 5)  y no x = (x * 3) + 5.



Operadores Relacionales: <, <=, >, >=
Siempre devuelven true or false. Se suelen utilizar en sentencias ifs para comprobar condiciones o en expresiones para asignar el valor resultante a una variable boolean.

Pueden comparar cualquier combinación de enteros, reales o carácteres. Cuando se compara con un carácter se utiliza su valor Unicode numérico.

Ejemplos:

boolean resultado;
int x = 200;
if (x<=100)
{
  resultado = true;
}
else
{
  resultado = false;
}

También se podría hacer directamente:

boolean resultado;
resultado = (x<=100);

Con caracteres:

char a = 'A';
char b = 'B';
boolean resultado = a>b;



Operadores de Igualdad: ==, !=

Se pueden comparar dos números, dos carácteres, dos boolean o dos variables de referencia.
Cuando se comparan tipos primitivos devolverá true si ambos valores son iguales.
Cuando se comparan referencias devolverá true si las variables apuntan al mismo objeto.
(No si dos objetos son iguales).

Ejemplos:

class Igualdad{
    public static void main (String[] args)
    {
         int a = 100;
         char b = 'b';
         boolean res = true;

         char[] letras1 = {'a','b','c','d'};
         char[] letras2 = {'a','b','c','d'};

         if (a == 100L)
         { System.out.println("100 y 100L, Iguales");}

         if (res != (b&gt;a))
         { System.out.println("res distinto a (b>;a)");}

         if (letras1 == letras2) //Imprime distinto aunque ambos tengan el mismo contenido.
         { System.out.println("Iguales");} //porque cada referencia apunta a un obj distinto.
         else
         { System.out.println("Distintos");}

         letras2 = letras1; //hacemos que letras2 apunte a letras1

         if (letras1 == letras2) //Imprimirá iguales porque ahora
         { System.out.println("Iguales");} //apuntan al mismo objeto.
         else
         { System.out.println("Distintos");}
    }
}

 


Operador instanceof:

Se utiliza solo con referencias y comprueba si un objeto es de una clase o interfaz determinada.

Por ejemplo, supongamos la siguiente jerarquía de clases:


La clase Persona tiene una subclase Empleado. Empleado a su vez tiene una subclase Tecnico.
Además la clase Persona implementa la interfaz Modales.

Con las siguientes declaraciones:

Persona p1 = new Persona();
Persona p2 = new Empleado();
Empleado e1 = new Empleado();
Tecnico t1 = new Tecnico();
Boolean b;

¿Qué devolvería el operador instanceof en las siguientes líneas de código?

b = p1 is instanceof Persona;
b = p1 is instanceof Modales;
b = p1 is instanceof Object;
b = p1 is instanceof Empleado;
b = p1 is instanceof Tecnico;

b = p2 is instanceof Persona;
b = p2 is instanceof Empleado;
b = p2 is instanceof Modales;
b = p2 is instanceof Tecnico;

b = e1 is instanceof Empleado;
b = e1 is instanceof Modales;
b = e1 is instanceof Persona;
b = e1 is instanceof Tecnico;

b = t1 is instanceof Persona;
b = t1 is instanceof Modales;
b = t1 is instanceof Empleado;
b = t1 is instanceof Tecnico;

b = null is instanceof Persona;
b = e1 is instanceof String;

Seguimos con el resto de operadores en la siguiente entrada…

 
1 comentario

Publicado por en 2 noviembre, 2011 en Tema4

 

Etiquetas: , , , , , , , , ,

El recolector de basura

Muchos lenguajes de programación permiten asignar memoria dinámica en tiempo de ejecución pero es el programador el que tiene la responsabilidad de liberarla.

Sin embargo, Java proporciona un hilo en el nivel del sistema que administra esta memoria, busca la que está en desuso y la libera. Es el recolector de basura o Garbage Collector (GC).

Cuándo se ejecuta:
El GC está bajo el control de la JVM y ella decide cuándo ejecutarlo. Dentro de un programa se puede solicitar la ejecución pero no hay ninguna garantía de que se ejecute.

Cómo funciona:
Los modelos de reciclaje de la memoria pueden variar considerablemente en cada implementación de la JVM. Lo que debemos tener claro es cuándo un objeto es elegible por el GC.

Un objeto es elegible cuando ningún thread vivo puede acceder a él.


Cómo hacer un objeto elegible:

  • Estableciendo la referencia a null:
    Cuando asignamos la referencia de un objeto a null estamos perdiendo cualquier posibilidad de acceder a él.

    public class aNull{
        public static void main (String[] args){
            Integer a = new Integer(10); //1
            a = null; //2
           //ahora el objeto Integer(10) es elegible por el GC.
        }
    }
    

    //1 Creación del objeto.

    //2 La referencia ya no apunta al objeto. La referencia es igual a null. El objeto es ahora elegible por el GC.

  • Reasignando la referencia:
    Cuando hacemos que la referencia que apunta a un objeto apunte a otro distinto dejando el primero inaccesible.

    public class Reasigno{
        public static void main (String[] args){
            Integer a = new Integer(10); //1
            Integer b = new Integer(20); //2
            a = b; //3
            //ahora el objeto Integer(10) es elegible por el GC.
        }
    }
    

    //1 y //2 Creación de los objetos.


    //3 La referencia a y b están ahora apuntando al segundo objeto, siendo el primero elegible para el GC.

  • Cuando la referencia está aíslada:
    Se produce cuando un objeto tiene como miembros otros objetos de su misma clase y aunque se pierdan las referencias de estos objetos aún conservan entre ellos referencias vivas que son elegibles para el GC.

    public class Aislada{
        Aislada vecina;
        public static void main (String[] args){
            Aislada a = new Aislada(); //1
            Aislada b = new Aislada();
    
            a.vecina = b; //2
            b.vecina = c;
            a = null; //3
            b = null; // Aunque las pongamos a null entre los objetos tienen referencias.
        }
     }
    

    //1 y //2: Creación de los objetos Aislada y asignación de la vecina.

       

    //3: Se ponen las referencias a null. Los dos objetos Aisladas son elegibles para el GC.

       

Solicitar la ejecución del GC:
Como hemos dicho antes no se puede forzar la ejecución del recolector de basuras. Se solicita su ejecución mediante la siguiente instrucción pero no se nos garantiza que se ejecute.

Se puede ejecutar mediante:

System.gc();

U obteniendo una instancia de Runtime:

Runtime rt = Runtime.getRuntime();
rt.gc();

Método finalize():
Este método está definido en la clase Object y por tanto todos los objetos lo heredan. En él
podemos escribir cualquier código que queramos que se ejecute antes de que el GC borre el objeto.

Como la ejecución del GC no está garantizada que se ejecute la ejecución de finalize() tampoco está garantizada.

Cada objeto sólo podrá llamar a este método una vez. En este código se podría hacer inelegible el objeto, por ejemplo, volviendo a asignarle una referencia.

 
10 comentarios

Publicado por en 20 octubre, 2011 en Estudio, Tema 3

 

Etiquetas: , , , , , , ,

 
A %d blogueros les gusta esto: