78.    finally (palabra reservada)

Componente sintáctico de sentencias “try”.

El bloque finally se ejecuta siempre al acabar el bloque try, tanto si acaba bien como si acaba mal, sea cual sea el significado de acabar bien o mal.


El ejemplo siguiente muestra como el bloque puede acabar bien (calculando la raíz cuadrada de un real positivo) o mal (por diferentes motivos de formato o números negativos); pero siempre incrementa el número de pruebas realizadas:

Inversos.java

public class Inversos {

  public static void main(String[] args) {

    Scanner scanner = new Scanner(System.in);

    int pruebas = 0;

    while (true) {

      double inverso = 0;

      try {

        String x = scanner.next();

        if (x.equals("fin"))

          break;

        int valor = Integer.parseInt(x);

        inverso= 100 / valor;

      } catch (Exception e) {

        System.out.println("  -> " + e);

        inverso = 0;

      } finally {

        pruebas++;

        System.out.println("  -> " + pruebas + ": " + inverso);

      }

    }

  }

}    

ejecución

$ java Inversos

2

  -> 1: 50.0

dos

  -> java.lang.NumberFormatException: For input string: "dos"

  -> 2: 0.0

0

  -> java.lang.ArithmeticException: / by zero

  -> 3: 0.0

fin

  -> 4: 0.0  

 

El bloque finally puede emplearse incluso sin bloques catch, aprovechando su característica de que siempre se ejecuta al salir del bloque try.

El siguiente ejemplo muestra como medir el tiempo que tarda un algoritmo independientemente de que termine bien o mal:

Concretamente, en el ejemplo se busca un cero de una función en un intervalo dado. Como algoritmo se usa el consistente en ir dividiendo el intervalo en mitades hasta acotarlo. Hay varias razones por las que puede no funcionar: la función no está definida en algún punto, o presenta una discontinuidad, o simplemente no pasa por cero. Todas estas causas se traducen en el lanzamiento de una excepción informativa.

Funcion.java

public class Funcion {

    private static final double ERROR = 1E-12;

 

    public double y(double x) {

        return Math.tan(x);             // discontinuidad en x= PI/2

    }

 

    public double cero(double a, double z)

            throws Exception {

        if (a > z) throw new Exception("a > z");

        double fa = y(a);

        double fz = y(z);

        if (Math.abs(fa) < ERROR) return a;

        if (Math.abs(fz) < ERROR) return z;

        if (fa * fz > 0)

          throw new Exception("no pasa por cero en el intervalo");

        double m = (a + z) / 2;

        double fm = y(m);

        if (Math.abs(fm) < ERROR) return m;

        if (Math.abs(a - z) < ERROR)

          throw new Exception("función discontinua");

        if (fa * fm < 0)

            return cero(a, m);

        else

            return cero(m, z);

    }

 

    public static void main(String[] args)

            throws Exception {           // nadie captura la excepción

        long t0 = System.currentTimeMillis();

        try {

            Funcion f = new Test();

            System.out.println("raíz= " + f.cero(1, 3));

        } finally {

            long t2 = System.currentTimeMillis();

            System.out.println((t2 - t0) + "ms");

        }

    }

}     

 

Temas relacionados

Vademécum
¿Qué hace finally con una excepción lanzada y no capturada dentro del try?
¿Puede hacerse "return" desde dentro del finally?
¿Puede lanzarse una excepción desde dentro del finally?