Pular para o conteúdo principal

Guia da certificação Java SE 8 Programmer l - Parte 7: Exceptions

Seja bem-vindo a série de postagens sobre a certificação Java. Como funciona, o que fazer para comprar, marcar o dia da prova e o principal, o que estudar.

Para ver o índice da série e as datas das publicações, acesse este link

Parte 7 – Exceptions

Controle de fluxo de exceções é tão importante quanto a própria orientação a objetos. Veremos como está o seu conhecimento sobre exceptions para que seja possível obter sucesso na prova.

Objetivos do exame

  • Checked, runtime e errors
  • Bloco try catch
  • Classes comuns de exceção
  • Utilizando throw e throws Exception

Exceptions

Uma exceção é um evento que ocorre durante a execução de um programa que interrompe o fluxo normal de instruções.

Classe Throwable e suas subclasses

Os objetos que herdam da classe Throwable incluem descendentes diretos (objetos que herdam diretamente da classe Throwable) e descendentes indiretos (objetos que herdam de filhos ou netos da classe Throwable). A figura abaixo ilustra a hierarquia de classes da classe Throwable e suas subclasses mais significativas. Como você pode ver, Throwable tem dois descendentes diretos: Error e Exception.
The Throwable class and its most significant subclasses.
Fonte: https://docs.oracle.com/javase/tutorial/essential/exceptions/throwing.html

Classe Error

Quando ocorre uma falha de vinculação dinâmica ou outra falha grave na máquina virtual Java, a máquina virtual lança um erro. Os programas simples geralmente não capturam nem lançam erros.

Classe Exception

A maioria dos programas lança e captura objetos derivados da classe Exception. Uma exceção indica que ocorreu um problema, mas não é um problema grave do sistema. A maioria dos programas que você escreve lançará e capturará exceções em vez de erros.

Checked exceptions

Uma checked exception inclui a classe Exception e todas as subclasses que não estendem de RuntimeException. Exceções verificadas tendem a ser antecipadas forçando que seja verificado em tempo de compilação.
void showMessage(String msg) throws Exception {
    if (msg == null){
        throw new Exception("Message is null");
    }
    System.out.println("Message: " + msg);
}
Quem chamar showMessage deve tratar a exceção ou lançar para a chamada anterior.
public static void main(String[] args) throws Exception {
    new TestExceptions().showMessage("hello!");
}

Unchecked exceptions

Exceções não verificadas (runtime exceptions) estendem da classe RuntimeException e não é obrigatório o seu tratamento pelo programador. Vejamos o mesmo exemplo do método showMessage.
void showMessage(String msg) {
    if (msg == null) {
        throw new NullPointerException("Message is null");
    }
    System.out.println("Message: " + msg);
}
Agora não precisamos declarar o throws Exception na assinatura do método, e quem chamar o método também não precisará verificar a exceção em tempo de compilação.

Obs: Não estamos discutindo qual seria a melhor estratégia para o controle de exceções. O que está sendo exposto é o que precisamos saber para a prova (a diferença entre Checked e Unchecked exceptions)

Lançando exceções

No exame, podemos ver duas situações onde devemos saber que uma exceção será lançada. Uma RuntimeException ou uma Exception lançada explicitamente.
public static void main(String[] args) {
    System.out.println(args[0]);
}
O código acima se executado sem passar nenhum parâmetro, fará com que uma RuntimeException seja lançada pela JVM.
Exception in thread "main" java.lang.ArrayIndexOutOfBoundsException: 0
throw new NullPointerException("Message is null");
Este outro trecho de código fará com que o fluxo seja interrompido e fará com que o programa retorne para a chamada anterior ou para algum bloco que capture esta exceção.

Utilizando o try

