1
|
- UniverCidade - Prof. Ismael H F Santos
|
2
|
- Modulo Ib - Introdução a Linguagem JAVA
- Notação UML
- Pacotes
- Classes Internas Aninhadas
- Tratamento de Exceção
- Asserções
|
3
|
- Linguagem de Programação JAVA
- Ismael H. F. Santos, Apostila
UniverCidade, 2002
- The Java Tutorial: A practical guide for programmers
- Tutorial on-line: http://java.sun.com/docs/books/tutorial
- Java in a Nutshell
- David Flanagan, O´Reilly &
Associates
- Just Java 2
- Mark C. Chan, Steven W. Griffith
e Anthony F. Iasi, Makron Books.
- Java 1.2
- Laura Lemay & Rogers
Cadenhead, Editora Campos
|
4
|
- Core Java 2, Cay S. Horstmann, Gary Cornell
- Volume 1 (Fundamentos)
- Volume 2 (Características Avançadas)
- Java: Como Programar, Deitel & Deitel
- Thinking in Patterns with JAVA, Bruce Eckel
- Gratuito. http://www.mindview.net/Books/TIJ/
|
5
|
|
6
|
- Classes são uma especificação para objetos, representa um tipo de dados
complexo.
- Objetos são instancias da classe
|
7
|
- Separação interface-imlementação: permite um maior reuso
- reuso depende de bom planejamento e design
- Uma vez criada uma classe, ela deve representar uma unidade de código
útil para que seja reutilizável
- Formas de uso e reuso
- Uso e reuso de objetos criados pela classe: mais flexível
- Composição: a “é parte essencial de” b
- Agregação: a “é parte de” b
- Associação: a “é usado por” b
- Reuso da interface da classe:
pouco flexível
- Herança: b “é” a (substituição pura) ou b “é um tipo de” a
(substituição útil, extensão)
|
8
|
- Composição: um trem é formado por locomotiva e vagões
- Agregação: uma locomotiva tem um farol (mas não vai deixar de ser uma
locomotiva se não o tiver)
- Associação: um trem usa uma estrada de ferro ( não faz parte do trem,
mas ele depende dela)
|
9
|
- Herança
- Um carro é um veiculo
- Fuscas e Porsches são carros (e também são veículos)
|
10
|
|
11
|
- Polimorfismo
- Uso de um objeto no lugar de outro. Dessa forma pode-se escrever código
que não dependa da existência previa de tipos específicos
(Extensibilidade)
|
12
|
|
13
|
|
14
|
|
15
|
- Modularidade em Java: Pacotes
- Além das classes, Java provê um
recurso adicional que ajuda a modularidade: o uso de pacotes.
- Um pacote é um conjunto de classes e outros pacotes.
- Pacotes permitem a criação de espaços de nomes, além de mecanismos de
controle de acesso.
- Pacotes: Espaço de Nomes
- Pacotes, a princípio, possuem nomes. O nome do pacote qualifica os
nomes de todas as classes e outros pacotes que o compõem.
- Exemplo: classe Math no pacote
java.lang
- int a = java.lang.Math.abs(-10); // a = 10;
|
16
|
- Pacotes: Espaços de Nomes
- Exemplo: classe Rectangle no pacote graphics
- graphics.Rectangle r = new graphics.Rectangle();
- ...... OU ......
- import graphics.*;
- Rectangle r = new Rectangle();
|
17
|
- Exemplo
- Aplicação
- Pacote appRet
- Classe Ponto
- Classe Retangulo
- Observe a estrutura de diretórios.
|
18
|
- Exemplo – Aplicação RetangApp
- import appRet.*; // importando
pacote appRet
- public class RetangApp {
- public static void main(String[]
args) {
- Retangulo rect1=new
Retangulo(100, 200);
- Retangulo rect2=new
Retangulo(new Ponto(44, 70));
- Retangulo rect3=new
Retangulo();
- rect1.deslocar(40, 20);
- System.out.println("A
área é " +rect1.calcularArea());
- int areaRect=new
Retangulo(100, 50).calcularArea();
- System.out.println("A
área é " + areaRect);
- }
- }
- }
|
19
|
- Exemplo – Classe Ponto
- package appRet; // pacote
- public class Ponto {
- int x; int y;
- public Ponto() { // construtor padrão
- x=0; y=0;
- }
- public Ponto(int x, int y) {
- this.x = x; this.y = y;
- }
- void deslocar(int dx, int dy){
- x+=dx; y+=dy;
- }
- }
|
20
|
- Exemplo – Classe Retangulo
- package appRet; //
declaracao pacote
- public class Retangulo {
- Ponto origem; int largura ; int altura ;
- public Retangulo() { origem = new Ponto(0, 0); largura=0; altura=0; }
- public Retangulo(Ponto p) {
this(p, 0, 0); }
- public Retangulo(int w, int h)
{ this(new Ponto(0, 0), w,
h); }
- public Retangulo(Ponto p, int
w, int h) { origem=p; largura=w; altura=h; }
- void deslocar(int dx, int dy)
{
- origem.deslocar(dx, dy);
- }
- int calcularArea() {
- return largura * altura;
- }
- }
|
21
|
- Pacotes: Controle de Acesso
- Além de membros públicos e privados, temos também membros package.
- Um membro package só pode ser acessado por classes declaradas no mesmo
pacote da classe que declara esse membro.
- Quando omitimos o modificador de controle de acesso, estamos dizendo
que o membro é do tipo package.
|
22
|
- Tipos de Visibilidade
- Os membros que vínhamos declarando eram do tipo package pois sempre
omitimos o modificador de controle de acesso.
- class A { public class B {
- private int i;
- int j; ...
- public int k; }
- }
|
23
|
- Implementação de Pacotes
- Pacotes são tipicamente implementados como diretórios.
- Os arquivos das classes pertencentes ao pacote devem ficar em seu
diretório.
- Hierarquias de pacotes são construídas através de hierarquias de
diretórios.
|
24
|
- “Empacotando” uma Classe
- Para declararmos uma classe como pertencente a um pacote, devemos:
- declará-la em um arquivo dentro do diretório que representa o pacote;
- declarar, na primeira linha do arquivo, que a classe pertence ao
pacote – declaração package.
|
25
|
- Importação de Pacotes
- Podemos usar o nome simples (não qualificado) de uma classe que
pertença a um pacote se importarmos a classe.
- A importação de uma classe (ou classes de um pacote) pode ser feita no
início do arquivo, após a declaração do pacote (se houver) – declaração
import
- As classes do pacote padrão java.lang não precisam ser importadas (Ex.:
Math).
|
26
|
- Exemplo de Arquivo
- package datatypes; //Stack
pertence a datatypes.
- import java.math.*; //Importa todas as classes.
- import java.util.HashTable; // Importa HashTable.
- /*A partir desse ponto, posso usar o nome HashTable diretamente, ao
invés de usar java.util.HashTable.
Assim como posso usar diretamente
o nome de qualquer classe que pertença ao pacote java.math.*/
- public class Stack { // Stack é exportada.
- ...
- }
- Exercícios – Questões 7 e 8
|
27
|
- CLASSPATH
- Propriedade do sistema que contém as localidades onde o JRE irá
procurar classes para execução. Consiste de:
- JARs nativos do JRE (API Java 2)
- Extensões do JRE ( subdiretórios $JAVA_HOME/jre/lib/classes e $JAVA_HOME/jre/lib/ext
)
- Lista de caminhos definidos na variável de ambiente CLASSPATH e/ou na
opção de linha de comando -classpath (-cp) da aplicação java.
- A ordem acima é importante
- Havendo mais de uma classe com mesmo pacote/Nome somente a primeira
classe encontrada é usada enquanto as outras serão ignoradas
|
28
|
- CLASSPATH
- A ordem anterior é importante (cont.)
- Há risco de conflitos. API nova sendo carregada depois de antiga pode
resultar em classes novas chamando classes antigas!
- A ordem dos caminhos na variável CLASSPATH (ou opção -cp) também é
significativa.
- Em uma instalação típica, CLASSPATH contém apenas ".“
- Pacotes iniciados no diretório
atual (onde o interpretador java é executado) são encontrados (podem
ter suas classes importadas)
- Classes localizadas no diretório atual são encontradas.
- Geralmente usada para definir caminhos para uma aplicação
- Os caminhos podem ser diretórios, arquivos ZIP ou JARs
- Pode acrescentar novos caminhos mas não pode remover caminhos do
Classpath do JRE (básico e extensões)
|
29
|
- CLASSPATH (cont.)
- A opção -cp (-classpath) substitui as definições em CLASSPATH
- Exemplo de definição de CLASSPATH
- no DOS/Windows
- set CLASSPATH=extras.jar;.;c:\progs\java
- java - cp %CLASSPATH%;c:\util\lib\jsw.zip gui.Programa
- no Unix (sh, bash)
- CLASSPATH=extras.jar:.:/home/mydir/java
- export CLASSPATH
- java -classpath importante.jar:$CLASSPATH gui.Programa
- Colocar JARs no subdiretório ext ou classes e pacotes no diretório
classes automaticamente os inclui no CLASSPATH para todas as aplicações
da JVM
- Carregados antes das variáveis CLASSPATH e –cp
- Evite usar: pode provocar conflitos. Coloque nesses diretórios apenas
os JARs e classes usados em todas suas aplicações
|
30
|
- CLASSPATH do JRE
- Exemplo: suponha que o CLASSPATH seja
- Classpath JRE: %JAVA_HOME%\jre\lib\rt.jar;
- Classpath Extensão JRE: %JAVA_HOME%\jre\lib\ext\z.jar
- Variável de ambiente CLASSPATH:
.;c:\programas;
- E que uma classe, localizada em c:\exercicio seja executada. Se esta
classe usar a classe arte.fr.Monet o sistema irá procurá-la em
- %JAVA_HOME%\jre\lib\rt.jar\arte\fr\Monet.class
- %JAVA_HOME%\jre\lib\ext\z.jar\arte\fr\Monet.class
- c:\exercício\arte\fr\Monet.class
- c:\programas\arte\fr\Monet.class
|
31
|
- Arquivos JAR
- Aplicações Java são distribuídas em arquivos JAR
- São extensões do formato ZIP
- armazenam pacotes e preservam a hierarquia de diretórios
- Para usar um JAR, é preciso incluí-lo no Classpath
- via CLASSPATH no contexto de execução da aplicação, ou
- via parâmetro -classpath (-cp) do interpretador Java, ou
- copiando-o para $JAVA_HOME/jre/lib/ext
- Para criar um JAR
- jar cvf classes.jar C1.class C2.class xyz.gif abc.html
- jar cf classes.jar –C raiz_onde_estao_pacotes/ .
- Para abrir um JAR
- Para listar o conteúdo de um JAR
|
32
|
|
33
|
|
34
|
- Programas que usem a biblioteca podem estar em qualquer lugar, basta que
caminho até a biblioteca (classes ou JAR) esteja definido no CLASSPATH
- CLASSPATH=%CLASSPATH%;c:\programas\java\classes
- CLASSPATH=%CLASSPATH%;c:\jars\utils.jar
- java –cp %CLASSPATH%; c:\programas\java\classes LibTest
- java –cp %CLASSPATH%; c:\jars\utils.jar LibTest
|
35
|
- Todo JAR possui um arquivo chamado Manifest.mf no subdiretório
/META-INF.
- Lista de pares Nome: atributo
- Serve para incluir informações sobre os arquivos do JAR, CLASSPATH,
classe Main, etc.
- Se não for indicado um arquivo específico, o sistema gerará um Manifest.mf
default (vazio)
- Para um JAR executável, o manifest.mf deve conter a linha:
- Main-Class: nome.da.Classe
- Crie um arquivo de texto qualquer com a linha acima e monte o JAR usando
a opção -manifest:
- jar cvfm arq.jar manifest.mf –C raiz .
- Para executar o JAR em linha de
comando:
|
36
|
- Visibilidade & Herança
- Membros públicos são herdados, enquanto membros privados não são. Às
vezes precisamos algo intermediário: um membro que não seja visto fora
da classe mas que possa ser herdado. As linguagens OO tipicamente dão
suporte a esse tipo de acesso.
- Java permite declararmos um membro que, embora não seja acessível por
outras classes, é herdado por suas sub-classes. Para isso usamos o
modificador de controle de acesso protected.
|
37
|
- Resumo de Visibilidade em Java
- private: membros que são vistos só pelo própria classe e não são
herdados por nenhuma outra;
- package: membros que são vistos e herdados pelas classes do pacote;
- protected: membros que são vistos pelas classes do pacote e herdados
por qualquer outra classe;
- public: membros são vistos e herdados por qualquer classe.
|
38
|
|
39
|
|
40
|
|
41
|
|
42
|
- Herança de Membros entre Pacotes
|
43
|
|
44
|
|
45
|
|
46
|
|
47
|
|
48
|
|
49
|
|
50
|
|
51
|
- Motivação
- Em diversas circunstâncias
precisamos criar classes cujo único objetivo é auxiliar na
implementação de uma outra classe. Nesses casos, podemos declarar uma
classe aninhada, ou seja, declarar uma nova classe como um membro de
uma outra. Em Java o seu uso maior é no tratamento de eventos onde uma
classe aninhada pode ser criada para ser o “event handler” para a
classe mãe.
|
52
|
- Motivação (cont)
- Java permite dois tipos diferentes de aninhamento de tipos:
- Aninhamento estático;
- Classes internas estáticas (membros de classe);
- Aninhamento dinâmico;
- Classes dentro de objetos (membros de instancia);
- Classes dentro de instruções (classes anônimas);
- Classes dentro de métodos (classes locais);
|
53
|
- Aninhamento Estático
- Gera classes e interfaces
normais, cuja única singularidade é o nome, que passa a ser qualificado
pelo nome da classe que as declara.
- Em particular, sendo um membro
de uma classe, uma interface ou classe aninhada está sujeita aos
modificadores de controle de acesso: public, private, protected e
package.
- package p;
- public class A {
- public int i; public static int j;
- public static class B {
... } // classe interna
estatica, so
- // pode
acessar vars e métodos estáticos
- }
- p.A a = new p.A(); p.A.B b =
new p.A.B();
- b.j = 1; // OK !; b.i = 2; //
erro !
|
54
|
- Aninhamento Dinâmico
- Gera classes associadas a objetos,
instruções ou métodos;
- Cada instância da classe
aninhada possui uma referência para o objeto a partir do qual ela é
criada;
- Como ela está associada a um
objeto, ela tem acesso a todos os membros desse objeto.
|
55
|
- São membros do objeto, como métodos e campos. Requerem que objeto exista
antes que possam ser usadas.
- Externamente use referencia.new para criar objetos
- Variáveis de mesmo nome sempre se referem à classe interna
- Use Externa.this.xxx para acessar campos externos
|
56
|
- Servem para tarefas "descartáveis" já que deixam de existir
quando o método acaba
- Têm o escopo de variáveis locais. Objetos criados, porém, podem
persistir além do escopo do método, se retornados
- Se usa variáveis locais do método essas variáveis devem ser constantes
(final), pois assim podem persistir após a conclusão do método. O
compilador cria uma cópia “escondida” dessas variáveis para poderem ser
acessadas com segurança no futuro.
|
57
|
- Classes usadas dentro de métodos freqüentemente servem apenas para criar
um objeto uma única vez
- A classe abaixo estende ou implementa SuperClasse, que pode ser uma
interface ou classe abstrata (o new, neste caso, indica a criação da
classe entre chaves, não da SuperClasse)
- Object i = new SuperClasse() { implementação };
- Compilador gera arquivo Externa$1.class, Externa$2.class,
|
58
|
- Mais reutilização
- Recurso poderoso quando combinado com interfaces e herança - facilita
implementação de delegação: tipo de herança de implementação que
combinando composição com herança de interfaces simula herança
múltipla;
- "Ponteiros seguros" apontando para métodos localizados em
classes internas;
- Flexibilidade para desenvolver objetos descartáveis
- Riscos
- Aumenta significativamente a complexidade do código
- Dificulta o trabalho de depuração (erros de compilador são mais
confusos em classes internas)
- Exercícios – Questão 9
|
59
|
|
60
|
|
61
|
- Terminologia
- Exceção é a ocorrência de uma condição anormal durante a execução de um
método;
- Falha é a inabilidade de um método cumprir a sua função;
- Erro é a presença de um método que não satisfaz sua especificação.
- Em geral a existência de um erro gera uma falha que resulta em uma
exceção !
|
62
|
- Exceções & Modularidade
- O quinto critério de modularidade de Meyer estabelece a capacidade de
conter situações anormais dentro dos módulos.
- Para estarmos aptos a construir um sistema robusto, os métodos devem
sinalizar todas as condições anormais. Ou seja, os métodos devem gerar
exceções que possam ser tratadas para resolver ou contornar as falhas.
|
63
|
- Motivações para Exceções:
- 1) Um método pode detectar uma falha mas não estar apto a resolver sua
causa, devendo repassar essa função a quem saiba. As causas podem ser
basicamente de três tipos:
- Erros de lógica de programação;
- Erros devido a condições do ambiente de execução (arquivo não
encontrado, rede fora do ar, etc.);
- Erros irrecuperáveis (erro interno na JVM, etc);
- 2) Se introduzirmos o tratamento de falhas ao longo do fluxo normal de
código, podemos estar comprometendo muito a legibilidade (veremos um
exemplo adiante ).
|
64
|
|
65
|
- Exceções
- Diz-se que uma exceção é lançada para sinalizar alguma falha.
- O lançamento de uma exceção causa uma interrupção abrupta do trecho de
código que a gerou.
- O controle da execução volta para o primeiro trecho de código (na pilha
de chamadas) apto a tratar a exceção lançada.
|
66
|
- Suporte a Exceções
- As linguagens OO tipicamente dão suporte ao uso de exceções. Para
usarmos exceções precisamos de:
- uma representação para a exceção;
- uma forma de lançar a exceção;
- uma forma de tratar a exceção.
- Java suporta o uso de exceções:
- são representadas por classes;
- são lançadas pelo comando throw;
- são tratadas pela estrutura try-catch-finally.
|
67
|
- De modo geral, um método que lance uma exceção deve declarar isso
explicitamente. Para uma classe representar uma exceção, ela deve
pertencer a uma certa hierarquia.
- Considere a classe:
- public class Calc {
- public int div(int a, int b)
{
- return a/b;
- }
- }
- O método div, se for chamado com
b igual à zero, dará um erro.
Esse erro poderia ser sinalizado através de uma exceção
|
68
|
- Modelo de uma exceção indicando uma divisão por zero.
- public class DivByZeroEx extends
Exception {
- public String toString() {
- return “Division by zero.”;
- }
- }
- Classe com método sinalizando a exceção criada
- public class Calc {
- public int div(int a, int b) throws
DivByZeroEx {
- if (b == 0)
- throw new DivByZeroEx();
- return a/b;
- }
- }
- Podemos, então, quando utilizarmos o método div tratar a exceção, caso
ela ocorra.
|
69
|
- Tratando uma Exceção
- Calc calc = new Calc();
- try {
- int div = calc.div(1,1);
- System.out.println(div);
- } catch ( DivByZeroEx e ) {
- System.out.println(e);
- finally {
- ... // código que sempre é executado
- }
|
70
|
- Tratando Múltiplas Exceções
- try {
- ...
- } catch (Exception1 e1) {
- ...
- } catch (Exception2 e2) {
- ...
- } catch ( Exeception e ) {
- ... // trata todos os outros tipos de
exceções
- } finally {
- ...
- }
|
71
|
|
72
|
|
73
|
- Estrutura try-catch-finally
- Como apresentado, usamos try-catch para tratar uma exceção. A terceira
parte dessa estrutura, finally, especifica um trecho de código que será
sempre executado, não importando o que acontecer dentro do bloco try-catch.
- Não é possível deixar um bloco try-catch-finally sem executar sua parte
finally.
|
74
|
|
75
|
- Código protegido com tratamento de exceções
- Connection conexao = null;
- try {
- Class.forName("sun.jdbc.odbc.JdbcOdbcDriver");
- conexao =
DriverManager.getConnection
(“jdbc:odbc:NorthWind”, ””,””);
- // Comunicação com o SGBD via
chamadas JDBC
- ....
- }catch (ClassNotFoundException
e) {
- System.out.println(“Driver não
encontrado” + e);
- }catch (SQLException sqle) {
- System.out.println(“Erro SQL:
” + sqle);
- }finally {
- if( conexao != null ) conexao.close();
- }
|
76
|
- errorCodeType readFile {
- initialize errorCode = 0;
- open the file;
- if ( theFileIsOpen ) {
- determine the length of the
file;
- if (gotTheFileLength) {
- allocate that much memory;
- if (gotEnoughMemory) {
- read the file into memory;
- if (readFailed) errorCode=
-1;
- } else errorCode = -2;
- } else {
- errorCode = -3;
- }
- close the file;
- if(fileDidntClose &&
errorCode==0) {
- errorCode = -4;
- } else {
- errorCode = errorCode and
-4;
- }
- } else { errorCode = -5; }
- return errorCode;
- }
|
77
|
- Tipos de Exceções em Java
- Checked Exceptions são exceções que devem ser usadas para modelar
falhas contornáveis. Devem sempre ser declaradas pelos métodos que as
lançam e precisam ser tratadas (a menos que explicitamente passadas
adiante);
- Unchecked Exceptions são exceções que devem ser usadas para modelar
falhas incontornáveis. Não precisam ser declaradas e nem tratadas.
|
78
|
- Checked Exceptions
- Para criarmos uma classe que modela uma Checked Exception, devemos
estender a classe Exception.
- Essa exceção será sempre verificada pelo compilador para garantir que
seja tratada quando recebida e declarada pelos métodos que a lançam.
|
79
|
- Unchecked Exceptions
- Esse tipo de exceção não será verificado pelo compilador. Tipicamente
não criamos exceções desse tipo, elas são usadas pela própria linguagem
para sinalizar condições de erro. Podem ser de dois tipos: Error ou RuntimeException.
- As Subclasses de Error não devem ser capturadas, pois representam
situações graves onde a recuperação é impossível ou indesejável.
- As Subclasses de RuntimeException representam erros de lógica de
programação que devem ser corrigidos (podem, mas não devem ser
capturadas: os erros devem ser corrigidos)
|
80
|
- Repassando Exceções
- Se quiséssemos usar o método div sem tratar a exceção, deveríamos
declarar que a exceção passaria adiante.
- public void f() throws DivByZeroEx {
- Calc calc = new Calc();
- int div = calc.div(a,b);
- System.out.println(div);
- ...
- }
|
81
|
- “Eu me comprometo a retornar uma referência para um objeto QueryResults.
Há a possibilidade de que uma exceção do tipo “SQLException” possa
acontecer enquanto eu estou tentando fazer isso para você. Se isso acontecer, eu
não irei tratar a exceção, mas
irei lançá-la para você.”
- Método execute
|
82
|
- try {
- try {
- ...
- } catch( FileNotFoundException e
) {
-
System.err.println("FileNotFoundException:
“+e.getMessage());
- throw new RuntimeException(e);
- }catch (IOException e) {
- class SampleException extends
Exception {
- public
SampleException(String msg) {super(msg);}
- public
SampleException(Throwable t) { super(t); }
- public
SampleException(String msg,Throwable t){super(msg,t);}
- }
- SampleException ex=new
SampleException("Other IOException", e);
- throw ex;
- }
- }catch (Exception cause) {
- System.err.println("Cause:
" + cause);
-
System.err.println("Original cause: " +
cause.getCause());
- }
|
83
|
- Informando mais dados sobre a Exceção
- ....
- }catch (Exception cause) {
- StackTraceElement elements[] =
cause.getStackTrace();
- for (int i=0; n=elements.length;
i < n; i++) {
-
System.err.println(elements[i].getFileName()+ ":“ +
-
elements[i].getLineNumber() + ">> " +
-
elements[i].getMethodName() + "()");
- }
- }
|
84
|
- Usando um arquivo de Log (java.util.logging)
- try {
- Handler handler = new
FileHandler("OutFile.log");
-
Logger.getLogger("").addHandler(handler);
- Logger logger = Logger.getLogger(
- "**[ verify
package:java.sun.example **]");
- StackTraceElement elems[] =
e.getStackTrace();
- for (int i = 0; n =
elems.length; i > n; i++) {
- logger.log(Level.WARNING,elems[i].getMethodName());
- }
- } catch (IOException logException) { System.err.println("Logging
error");
- }
|
85
|
- Encadeando Exceções (versão 1.4 em diante)
- try {
- InputStream fin = new
FileInputStream(args[0]);
- .....
- while((b=in.read()) != -1) {
System.out.print((char)b); }
- } catch (IOException e) {
- throw (HighLevelException) new
-
HighLevelException(e.getMessage()).initCause(e);
- }
- Um objeto Throwable contem um
snapshot da stack trace de sua thread quando de sua criação, alem disso
pode conter um outro objeto Throwable que foi responsável pela sua
criação. Isto implementa o mecanismo de chained exception.
- O metodo initCause salva internamente a exceção indicada para que a
stack trace possa ser impressa em uma instancia da exceção de nível superior, no
exemplo acima HighLevelException
|
86
|
- Exemplo: leitura de arquivo
- import java.io.*;
- public class PrintFile {
- public static void
main(String[] args) {
- try {
- InputStream fin = new
FileInputStream(args[0]);
- InputStream in = new
BufferedInputStream(fin);
- int b;
- while((b=in.read()) != -1)
{ System.out.print((char)b);}
- } catch (IOException e) {
- System.out.println(e);
- } finaly {
- if (fin != null)
fin.close();
- }
- } Exercícios
– Questão 10
- }
|
87
|
- Exemplo: Impressão para arquivo
- import java.io.*;
- public void writeList(Vector v) {
- PrintWriter out = null;
- try {
-
System.out.println("Entering try statement");
- out = new PrintWriter(new
FileWriter("OutFile.txt"));
- for (int i = 0; i > size;
i++) {
- out.println("Value
at: " +i+ "=" +v.elementAt(i));
- }
- } catch (FileNotFoundException
e) {
-
System.err.println("FileNotFoundException:"+e.getMessage());
- } catch (IOException e) {
-
System.err.println("Caught IOException: " +
e.getMessage());
- } finally {
- if (out != null) {
-
System.out.println("Closing PrintWriter");
out.close();
- }else {
System.out.println("PrintWriter not open"); }
- }
- }
|
88
|
|
89
|
|
90
|
- Construtores de Exception
- Exception ()
- Exception (String message)
- Exception (String message, Throwable cause) [Java 1.4]
- Métodos de Exception
- String getMessage() - retorna mensagem passada pelo construtor
- Throwable getCause() - retorna exceção que causou esta exceção [Java
1.4]
- String toString() - retorna nome da exceção e mensagem
- void printStackTrace() - Imprime detalhes (stack trace) sobre exceção
|
91
|
|
92
|
|
93
|
|
94
|
|
95
|
|
96
|
|
97
|
|
98
|
|
99
|
- Exceptions due to programming errors
- In this category, exceptions are generated due to programming errors
(e.g., NullPointerException and IllegalArgumentException). The client
code usually cannot do anything about programming errors.
- Exceptions due to client code errors
- Client code attempts something not allowed by the API, and thereby
violates its contract. The client can take some alternative course of
action, if there is useful information provided in the exception. For
example: an exception is thrown while parsing an XML document that is
not well-formed. The exception contains useful information about the
location in the XML document that causes the problem. The client can
use this information to take recovery steps.
- Exceptions due to resource failures
- Exceptions that get generated when resources fail. For example: the
system runs out of memory or a network connection fails. The client's
response to resource failures is context-driven. The client can retry
the operation after some time or just log the resource failure and
bring the application to a halt.
|
100
|
- Checked exceptions
- Exceptions that inherit from the Exception class are checked exceptions.
Client code has to handle the checked exceptions thrown by the API,
either in a catch clause or by forwarding it outward with the throws
clause.
- Unchecked exceptions
- RuntimeException also extends from Exception. However, all of the
exceptions that inherit from RuntimeException get special treatment.
There is no requirement for the client code to deal with them, and
hence they are called unchecked exceptions.
- C++ and C# do not have checked exceptions at all; all exceptions in
these languages are unchecked.
|
101
|
- When deciding on checked exceptions vs. unchecked exceptions, ask
yourself, "What action can the client code take when the exception
occurs?"
|
102
|
- Preserve encapsulation
- Never let implementation-specific checked exceptions escalate to the
higher layers. For example, do not propagate SQLException from data
access code to the business objects layer. Business objects layer do
not need to know about SQLException. You have two options:
- Convert SQLException into another checked exception, if the client
code is expected to recuperate from the exception.
- Convert SQLException into an unchecked exception, if the client code
cannot do anything about it.
|
103
|
- public void dataAccessCode(){
- try{ ..some code that throws
SQLException
- } catch(SQLException ex){
ex.printStacktrace(); }
- }
- This catch block just suppresses the exception and does nothing. The
justification is that there is nothing my client could do about an
SQLException. How about dealing with it in the following manner?
- public void dataAccessCode(){
- try{ ..some code that throws
SQLException
- } catch(SQLException ex){
- throw new RuntimeException(ex);
- }
- }
|
104
|
- Try not to create new custom exceptions if they do not have useful
information for client code.
- public class DuplicateUsernameException extends Exception{}
- The new version provides two useful methods: requestedUsername(), which
returns the requested name, and availableNames(), which returns an array
of available usernames similar to the one requested.
- public class DuplicateUsernameException extends Exception {
- public
DuplicateUsernameException (String username){....}
- public String
requestedUsername(){...}
- public String[]
availableNames(){...}
- }
|
105
|
- Document exceptions
- You can use Javadoc's @throws tag to document both checked and
unchecked exceptions that your API throws. Or write unit tests to
document exceptions.
- public void testIndexOutOfBoundsException() {
- ArrayList blankList = new
ArrayList();
- try {
- blankList.get(10);
- fail("Should raise an
IndexOutOfBoundsException");
- } catch
(IndexOutOfBoundsException success) {}
- }
|
106
|
- Always clean up after yourself
- If you are using resources like database connections or network
connections, make sure you clean them up.
- public void dataAccessCode(){
- Connection conn = null;
- try{
- conn = getConnection();
- ..some code that throws
SQLException
- } catch( SQLException ex ) {
- ex.printStacktrace();
- } finally{
- DBUtil.closeConnection(conn);
- }
- }
|
107
|
- Always clean up after yourself (cont.)
- class DBUtil{
- public static void
closeConnection (Connection conn) {
- try{
- conn.close();
- } catch(SQLException ex) {
- logger.error("Cannot
close connection");
- throw new
RuntimeException(ex);
- }
- }
- }
- DBUtil is a utility class that closes the Connection. The important
point is the use of finally block, which executes whether or not an
exception is caught. In this example, the finally closes the connection
and throws a RuntimeException if there is problem with closing the
connection.
|
108
|
- Never use exceptions for flow control
- Generating stack traces is expensive and the value of a stack trace is
in debugging. In a flow-control situation, the stack trace would be
ignored, since the client just wants to know how to proceed.
- public void useExceptionsForFlowControl() {
- try {
- while(true) { increaseCount();
}
- } catch
(MaximumCountReachedException ex) {
- } //Continue execution
- }
- public void increaseCount() throws MaximumCountReachedException { if
(count >= 5000) throw new MaximumCountReachedException();
- }
|
109
|
- Do not suppress or ignore exceptions
- When a method from an API throws a checked exception, it is trying to
tell you that you should take some counter action.
- Do not catch top-level exceptions
- Unchecked exceptions inherit from the RuntimeException class, which in
turn inherits from Exception. By catching the Exception class, you are
also catching RuntimeException as in the following code:
- try{
- ..
- } catch( Exception ex ){ }
|
110
|
- Log exceptions just once
- Logging the same exception stack trace more than once can confuse the
programmer examining the stack trace about the original source of
exception. So just log it once.
|
111
|
|
112
|
- Expressões booleanas que o programador define para afirmar uma condição
que ele acredita ser verdade
- Asserções são usadas para validar código ( ter a certeza que um vetor
tem determinado tamanho, ter a certeza que o programa não passou por
determinado lugar, etc)
- Melhoram a qualidade do código: tipo de teste caixa-branca
- Devem ser usadas durante o desenvolvimento e desligadas na produção
(afeta a performance)
- Não devem ser usadas como parte da lógica do código
- Asserções são um recurso novo do JSDK1.4.0
- Nova palavra-chave: assert
- É preciso compilar usando a opção -source 1.4:
- >javac -source 1.4 Classe.java
- Para executar, é preciso habilitar afirmações (enable assertions):
|
113
|
- Asserções testam uma condição. Se a condição for falsa, um AssertionError
é lançado
- Sintaxe:
- assert expressão;
- assert expressãoUm : expressãoDois;
- Se primeira expressão for true, a segunda não é avaliada. Sendo falsa,
um AssertionError é lançado e o valor da segunda expressão é passado no
seu construtor.
|
114
|
- Trecho de código que afirma que controle nunca passará pelo default:
- switch( estacao ) {
- case Estacao.PRIMAVERA:
- ...
- break;
- case Estacao.VERAO:
- ...
- break;
- case Estacao.OUTONO:
- ...
- break;
- case Estacao.INVERNO:
- ...
- break;
- default:
- assert false: "Controle nunca deveria chegar aqui!";
- }
|