Try serve basicamente para dizer ao seu código que alguma situação pode ocorrer e que você precisa captura-la para tomar alguma ação. Isso pode ocorrer em uma situação em que você chamou um método que lança exceções verificadas ou é necessário fazer alguma conversão que possa causar uma exceção dentro do bloco try. É obrigatório o uso das chaves após a palavra chave try e também um bloco catch ou finally para que seja considerado válido. A estrutura mínima de um bloco try:
try {
catch (Exception e) {
}
try {
finally {
}
Utilizar apenas o bloco try é um erro de compilação:
try {
}// não compila

Utilizando o finally

O bloco finally pode ser executado em duas situações:
  1. Se uma exceção é lançada, o bloco finally é executado após o bloco catch.
  2. Se nenhuma exceção for lançada, o bloco finally será executado após a conclusão do bloco try.
Ainda podemos ter uma situação onde uma RuntimeException é lançada e não temos o bloco catch.
public static void main(String[] args) {
    try {
        showMessage(null);
    } finally {
        System.out.println("finally");
    }
}
static void showMessage(String msg) {
    if (msg == null) {
        throw new NullPointerException("Message is null");
    }
    System.out.println("Message: " + msg);
}
O código acima irá executar, imprimir finally no console e lançar a exceção para a JVM, pois como é uma RuntimeException, não fomos obrigados a capturar a exceção.
Lembre-se: O bloco finally sempre deve ser o último bloco do try. Existe uma forma onde o bloco finally não é executado. Quando um comando System.exit(0); é invocado, a JVM para de executar naquele momento.
try {
    showMessage(null);
} catch (Exception e) {
    System.out.println("catch");
    System.exit(0);
} finally {
    System.out.println("finally");
}
No código acima, o bloco finally nunca será executado.

Capturando exceções

Podemos ter vários blocos catch entre os blocos try e finally, porém devemos obedecer algumas regras:
  1. Você deve ser capaz de reconhecer se a exceção é uma checked exception ou uma unchecked exception.
  2. Você precisa determinar se alguma das exceções são subclasses das outras. Neste caso, as exceções mais especialistas (subclasses) devem vir antes.
Lembre-se que no máximo um bloco catch será executado e será o primeiro bloco de captura que pode manipulá-lo.
try {
    showMessage(null);
} catch (Exception e) {
    System.out.println("catch");
} catch (NullPointerException n) { //Erro
    System.out.println("null");
} finally {
    System.out.println("finally");
}
O código acima não compila pois um NullPointerException estende de Exception que será capturado primeiro. Para que o código compile, é necessário colocar a exceção mais genérica após.
try {
    showMessage(null);
} catch (NullPointerException n) { //OK
    System.out.println("null");
} catch (Exception e) {
    System.out.println("catch");
} finally {
    System.out.println("finally");
}
O que acontece se lançarmos uma exceção dentro de um bloco try? Perceba que após a chamada do método showMessage, lançamos uma RuntimeException que será capturada pelo nosso bloco catch (Exception e).
public static void main(String[] args) {
    try {
        showMessage("test");
        throw new RuntimeException("catch it!");
    } catch (NullPointerException n) {
        System.out.println("null");
    } catch (Exception e) {
        System.out.println("catched");
    } finally {
        System.out.println("finally");
    }
}
static void showMessage(String msg) {
    if (msg == null) {
        throw new NullPointerException("Message is null");
    }
    System.out.println("Message: " + msg);
}
A execução do código acima resulta em:
Message: test
catched
finally

Tipos de exceção

Para o exame, você deverá ser capaz de reconhecer os três tipos de exceção. Exceções de tempo de execução (runtime exceptions ou unchecked exceptions), exceções verificadas (checked exceptions) e erros.

Runtime (Unchecked) exceptions

Não precisam ser capturadas ou declaradas. Elas podem ser lançadas pelo programador ou pela própria JVM:

Checked Exceptions

Devem ser manipuladas ou declaradas. São filhas de Exception com exceção da RuntimeException. As exceções a seguir aparecem no exame: FileNotFoundExceptionIOExceptionVocê deve saber que FileNotFoundException estende de IOException.

Errors

Erros estendem a classe Error. Eles são lançados pela JVM e não devem ser manipulados ou declarados. Erros que devemos conhecer: ExceptionInInitializerError, StackOverflowError e NoClassDefFoundError.

Métodos que lançam exceções

Se você chamar um método que lança exceções, você deve verificar se a exceção é do tipo checked ou uncheked. Isso faz a diferença entre o código compilar ou não.
public class MyException extends Exception {
}
public class MyClass {
    public static void main(String[] args) {
        MyClass myClass = new MyClass();
        myClass.showCode(200); //Não compila    }
    private void showCode(int code) throws MyException {
        System.out.println("The code is: " + code);
    }
}
O código acima não compila, pois o método showCode lança uma checked exception. E por mais que não seja dado um throw dentro do método, o que importa para quem esta chamando, é a assinatura do método. Para que o código compile, temos duas alternativas:
1 - Lançar a exceção para cima (throws):
public static void main(String[] args) throws MyException {
2 - Capturar a exceção:
try {
    myClass.showCode(200);
} catch (MyException e) {
    e.printStackTrace();
}
E quando um método não lança uma exceção, eu posso capturar?
private void showCode(int code) {
    System.out.println("The code is: " + code);
}
try {
    myClass.showCode(200);
} catch (MyException e) { //Não compila
   e.printStackTrace();
}
O código acima não compila pois nunca será lançada uma checked exception como esperado. Alterando o código acima para uma Exception ou RuntimeExeption, o código compila normalmente.

Exceções e Herança

Quando uma classe sobrescreve um método de uma superclasse ou implementa um método de uma interface, não é permitido adicionar novas checked exceptions à assinatura do método.
public class MyClass {
    public void showCode(int code) {
        System.out.println("The code is: " + code);
    }
}
class SubClass extends MyClass {
    public void showCode(int code) throws MyException {
        super.showCode(code);
    }
}
O método showCode da classe SubClass não compila pois esta declarando que lança uma exceção verificada não compatível com o método da classe pai.
Uma subclasse tem permissão para declarar menos exceções do que a superclasse ou interface. Isso é legal porque os chamadores já estão lidando com isso.
public class MyClass {
    public void showCode(int code) throws Exception {
        System.out.println("The code is: " + code);
    }
}
class SubClass extends MyClass {
    public void showCode(int code) throws MyException {
        System.out.println("code");
    }
}
A subclasse está sobrescrevendo um método que declara uma exceção mais genérica do que esta declarando na versão sobrescrita. Isto é perfeitamente legal. Assim como é legal também a subclasse declarar uma uncheked exception e a classe pai não declarar nada.
public class MyClass {
    public void showCode(int code) {
        System.out.println("The code is: " + code);
    }
}
class SubClass extends MyClass {
    public void showCode(int code) throws RuntimeException {
        System.out.println("code");
    }
}
O código acima compila sem problemas, pois a subclasse lança uma RuntimeException.

Resumo

E com isso fechamos mais um capítulo dos nossos estudos. Lembre-se que para o exame você precisa saber:
  • Diferenciar entre uma uncheked exception e uma checked exception
  • Entender como funciona o bloco try
  • Identificar se uma exceção é lançada pelo programador ou pela JVM
  • Declarar métodos que declaram exceções
  • Reconhecer quando usar throw e throws

Bons estudos e até a próxima!

Comentários

Postagens mais visitadas deste blog

Guia da certificação Java SE 8 Programmer l

Seja bem-vindo a série de postagens sobre a certificação Java. Como funciona, o que fazer para comprar, marcar o dia da prova e o principal, o que estudar.
IntroduçãoNeste guia dividido em 7 partes, você irá saber o que é cobrado na prova denominada “OCA Oracle Certified Associate Java SE 8 Programmer I. Exam 1Z0-808”, assim como os passos para se registrar no exame e fazer a prova. Algumas dicas para ser mais ágil no momento da prova.
Primeiro detalhe importante é que a prova não tem opção em português (existe uma opção em Espanhol). Então é bom se acostumar com a leitura em inglês para poder interpretar as questões. O site para marcar a prova também é todo em Inglês.
A prova tem 70 questões de múltipla escolha que devem ser respondidas em até 150 minutos. O candidato deve obter no mínimo 65% de acerto para receber a certificação.
Vou procurar dar algumas orientações para quem irá fazer a primeira certificação, assim como os que tem certificação em outras versões do Java e querem se atua…

Guia da certificação Java SE 8 Programmer l - Parte 1: Conhecendo a certificação

Seja bem-vindo a série de postagens sobre a certificação Java. Como funciona, o que fazer para comprar, marcar o dia da prova e o principal, o que estudar.

Para ver o índice da série e as datas das publicações, acesse este link

Parte 1 – Conhecendo a certificação
Nesta primeira parte, vamos navegar pelo site da Oracle Education e da Pearson VUE para conhecer como funciona a certificação e se ambientar. Ambos os site estão em Inglês e como já dito no índice da série, a prova não tem opção em português.
Site da Oracle
O site da Oracle não é um dos melhores em usabilidade. Então se procurar por certificação Java no Google, irá encontrar diversos cursos, livros e blogs falando a respeito da certificação menos o site da Oracle.
Pois bem, abaixo o link direto para informações do exame 1Z0-808 - Java SE 8 Programmer I
https://education.oracle.com/pls/web_prod-plq-dad/db_pages.getpage?page_id=5001&get_params=p_exam_id:1Z0-808

Neste link você encontrará as informações detalhadas do exame, tais co…

Certificação Java e carreira

Bate papo ao vivo sobre certificação Java e carreira. 

Venha conversar conosco e tirar suas dúvidas sobre carreira e Java. Certificação é suficiente? Como anda minha carreira? Será dia 15/08. Confere ai!
http://bit.ly/javacarreer