SlideShare uma empresa Scribd logo
1 de 16
Baixar para ler offline
Curso de Java – Módulo I
                            Exceções, Entrada e Saída
                              Programação Swing
                                 Fábio Mengue – fabio@unicamp.br
                                  Centro de Computação - Unicamp




                                        Exceções
       O termo exception é uma abreviatura da frase “exceptional event”. Sua definição formal é
um evento que ocorre durante a execução de um programa que quebra o fluxo normal dessa
execução.

        Vários eventos podem causar exceções. Desde problemas sérios com hardware (como um
crash de disco) até um erro simples de programação, como acessar um elemento de um vetor
com um índice inválido. Quando um erro desses tipos ocorrem em um método Java, o método
cria um objeto do tipo Exception e o envia para o sistema. Esse objeto contém informação sobre
o erro, incluindo seu tipo e o estado em que o programa se encontrava quando o erro aconteceu.
O sistema fica responsável por encontrar alguma maneira de lidar corretamente com o erro. Na
linguagem usada pelos programadores Java, dizemos que o sistema gerou uma exceção (em
inglês, throwed an exception).

        Depois que o método gerou uma exceção, o sistema tenta encontrar algum código que
possa ser utilizado para lidar com a exceção. Os candidatos mais prováveis são os que
“chamaram” o método onde o erro aconteceu. Se eles não tiverem condições de lidar com o
erro, o sistema continua a seguir a pilha de chamadas, até encontrar o código apropriado. Por sua
vez, o código é considerado apropriado para lidar com uma exceção quando o tipo da exceção
gerada é o mesmo tipo para o qual ele foi programado. Ao ser encontrado o código correto, o
sistema o executa (em inglês, catch the exception).

        Caso o sistema não consiga identificar um código correto para gerenciar a exceção, o
sistema (normalmente representado pelo programa Java) se encerra. Claro que é desnecessário
dizer que isso não é exatamente o que gostaríamos que acontecesse na maioria das vezes.

       Pelo fato de utilizar exceções para gerenciar erros, os programas em java possuem
vantagens sobre as linguagens tradicionais. A primeira grande vangatem é poder separar o
gerenciamento de erros do código comum. Outra vantagem é a propagação de erros, que permite
que se crie uma classe especializada apenas no gerenciamento destes eventos. E por fim, é
possível agrupar erros por tipo, tratando-os de uma vez. Veremos exemplos para cada uma das
vantagens a seguir.




1
Nas linguagens de programação tradicionais, a detecção de erros e seu tratamento
normalmente causa uma certa confusão no código, pois tudo está misturado. Por exemplo,
imagine que você tenha uma função que leia um arquivo do disco para a memória. Imagine que
esse programa se parece com isso:

lerArquivo{
       abrir o arquivo;
       determinar seu tamanho;
       alocar memória;
       ler o arquivo para a memória;
       fechar o arquivo;
}

        Parece muito simples. Mas o que acontece se:
 




    O arquivo não puder ser aberto ?
 




    For impossível determinar o tamanho do arquivo ?
 




    Não for possível alocar a quantidade total de memória ?
 




    A leitura falhar ?
 




    O arquivo não puder ser fechado ?

       Então, criamos código a mais para detectar e lidar com esses possíveis erros. Assim,
nosso programa agora ficaria assim:

lerArquivo {
       codigoErro=0;
       abrir arquivo;
       if (arquivoAberto) {
               determinar tamanho;
               if (tamanhoDeterminado) {
                       alocar memória;
                       if (memoriaAlocada) {
                               ler o arquivo para a memória;
                               if (leituraFalhou) {
                                        codigoErro=-1;
                               } else {
                                        codigoErro=-2;
                               }
                       } else {
                               codigoErro=-3;
                       }
               fechar arquivo;
               if (arquivoNaoFechado) && codigoErro=0)
               {
                       codigoErro=-4;
               }

2
}
}

         Desta maneira, seu programa com 7 linhas ficou praticamente 3 vezes maior. O pior é
que o código a mais torna o programa um tanto ilegível, e a lógica se perde no meio dos if's e
else's, dificultando a identificação de quais pedaços do código estão realmente fazendo parte da
linha de raciocínio deste programa. Depois de algumas manutenções, o código deve ficar ainda
pior de ler, e os programadores geralmente irão resolver o problema simplesmente ignorando a
prevenção aos erros; eles irão aparecer quando o programa “der pau”.

       A soluçaõ encontrada pelo Java é mais elegante. O programador irá escrever o programa
de maneira usual, mas o tratamento de erros estará separado. Se sua função for reescrita à
maneira Java, ficaria assim:

lerArquivo {
       try {
               abrir arquivo;
               determinar tamanho;
               alocar memória;
               ler o arquivo para memória;
               fechar arquivo;
       } catch (falhaAberturaArquivo) {
               Código de tratamento
       }
       } catch (falhaDeterminarTamanho) {
               Código de tratamento
       }
       } catch (falhaAlocacaoMemoria) {
               Código de tratamento
       }
       } catch (falhaLeitura) {
               Código de tratamento
       }
       } catch (falhaFechamentoArquivo) {
               Código de tratamento
       }
}

        Note que o trabalho de criar código para gerenciar o erro continua. O que temos é a
separação dos detalhes do que fazer quando algo acontece. O Java automaticamente executa
apenas o código que se relaciona com o erro, tornando desnecessária a construção de cadeias if-
else para gerenciar os erros. O programa também fica maior, mas mais legivel e ainda sim menor
do que na abordagem tradicional.

        A segunda vantagem que existe na utilização de exceções é a habilidade de propagar
erros. Suponha que nossa função lerArquivo é o quarto método em uma série de métodos

3
implementados em sua classe. O metodo1 chama o metodo2, que chama metodo3, que
finalmente chama lerArquivo.

metodo1 {
      call method2;
}
metodo2 {
      call method3;
}
metodo3 {
      call lerArquivo;
}

       Suponha que o código em metodo1 seja o único interessado nos erros que podem
acontecer em lerArquivo. Se isso fosse ser implementado usando a notificação tradicional,
metodo3 e metodo2 deveriam ter maneiras de propagar códigos de erro eventualmente
retornados por lerArquivo para os métodos que os invocaram, até chegar a metodo1.

metodo1 {
   errorCodeType error;
   error = call metodo2;
   if (error)
      doErrorProcessing;
   else
      proceed;
}
errorCodeType metodo2 {
   errorCodeType error;
   error = call metodo3;
   if (error)
      return error;
   else
      proceed;
}
errorCodeType metodo3 {
   errorCodeType error;
   error = call lerArquivo;
   if (error)
      return error;
   else
      proceed;
}




4
Como já visto, o sistema Java irá procurar automaticamente um código adequado para o
gerenciamento de erros. Usamos então uma palavra que indica que qualquer exceção ocorrida (e
não tratada) deve ter propagada para a classe que “chamou” a classe corrente. Veja o exemplo:

metodo1 {
  try {
     call metodo2;
  } catch (Exception) {
     doErrorProcessing;
  }
}
metodo2 throws Exception {
  call metodo3;
}
metodo3 throws Exception {
  call lerArquivo;
}

       Entretanto, como pode ser visto no código, o envio das exceções exige um certo esforço
dos métodos intermediários, que também necessitam repassar a exceção com throws até o
método correto. Mesmo assim, essa técnica obviamente é mais vantajosa que a tradicional, no
sentido que evita confusão no código.

       A última mas não menos importante vantagem é que as exceções são agrupadas. Por
exemplo, imagine um grupo de exceções. Todas elas dizem respeito a erros que podem ocorrer
quando se manipula um vetor. Exceção para estouro do vetor, para inclusão de tipo inválido, ou
mesmo para quando o elemento procurado não faz parte do vetor. Cada uma dessas exceções
pode ser tratada de maneira independente, ou você pode ter um método que trate todas as
exceções deste grupo, tornando a coisa mais simples.

        Pelo fato das exceções serem classes Java como qualquer outra, a hierarquia presente em
todas as classes Java também está presente aqui. Todas elas são instâncias ou descendentes da
classe Throwable. Cada “folha” da árvore que se inicia em Throwable representa uma exceção
específica, e cada “tronco” representa um grupo relacionado de exceções.

      Por exemplo, ArrayException é uma subclasse de Exception (por sua vez, uma subclasse
de Throwable), e possui 3 subclasses: InvalidIndexException, ElementTypeException,
NoSuchElementException. Cada uma delas representa um erro específico, que pode ocorrer na
manipulação de um vetor. Uma maneira de lidar com as exceções é uma a uma:

catch (InvalidIndexException e) {
  ...
}
        Outra maneira seria tratando a exceção de acordo com o grupo ao qual ela pertence. Isso
pode ser feito por vários motivos, o mais forte deles é manter a simpliciadade. No nosso
exemplo, temos ArrayException, que representa qualquer erro que pode acontecer com a

5
manipulação de um vetor. Assim, um método pode lidar com uma exceção baseada em sua
hierarquia. Por exemplo:

catch (ArrayException e) {
  ...
}

       Este método lida com todas as exceções que dizem respeito a vetores. É possível saber
qual a exceção através de uma pergunta ao objeto e, recebido como parâmetro. Também é
possível definir um método que lida com qualquer exceção que chegar até ele, como no exemplo:

catch (Exception e) {
  ...
}


Seu primeiro encontro com exceções Java.

      Veja a mensagem de erro abaixo. Ela é gerada pois a classe que estamos compilando
contém chamadas a métodos que lançam exceções quando um erro acontece.

     InputFile.java:8: Warning: Exception java.io.FileNotFoundException
     must be caught, or it must be declared in throws clause of this method.
          in = new FileReader(filename);
              ^
        A linguagem Java exige que os métodos capturem ou especifiquem o lançamento de
exceções que podem acontecer dentro daquele escopo. Se o compilador identifica que aquele
pedaço de código não possui código adequado para o tratamento de exceções, a mensagem de
erro acima é apresentada e o programa simplesmente não é compilado.

       Vamos ver o código do programa InputFile.java e verificar a causa do erro.

    import java.io.*;

    public class InputFile {

       private FileReader in;

       public InputFile(String filename) {
         in = new FileReader(filename);
       }

       public String getWord() {
         int c;
         StringBuffer buf = new StringBuffer();


6
do {
              c = in.read();
              if (Character.isWhitespace((char)c))
                 return buf.toString();
              else
                 buf.append((char)c);
            } while (c != -1);

            return buf.toString();
        }
    }

        O compilador apresenta o erro na linha 8 (in = new FileReader(filename);). Essa
instrução cria um objeto FileReader, usado para abrir um arquivo cujo nome é passado como
parâmetro.

        O que acontece se o arquivo não existir no disco ? Os profissionais que desenharam a
classe FileReader não tinham a menor idéia do que o programador gostaria que acontecesse caso
o arquivo não existisse. O programa deve terminar ? Um nome de arquivo diferente deve ser
testado ? O arquivo deve ser criado ? Não existe jeito de saber o que o programador que está
utilizando o FileReader gostaria que acontecesse nessa situação. Assim, eles geram uma exceção
(do tipo java.io.FileNotFoundException). Assim, o método que chamou a instrução decide a
maneira apropriada de tratar do assunto.

       No nosso exemplo, pode se ver que o programa ignora o fato de que FileReader pode
gerar uma exceção. Mas o compilador Java não deixa que o fato passe em branco, se recusando a
compilar o programa e gerando uma mensagem de erro que alerta o programador a respeito.

        Além da mensagem vista acima, outra mensagem deve ser gerada:

    InputFile.java:15: Warning: Exception java.io.IOException
    must be caught, or it must be declared in throws clause
    of this method.
          while ((c = in.read()) != -1) {
                       ^
       Agora, o problema está no objeto in, que da classe FileReader. O método read() também
pode gerar uma exceção, desta vez caso algum problema aconteça na leitura. Por exemplo, se as
permissões do arquivo não estejam configuradas de modo que esse programa possa ler seus
dados. A exceção gerada pode esse método é java.io.IOException.

        Nesse ponto, você tem duas opções. Ou pode criar o código para capturar as exceções
dentro do programa InputFile ou propaga-las para outros métodos mais acima na pilha de
execução. De qualquer maneira, o programa InputFile deve fazer alguma coisa. E para fazer isso
existe uma maneira correta.



7
O Bloco try

      O primeiro passo para construir um programa capaz de gerenciar exceções é colocar os
comandos que podem gerar exceções dentro de um mesmo contexto, usando a palavra reservada
try:

    try {
       Comandos...
    }

       Você pode colocar cada um dos comandos em um contexto próprio, ou pode colocar
todos os comandos que podem gerar exceção em apenas um contexto e depois programar
(separadamente) o código que irá lidar com cada uma das exceções.

         Por exemplo:

    PrintWriter out = null;
    try {
       out = new PrintWriter(
             new FileWriter("OutFile.txt"));

         for (int i = 0; i < size; i++)
            out.println("Value at: " + i + " = " + victor.elementAt(i));
    }

        O bloco try neste programa delimita o escopo sobre o qual o código de tratamento de
erros irá atuar. Nesse pedaço de código existem duas instruções que podem gerar exceções; você
consegue identifica-las ?

         Uma instrução try deve ser acompanha de pelo menos um bloco catch.

O Bloco catch

       A instrução catch define qual o código que irá ser executado, dependendo da exceção
gerada. Você os associa aos blocos definidos pelo try colocando-os logo após o bloco:

    try {
       ...
    } catch ( . . . ) {
       ...
    } catch ( . . . ) {
       ...
    }...

         Não se deve ter nenhuma outra instrução entre o final do contexto do try e o início do
catch.

8
A forma geral do catch é:

    catch (SomeThrowableObject variavel) {
      Comandos...
    }

       Note que ele é muito parecido com um método. Todo bloco catch identifica o tipo de
exceção que ele trata (SomeThrowableObjet, que é o nome da classe-filho de Throwable) e
recebe como parâmetro a exceção recebida.

       Essa exceção, como tudo em Java, é um objeto. Sendo subclasse de Throwable, esse
objeto herda uma série de métdos. Um dos mais utilizados é o getMessage(), que serve para
mostrar qual a mensagem de erro. Temos ainda métodos para mostrar a pilha de execução e você
pode definir ainda suas próprias exceções (basta criar uma classe que extends Throwable).

       O bloco catch contém normalmente comandos comuns do Java. Muitas vezes o bloco
serve simplesmente para imprimir uma mensagem indicando o erro e parando o programa. O
bloco é executado apenas se a exceção for disparada; os outros blocos catch são ignorados.

       Se utilizarmos como exemplo o código apresentado na página anterior, podemos definir
os blocos catch da maneira mostrada abaixo:

    try {
       ...
    } catch (ArrayIndexOutOfBoundsException e) {
       System.err.println("Caught ArrayIndexOutOfBoundsException: " +
                   e.getMessage());
    } catch (IOException e) {
       System.err.println("Caught IOException: " +
                   e.getMessage());
    }

        O primeiro bloco irá ser executado quando for disparada uma exceção de índice do vetor,
e o outro quando ocorrer um erro de escrita no arquivo.

       A granularidade permitida é muito grande, como podemos ver. Mas é possível definir
apenas alguns (ou mesmo um) blocos para todas as exceções. Criar código diferenciado para
erros de acesso a um vetor ou erro no disco pode ser pouco produtivo. O Java tem a capacidade
de agrupar as exceções, baseado na organização hierárquica das mesmas.

     Quanto mais próximo da classe “folha”, mais específica é o tratamento da exceção.
Podemos escolher em tratar as classes mais próximas do “tronco” ou mesmo da “raiz”.

       Veja a imagem:



9
Assim, podemos reescrever nosso exemplo de modo que apenas um bloco catch pode
lidar com todas as exceções:

     try {
        ...
     } catch (Exception e) {
        System.err.println("Exception caught: " + e.getMessage());
     }

       A classe Exception é a mais alta na hierarquia Throwable. Assim, qualquer exceção que
ocorrer será tratada por esse bloco. A idéia em si é que ele basta para tratar de erros gerais, mas é
um tanto inútil para um tratamento adequado, perdendo um pouco da vantagem de tratamento
que o Java fornece.

       Finalmente, temos o bloco finally.

O Bloco finally

       Todo try deve ter pelo menos um catch. Existe mais um bloco de código que pode ser
definido, mas ele não é obrigatório. Ele existe para que se possa realizar certas atividades que
devem ser feitas independentemente do curso de execução ter gerado exceções ou não. Um
exemplo é fechar um arquivo ou conexão com o banco de dados.

       Lembremos novamente de nosso exemplo da página 8. Três casos ocorrer.

1) O FileWriter falha e lança uma IOException.
2) O victor.elementAt(i) falha e lança uma ArrayIndexOutOfBoundsException.
3) Tudo dá certo, e nenhuma exceção é gerada.

        Certas instruções devem ser executadas para qualquer um dos casos. O bloco finally serve
justamente para isso. Suas instruções serão executadas sempre, com exceções ou sem elas. Sua
definição permite que eliminemos código duplicado e facilita o encerramento de uma rotina.

10
Exercícios:

1. O código abaixo é válido ?

      try {
         ...
      } finally {
         ...
      }

2.Quais as exceções que serão capturadas pelo bloco abaixo ?

      catch (Exception e) {
        ...
      }

Cite uma desvantagem de usar esse tipo de classe de exceção.

3.Quais as exceções que serão capturadas pelo bloco abaixo ?

      ...
      } catch (Exception e) {
          ...
      } catch (ArithmeticException a) {
          ...
      }

Há alguma coisa errada com esses blocos ? O código compila ?




11
Entrada e saida
       As vezes um programa necessita trazer informação de uma fonte externa ou enviar
informação para um destino fora do programa. A informação pode estar em qualquer lugar: um
arquivo em disco, na rede, em outro programa. A informação também pode ser de qualquer tipo:
um objeto, um caracter, uma imagem, um som...

       Para lidar com essas informações, o Java utiliza o conceito de stream. Ele pode ser
entendido como se fosse um “tubo”, onde as informações são enviadas em fluxo, que são lidas
(ou escritas). Veja o desenho:




        Não importa de onde o dado esteja vindo (ou indo), e não importa seu tipo. Os algoritmos
que lidam com streams tratam de maneira sequencial do dados:

       abrir o stream
       enquanto houver informação
               ler informação
       fechar o stream

        O pacote java.io possui classes que tratam e criam os streams. Basicamente, temos
streams para leitura de caracteres e para leitura de bytes. Os primeiros possibilitam a leitura e
escrita de palavras de 16 bits, e são originários da classe abstrata java.io.Reader e java.io.Writer.




12
Os streams para leitura de bytes lidam com palavras de 8 bits, e são subclasses de
java.io.InputStream e java.io.OutputStream.




       Os streams mais fáceis de entender são os relacionados a arquivos. Segue um exemplo de
programa que copia um arquivo de um stream para outro.

import java.io.*;

     public class Copy {
       public static void main(String[] args) throws IOException {
          File inputFile = new File("entrada.txt");

13
File outputFile = new File("saida.txt");

             FileReader in = new FileReader(inputFile);
             FileWriter out = new FileWriter(outputFile);
             int c;

             while ((c = in.read()) != -1)
              out.write(c);

             in.close();
             out.close();
         }
     }

        Como podemos ver, o programa é muito simples. Ele abre um FileReader no arquivo
entrada.txt e abre um FileWriter no arquivo saida.txt. O programa lê caracteres enquanto houver
no stream de entrada e os escreve no stream de saída. Quando terminar, ele fecha ambos os
streams.

         O assunto é um tanto extenso, e esse curso se propõe a passar apenas a idéia básica sobre
o assunto. Temos capacidade de gerar ou ler streams com arquivos zipados, serializar objetos
(artifício utilizado para comunicação remota) e mesmo acessar arquivos de maneira não
sequencial.

                                    Introducao ao Swing
       O pacote Swing é parte da JavaTM Foundation Classes (JFC) na plataforma Java. Existe
na linguagem como pacote de extensão desde a versão 1.1, e serve basicamente para auxiliar as
pessoas a construirem GUI's (Guided User Interface). O Swing fornece todos os componentes
básicos, de botões a tabelas.

Seu primeiro Swing

       A maneira mais fácil de ensinar a utilizar o Swing mostrando código. Vamos a um
programa bem simples, que exibe “Alo Mundo”.

     import javax.swing.*;

     public class HelloWorldSwing {
       public static void main(String[] args) {
          JFrame frame = new JFrame("HelloWorldSwing");
          final JLabel label = new JLabel("Hello World");
          frame.getContentPane().add(label);

             frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
             frame.pack();
14
frame.setVisible(true);
         }
     }

         Esta é a aplicação mais simples que se pode escrever. Vamos analisar o código linha a
linha.

        Inicialmente, como sempre, importamos os pacotes que iremos utilizar. No caso,
javax.swing.*. A outra linha interessante é a onde se define nossa raiz, ou container. Ele é o
elemento principal, e onde iremos “dependurar” tudo que queremos que apareca em nossa tela.
No nosso caso, eh o JFrame. Ele permite que outros componentes sejam adicionados a ele, e tem
a capacidade de gerenciar eventos. Existem outros 2 containers Swing: JDialog e JApplet (esse
último, utilizado apenas para Applets).

       Cada objeto JFrame implementa uma única janela principal, que possui decorações. Elas
são a borda, o título e botões para maximizar, minimizar e fechar a janela. Uma aplicação Swing
usa normalmente pelo menos um JFrame.

        Nosso frame tem um componente. Um label, onde escrevemos “Alo Mundo”. As duas
linhas de código abaixo constroem e adicionam o componente ao frame:

     final JLabel label = new JLabel("Hello World");
     frame.getContentPane().add(label);

       Para fechar a janela quando o botão de fechar é clicado, devemos incluir a linha abaixo
no nosso programa:

     frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);

        O comportamento padrão de um frame quando o botão de fechar é clicado é esconder a
janela, coisa que não desejamos.

       A linha onde consta o método pack() determina o tamanho do frame de modo que todos
os componentes estejam em um tamanho padrão. Esse método utiliza algumas propriedades do
sistema para criar e colocar o frame em um tamanho considerado adequado.

         A última linha, que chama o método setVisible(), faz com que o frame apareça na tela.

         Veja o resultado:




15
Notas sobre o Swing:

       Para aparecer na tela, todos os componentes devem ser adicionados e estarem presentes
em alguma parte de hierarquia, que se inicia na raiz (JFrame, JDialog ou JApplet).

      Todos os componentes raiz possuem um content pane, que contém a parte visível do que
estamos montando, como mostrado na figura abaixo:




       Opcionalmente, você pode adicionar um menu a um componente raiz. O menu é
posicionado diretamente na raiz, fora do content pane.


                                                  Bibliografia

The Java Tutorial – http://www.sun.com/docs
Core Java – Horstmann, Cay S., Cornell, Gary. Makron Books


Proibida a alteração, reprodução e cópia de parte deste material para qualquer finalidade sem a permissão do Centro
de Computação da Unicamp.

A utilização deste material é permitida desde que conste a autoria do mesmo.

© 2002 Centro de Computação da Unicamp.




16

Mais conteúdo relacionado

Mais procurados

Aula 01 - Começando a programar em PHP
Aula 01 - Começando a programar em PHPAula 01 - Começando a programar em PHP
Aula 01 - Começando a programar em PHPEvandro Júnior
 
Java introdução ao java
Java   introdução ao javaJava   introdução ao java
Java introdução ao javaArmando Daniel
 
Certificação Java: Exceções
Certificação Java: ExceçõesCertificação Java: Exceções
Certificação Java: ExceçõesEduardo Mendes
 
Apostila - Linguagem de Programação I
Apostila - Linguagem de Programação IApostila - Linguagem de Programação I
Apostila - Linguagem de Programação ISidney Roberto
 
Programação Concorrente - Gerenciamento de Threads - Parte II
Programação Concorrente - Gerenciamento de Threads - Parte IIProgramação Concorrente - Gerenciamento de Threads - Parte II
Programação Concorrente - Gerenciamento de Threads - Parte IIFabio Moura Pereira
 
Módulo 9 - Introdução à Programação Orientada a Objectos
Módulo 9 - Introdução à Programação Orientada a Objectos Módulo 9 - Introdução à Programação Orientada a Objectos
Módulo 9 - Introdução à Programação Orientada a Objectos Luis Ferreira
 
Curso Java Basico
Curso Java BasicoCurso Java Basico
Curso Java BasicoJoel Lobo
 
05 - Sincronização de Threads - I
05 - Sincronização de Threads - I05 - Sincronização de Threads - I
05 - Sincronização de Threads - IFabio Moura Pereira
 
Java Primeiros Passos - Cap 7
Java Primeiros Passos - Cap 7Java Primeiros Passos - Cap 7
Java Primeiros Passos - Cap 7David Willian
 
Programação Concorrente - Gerenciamento de Threads - Parte I
Programação Concorrente - Gerenciamento de Threads - Parte IProgramação Concorrente - Gerenciamento de Threads - Parte I
Programação Concorrente - Gerenciamento de Threads - Parte IFabio Moura Pereira
 
Java recursos avançados - multithreading
Java   recursos avançados - multithreadingJava   recursos avançados - multithreading
Java recursos avançados - multithreadingArmando Daniel
 

Mais procurados (20)

Aula 01 - Começando a programar em PHP
Aula 01 - Começando a programar em PHPAula 01 - Começando a programar em PHP
Aula 01 - Começando a programar em PHP
 
Listas (parte 2 de 3)
Listas (parte 2 de 3)Listas (parte 2 de 3)
Listas (parte 2 de 3)
 
Java introdução ao java
Java   introdução ao javaJava   introdução ao java
Java introdução ao java
 
01 java fundamentos
01 java fundamentos01 java fundamentos
01 java fundamentos
 
Aula Tratamento de Exceções
Aula Tratamento de ExceçõesAula Tratamento de Exceções
Aula Tratamento de Exceções
 
Certificação Java: Exceções
Certificação Java: ExceçõesCertificação Java: Exceções
Certificação Java: Exceções
 
Ficha teorica aula_input_reader
Ficha teorica aula_input_readerFicha teorica aula_input_reader
Ficha teorica aula_input_reader
 
Java2
Java2Java2
Java2
 
Apostila - Linguagem de Programação I
Apostila - Linguagem de Programação IApostila - Linguagem de Programação I
Apostila - Linguagem de Programação I
 
Programação Concorrente - Gerenciamento de Threads - Parte II
Programação Concorrente - Gerenciamento de Threads - Parte IIProgramação Concorrente - Gerenciamento de Threads - Parte II
Programação Concorrente - Gerenciamento de Threads - Parte II
 
Módulo 9 - Introdução à Programação Orientada a Objectos
Módulo 9 - Introdução à Programação Orientada a Objectos Módulo 9 - Introdução à Programação Orientada a Objectos
Módulo 9 - Introdução à Programação Orientada a Objectos
 
Curso Java Basico
Curso Java BasicoCurso Java Basico
Curso Java Basico
 
05 - Sincronização de Threads - I
05 - Sincronização de Threads - I05 - Sincronização de Threads - I
05 - Sincronização de Threads - I
 
Java7
Java7Java7
Java7
 
Java
JavaJava
Java
 
Java Primeiros Passos - Cap 7
Java Primeiros Passos - Cap 7Java Primeiros Passos - Cap 7
Java Primeiros Passos - Cap 7
 
Java6
Java6Java6
Java6
 
Programação Concorrente - Gerenciamento de Threads - Parte I
Programação Concorrente - Gerenciamento de Threads - Parte IProgramação Concorrente - Gerenciamento de Threads - Parte I
Programação Concorrente - Gerenciamento de Threads - Parte I
 
Java recursos avançados - multithreading
Java   recursos avançados - multithreadingJava   recursos avançados - multithreading
Java recursos avançados - multithreading
 
Mvc delphi
Mvc delphiMvc delphi
Mvc delphi
 

Semelhante a Apostila: Curso de java I

Excecoes
ExcecoesExcecoes
ExcecoesEMSNEWS
 
Como manipular exceções em java
Como manipular exceções em javaComo manipular exceções em java
Como manipular exceções em javadaliarafaela
 
Tratamento de excees slide trabalho
Tratamento de excees slide trabalhoTratamento de excees slide trabalho
Tratamento de excees slide trabalhoHigor Klecyus
 
Curso Java Básico - Aula 04
Curso Java Básico - Aula 04Curso Java Básico - Aula 04
Curso Java Básico - Aula 04Natanael Fonseca
 
Tratamento de exceções em Java
Tratamento de exceções em JavaTratamento de exceções em Java
Tratamento de exceções em JavaWilson Júnior
 
Programação defensiva
Programação defensivaProgramação defensiva
Programação defensivaKayo Rayner
 
Tratamento de exceções
Tratamento de exceçõesTratamento de exceções
Tratamento de exceçõesFAFICA
 
Tratamento de exceções com PHP
Tratamento de exceções com PHPTratamento de exceções com PHP
Tratamento de exceções com PHPLeonardo Soares
 
Java: Excecoes e Tratamento de Erros
Java: Excecoes e Tratamento de ErrosJava: Excecoes e Tratamento de Erros
Java: Excecoes e Tratamento de ErrosArthur Emanuel
 

Semelhante a Apostila: Curso de java I (20)

Excepções JAVA
Excepções JAVAExcepções JAVA
Excepções JAVA
 
Excecoes
ExcecoesExcecoes
Excecoes
 
Excecoes em Java
Excecoes em JavaExcecoes em Java
Excecoes em Java
 
Tratamento de exceções em Java
Tratamento de exceções em JavaTratamento de exceções em Java
Tratamento de exceções em Java
 
Como manipular exceções em java
Como manipular exceções em javaComo manipular exceções em java
Como manipular exceções em java
 
Tratamento de excees slide trabalho
Tratamento de excees slide trabalhoTratamento de excees slide trabalho
Tratamento de excees slide trabalho
 
Curso java 07 - exceções
Curso java   07 - exceçõesCurso java   07 - exceções
Curso java 07 - exceções
 
Curso Java Básico - Aula 04
Curso Java Básico - Aula 04Curso Java Básico - Aula 04
Curso Java Básico - Aula 04
 
Tratamento de exceções em Java
Tratamento de exceções em JavaTratamento de exceções em Java
Tratamento de exceções em Java
 
Programação Defensiva
Programação DefensivaProgramação Defensiva
Programação Defensiva
 
Programação defensiva
Programação defensivaProgramação defensiva
Programação defensiva
 
Erros, exceções e asserções
Erros, exceções e asserçõesErros, exceções e asserções
Erros, exceções e asserções
 
Erros, exceções e asserções
Erros, exceções e asserçõesErros, exceções e asserções
Erros, exceções e asserções
 
Tratamento de exceções
Tratamento de exceçõesTratamento de exceções
Tratamento de exceções
 
Exceptions Em Java UFF
Exceptions Em Java UFFExceptions Em Java UFF
Exceptions Em Java UFF
 
Tratamento de exceções com PHP
Tratamento de exceções com PHPTratamento de exceções com PHP
Tratamento de exceções com PHP
 
Java 13 Excecoes
Java 13 ExcecoesJava 13 Excecoes
Java 13 Excecoes
 
Erros comuns em java
Erros comuns em javaErros comuns em java
Erros comuns em java
 
Java: Excecoes e Tratamento de Erros
Java: Excecoes e Tratamento de ErrosJava: Excecoes e Tratamento de Erros
Java: Excecoes e Tratamento de Erros
 
Java script
Java scriptJava script
Java script
 

Mais de Verônica Veiga

Mais de Verônica Veiga (17)

Trabalho: Arquitetura e software paralelo
Trabalho: Arquitetura e software paralelo  Trabalho: Arquitetura e software paralelo
Trabalho: Arquitetura e software paralelo
 
Trabalho: Rede sem fio.
Trabalho: Rede sem fio.Trabalho: Rede sem fio.
Trabalho: Rede sem fio.
 
Projeto: Montagem de uma rede local
Projeto: Montagem de uma rede local Projeto: Montagem de uma rede local
Projeto: Montagem de uma rede local
 
ApresentaçãoSlides - Xfetecep
ApresentaçãoSlides - XfetecepApresentaçãoSlides - Xfetecep
ApresentaçãoSlides - Xfetecep
 
Apostila: tutorial bios setup ide
Apostila: tutorial bios setup ideApostila: tutorial bios setup ide
Apostila: tutorial bios setup ide
 
Apostila:Curso de java II
Apostila:Curso de java II  Apostila:Curso de java II
Apostila:Curso de java II
 
Apostila: Netbeans
Apostila: NetbeansApostila: Netbeans
Apostila: Netbeans
 
Apostila: CSS
Apostila: CSSApostila: CSS
Apostila: CSS
 
Apostila dreamweaver
Apostila dreamweaver Apostila dreamweaver
Apostila dreamweaver
 
Banco de dados
Banco de dados   Banco de dados
Banco de dados
 
Algoritmo lamport
Algoritmo lamportAlgoritmo lamport
Algoritmo lamport
 
Arquitetura paralela
Arquitetura paralelaArquitetura paralela
Arquitetura paralela
 
Placas de redes
Placas de redesPlacas de redes
Placas de redes
 
Processadores
ProcessadoresProcessadores
Processadores
 
Estrutura de linguagem C++
Estrutura de linguagem C++Estrutura de linguagem C++
Estrutura de linguagem C++
 
Relatório banda larga
Relatório banda largaRelatório banda larga
Relatório banda larga
 
Projeto rede local
Projeto rede localProjeto rede local
Projeto rede local
 

Apostila: Curso de java I

  • 1. Curso de Java – Módulo I Exceções, Entrada e Saída Programação Swing Fábio Mengue – fabio@unicamp.br Centro de Computação - Unicamp Exceções O termo exception é uma abreviatura da frase “exceptional event”. Sua definição formal é um evento que ocorre durante a execução de um programa que quebra o fluxo normal dessa execução. Vários eventos podem causar exceções. Desde problemas sérios com hardware (como um crash de disco) até um erro simples de programação, como acessar um elemento de um vetor com um índice inválido. Quando um erro desses tipos ocorrem em um método Java, o método cria um objeto do tipo Exception e o envia para o sistema. Esse objeto contém informação sobre o erro, incluindo seu tipo e o estado em que o programa se encontrava quando o erro aconteceu. O sistema fica responsável por encontrar alguma maneira de lidar corretamente com o erro. Na linguagem usada pelos programadores Java, dizemos que o sistema gerou uma exceção (em inglês, throwed an exception). Depois que o método gerou uma exceção, o sistema tenta encontrar algum código que possa ser utilizado para lidar com a exceção. Os candidatos mais prováveis são os que “chamaram” o método onde o erro aconteceu. Se eles não tiverem condições de lidar com o erro, o sistema continua a seguir a pilha de chamadas, até encontrar o código apropriado. Por sua vez, o código é considerado apropriado para lidar com uma exceção quando o tipo da exceção gerada é o mesmo tipo para o qual ele foi programado. Ao ser encontrado o código correto, o sistema o executa (em inglês, catch the exception). Caso o sistema não consiga identificar um código correto para gerenciar a exceção, o sistema (normalmente representado pelo programa Java) se encerra. Claro que é desnecessário dizer que isso não é exatamente o que gostaríamos que acontecesse na maioria das vezes. Pelo fato de utilizar exceções para gerenciar erros, os programas em java possuem vantagens sobre as linguagens tradicionais. A primeira grande vangatem é poder separar o gerenciamento de erros do código comum. Outra vantagem é a propagação de erros, que permite que se crie uma classe especializada apenas no gerenciamento destes eventos. E por fim, é possível agrupar erros por tipo, tratando-os de uma vez. Veremos exemplos para cada uma das vantagens a seguir. 1
  • 2. Nas linguagens de programação tradicionais, a detecção de erros e seu tratamento normalmente causa uma certa confusão no código, pois tudo está misturado. Por exemplo, imagine que você tenha uma função que leia um arquivo do disco para a memória. Imagine que esse programa se parece com isso: lerArquivo{ abrir o arquivo; determinar seu tamanho; alocar memória; ler o arquivo para a memória; fechar o arquivo; } Parece muito simples. Mas o que acontece se:   O arquivo não puder ser aberto ?   For impossível determinar o tamanho do arquivo ?   Não for possível alocar a quantidade total de memória ?   A leitura falhar ?   O arquivo não puder ser fechado ? Então, criamos código a mais para detectar e lidar com esses possíveis erros. Assim, nosso programa agora ficaria assim: lerArquivo { codigoErro=0; abrir arquivo; if (arquivoAberto) { determinar tamanho; if (tamanhoDeterminado) { alocar memória; if (memoriaAlocada) { ler o arquivo para a memória; if (leituraFalhou) { codigoErro=-1; } else { codigoErro=-2; } } else { codigoErro=-3; } fechar arquivo; if (arquivoNaoFechado) && codigoErro=0) { codigoErro=-4; } 2
  • 3. } } Desta maneira, seu programa com 7 linhas ficou praticamente 3 vezes maior. O pior é que o código a mais torna o programa um tanto ilegível, e a lógica se perde no meio dos if's e else's, dificultando a identificação de quais pedaços do código estão realmente fazendo parte da linha de raciocínio deste programa. Depois de algumas manutenções, o código deve ficar ainda pior de ler, e os programadores geralmente irão resolver o problema simplesmente ignorando a prevenção aos erros; eles irão aparecer quando o programa “der pau”. A soluçaõ encontrada pelo Java é mais elegante. O programador irá escrever o programa de maneira usual, mas o tratamento de erros estará separado. Se sua função for reescrita à maneira Java, ficaria assim: lerArquivo { try { abrir arquivo; determinar tamanho; alocar memória; ler o arquivo para memória; fechar arquivo; } catch (falhaAberturaArquivo) { Código de tratamento } } catch (falhaDeterminarTamanho) { Código de tratamento } } catch (falhaAlocacaoMemoria) { Código de tratamento } } catch (falhaLeitura) { Código de tratamento } } catch (falhaFechamentoArquivo) { Código de tratamento } } Note que o trabalho de criar código para gerenciar o erro continua. O que temos é a separação dos detalhes do que fazer quando algo acontece. O Java automaticamente executa apenas o código que se relaciona com o erro, tornando desnecessária a construção de cadeias if- else para gerenciar os erros. O programa também fica maior, mas mais legivel e ainda sim menor do que na abordagem tradicional. A segunda vantagem que existe na utilização de exceções é a habilidade de propagar erros. Suponha que nossa função lerArquivo é o quarto método em uma série de métodos 3
  • 4. implementados em sua classe. O metodo1 chama o metodo2, que chama metodo3, que finalmente chama lerArquivo. metodo1 { call method2; } metodo2 { call method3; } metodo3 { call lerArquivo; } Suponha que o código em metodo1 seja o único interessado nos erros que podem acontecer em lerArquivo. Se isso fosse ser implementado usando a notificação tradicional, metodo3 e metodo2 deveriam ter maneiras de propagar códigos de erro eventualmente retornados por lerArquivo para os métodos que os invocaram, até chegar a metodo1. metodo1 { errorCodeType error; error = call metodo2; if (error) doErrorProcessing; else proceed; } errorCodeType metodo2 { errorCodeType error; error = call metodo3; if (error) return error; else proceed; } errorCodeType metodo3 { errorCodeType error; error = call lerArquivo; if (error) return error; else proceed; } 4
  • 5. Como já visto, o sistema Java irá procurar automaticamente um código adequado para o gerenciamento de erros. Usamos então uma palavra que indica que qualquer exceção ocorrida (e não tratada) deve ter propagada para a classe que “chamou” a classe corrente. Veja o exemplo: metodo1 { try { call metodo2; } catch (Exception) { doErrorProcessing; } } metodo2 throws Exception { call metodo3; } metodo3 throws Exception { call lerArquivo; } Entretanto, como pode ser visto no código, o envio das exceções exige um certo esforço dos métodos intermediários, que também necessitam repassar a exceção com throws até o método correto. Mesmo assim, essa técnica obviamente é mais vantajosa que a tradicional, no sentido que evita confusão no código. A última mas não menos importante vantagem é que as exceções são agrupadas. Por exemplo, imagine um grupo de exceções. Todas elas dizem respeito a erros que podem ocorrer quando se manipula um vetor. Exceção para estouro do vetor, para inclusão de tipo inválido, ou mesmo para quando o elemento procurado não faz parte do vetor. Cada uma dessas exceções pode ser tratada de maneira independente, ou você pode ter um método que trate todas as exceções deste grupo, tornando a coisa mais simples. Pelo fato das exceções serem classes Java como qualquer outra, a hierarquia presente em todas as classes Java também está presente aqui. Todas elas são instâncias ou descendentes da classe Throwable. Cada “folha” da árvore que se inicia em Throwable representa uma exceção específica, e cada “tronco” representa um grupo relacionado de exceções. Por exemplo, ArrayException é uma subclasse de Exception (por sua vez, uma subclasse de Throwable), e possui 3 subclasses: InvalidIndexException, ElementTypeException, NoSuchElementException. Cada uma delas representa um erro específico, que pode ocorrer na manipulação de um vetor. Uma maneira de lidar com as exceções é uma a uma: catch (InvalidIndexException e) { ... } Outra maneira seria tratando a exceção de acordo com o grupo ao qual ela pertence. Isso pode ser feito por vários motivos, o mais forte deles é manter a simpliciadade. No nosso exemplo, temos ArrayException, que representa qualquer erro que pode acontecer com a 5
  • 6. manipulação de um vetor. Assim, um método pode lidar com uma exceção baseada em sua hierarquia. Por exemplo: catch (ArrayException e) { ... } Este método lida com todas as exceções que dizem respeito a vetores. É possível saber qual a exceção através de uma pergunta ao objeto e, recebido como parâmetro. Também é possível definir um método que lida com qualquer exceção que chegar até ele, como no exemplo: catch (Exception e) { ... } Seu primeiro encontro com exceções Java. Veja a mensagem de erro abaixo. Ela é gerada pois a classe que estamos compilando contém chamadas a métodos que lançam exceções quando um erro acontece. InputFile.java:8: Warning: Exception java.io.FileNotFoundException must be caught, or it must be declared in throws clause of this method. in = new FileReader(filename); ^ A linguagem Java exige que os métodos capturem ou especifiquem o lançamento de exceções que podem acontecer dentro daquele escopo. Se o compilador identifica que aquele pedaço de código não possui código adequado para o tratamento de exceções, a mensagem de erro acima é apresentada e o programa simplesmente não é compilado. Vamos ver o código do programa InputFile.java e verificar a causa do erro. import java.io.*; public class InputFile { private FileReader in; public InputFile(String filename) { in = new FileReader(filename); } public String getWord() { int c; StringBuffer buf = new StringBuffer(); 6
  • 7. do { c = in.read(); if (Character.isWhitespace((char)c)) return buf.toString(); else buf.append((char)c); } while (c != -1); return buf.toString(); } } O compilador apresenta o erro na linha 8 (in = new FileReader(filename);). Essa instrução cria um objeto FileReader, usado para abrir um arquivo cujo nome é passado como parâmetro. O que acontece se o arquivo não existir no disco ? Os profissionais que desenharam a classe FileReader não tinham a menor idéia do que o programador gostaria que acontecesse caso o arquivo não existisse. O programa deve terminar ? Um nome de arquivo diferente deve ser testado ? O arquivo deve ser criado ? Não existe jeito de saber o que o programador que está utilizando o FileReader gostaria que acontecesse nessa situação. Assim, eles geram uma exceção (do tipo java.io.FileNotFoundException). Assim, o método que chamou a instrução decide a maneira apropriada de tratar do assunto. No nosso exemplo, pode se ver que o programa ignora o fato de que FileReader pode gerar uma exceção. Mas o compilador Java não deixa que o fato passe em branco, se recusando a compilar o programa e gerando uma mensagem de erro que alerta o programador a respeito. Além da mensagem vista acima, outra mensagem deve ser gerada: InputFile.java:15: Warning: Exception java.io.IOException must be caught, or it must be declared in throws clause of this method. while ((c = in.read()) != -1) { ^ Agora, o problema está no objeto in, que da classe FileReader. O método read() também pode gerar uma exceção, desta vez caso algum problema aconteça na leitura. Por exemplo, se as permissões do arquivo não estejam configuradas de modo que esse programa possa ler seus dados. A exceção gerada pode esse método é java.io.IOException. Nesse ponto, você tem duas opções. Ou pode criar o código para capturar as exceções dentro do programa InputFile ou propaga-las para outros métodos mais acima na pilha de execução. De qualquer maneira, o programa InputFile deve fazer alguma coisa. E para fazer isso existe uma maneira correta. 7
  • 8. O Bloco try O primeiro passo para construir um programa capaz de gerenciar exceções é colocar os comandos que podem gerar exceções dentro de um mesmo contexto, usando a palavra reservada try: try { Comandos... } Você pode colocar cada um dos comandos em um contexto próprio, ou pode colocar todos os comandos que podem gerar exceção em apenas um contexto e depois programar (separadamente) o código que irá lidar com cada uma das exceções. Por exemplo: PrintWriter out = null; try { out = new PrintWriter( new FileWriter("OutFile.txt")); for (int i = 0; i < size; i++) out.println("Value at: " + i + " = " + victor.elementAt(i)); } O bloco try neste programa delimita o escopo sobre o qual o código de tratamento de erros irá atuar. Nesse pedaço de código existem duas instruções que podem gerar exceções; você consegue identifica-las ? Uma instrução try deve ser acompanha de pelo menos um bloco catch. O Bloco catch A instrução catch define qual o código que irá ser executado, dependendo da exceção gerada. Você os associa aos blocos definidos pelo try colocando-os logo após o bloco: try { ... } catch ( . . . ) { ... } catch ( . . . ) { ... }... Não se deve ter nenhuma outra instrução entre o final do contexto do try e o início do catch. 8
  • 9. A forma geral do catch é: catch (SomeThrowableObject variavel) { Comandos... } Note que ele é muito parecido com um método. Todo bloco catch identifica o tipo de exceção que ele trata (SomeThrowableObjet, que é o nome da classe-filho de Throwable) e recebe como parâmetro a exceção recebida. Essa exceção, como tudo em Java, é um objeto. Sendo subclasse de Throwable, esse objeto herda uma série de métdos. Um dos mais utilizados é o getMessage(), que serve para mostrar qual a mensagem de erro. Temos ainda métodos para mostrar a pilha de execução e você pode definir ainda suas próprias exceções (basta criar uma classe que extends Throwable). O bloco catch contém normalmente comandos comuns do Java. Muitas vezes o bloco serve simplesmente para imprimir uma mensagem indicando o erro e parando o programa. O bloco é executado apenas se a exceção for disparada; os outros blocos catch são ignorados. Se utilizarmos como exemplo o código apresentado na página anterior, podemos definir os blocos catch da maneira mostrada abaixo: try { ... } catch (ArrayIndexOutOfBoundsException e) { System.err.println("Caught ArrayIndexOutOfBoundsException: " + e.getMessage()); } catch (IOException e) { System.err.println("Caught IOException: " + e.getMessage()); } O primeiro bloco irá ser executado quando for disparada uma exceção de índice do vetor, e o outro quando ocorrer um erro de escrita no arquivo. A granularidade permitida é muito grande, como podemos ver. Mas é possível definir apenas alguns (ou mesmo um) blocos para todas as exceções. Criar código diferenciado para erros de acesso a um vetor ou erro no disco pode ser pouco produtivo. O Java tem a capacidade de agrupar as exceções, baseado na organização hierárquica das mesmas. Quanto mais próximo da classe “folha”, mais específica é o tratamento da exceção. Podemos escolher em tratar as classes mais próximas do “tronco” ou mesmo da “raiz”. Veja a imagem: 9
  • 10. Assim, podemos reescrever nosso exemplo de modo que apenas um bloco catch pode lidar com todas as exceções: try { ... } catch (Exception e) { System.err.println("Exception caught: " + e.getMessage()); } A classe Exception é a mais alta na hierarquia Throwable. Assim, qualquer exceção que ocorrer será tratada por esse bloco. A idéia em si é que ele basta para tratar de erros gerais, mas é um tanto inútil para um tratamento adequado, perdendo um pouco da vantagem de tratamento que o Java fornece. Finalmente, temos o bloco finally. O Bloco finally Todo try deve ter pelo menos um catch. Existe mais um bloco de código que pode ser definido, mas ele não é obrigatório. Ele existe para que se possa realizar certas atividades que devem ser feitas independentemente do curso de execução ter gerado exceções ou não. Um exemplo é fechar um arquivo ou conexão com o banco de dados. Lembremos novamente de nosso exemplo da página 8. Três casos ocorrer. 1) O FileWriter falha e lança uma IOException. 2) O victor.elementAt(i) falha e lança uma ArrayIndexOutOfBoundsException. 3) Tudo dá certo, e nenhuma exceção é gerada. Certas instruções devem ser executadas para qualquer um dos casos. O bloco finally serve justamente para isso. Suas instruções serão executadas sempre, com exceções ou sem elas. Sua definição permite que eliminemos código duplicado e facilita o encerramento de uma rotina. 10
  • 11. Exercícios: 1. O código abaixo é válido ? try { ... } finally { ... } 2.Quais as exceções que serão capturadas pelo bloco abaixo ? catch (Exception e) { ... } Cite uma desvantagem de usar esse tipo de classe de exceção. 3.Quais as exceções que serão capturadas pelo bloco abaixo ? ... } catch (Exception e) { ... } catch (ArithmeticException a) { ... } Há alguma coisa errada com esses blocos ? O código compila ? 11
  • 12. Entrada e saida As vezes um programa necessita trazer informação de uma fonte externa ou enviar informação para um destino fora do programa. A informação pode estar em qualquer lugar: um arquivo em disco, na rede, em outro programa. A informação também pode ser de qualquer tipo: um objeto, um caracter, uma imagem, um som... Para lidar com essas informações, o Java utiliza o conceito de stream. Ele pode ser entendido como se fosse um “tubo”, onde as informações são enviadas em fluxo, que são lidas (ou escritas). Veja o desenho: Não importa de onde o dado esteja vindo (ou indo), e não importa seu tipo. Os algoritmos que lidam com streams tratam de maneira sequencial do dados: abrir o stream enquanto houver informação ler informação fechar o stream O pacote java.io possui classes que tratam e criam os streams. Basicamente, temos streams para leitura de caracteres e para leitura de bytes. Os primeiros possibilitam a leitura e escrita de palavras de 16 bits, e são originários da classe abstrata java.io.Reader e java.io.Writer. 12
  • 13. Os streams para leitura de bytes lidam com palavras de 8 bits, e são subclasses de java.io.InputStream e java.io.OutputStream. Os streams mais fáceis de entender são os relacionados a arquivos. Segue um exemplo de programa que copia um arquivo de um stream para outro. import java.io.*; public class Copy { public static void main(String[] args) throws IOException { File inputFile = new File("entrada.txt"); 13
  • 14. File outputFile = new File("saida.txt"); FileReader in = new FileReader(inputFile); FileWriter out = new FileWriter(outputFile); int c; while ((c = in.read()) != -1) out.write(c); in.close(); out.close(); } } Como podemos ver, o programa é muito simples. Ele abre um FileReader no arquivo entrada.txt e abre um FileWriter no arquivo saida.txt. O programa lê caracteres enquanto houver no stream de entrada e os escreve no stream de saída. Quando terminar, ele fecha ambos os streams. O assunto é um tanto extenso, e esse curso se propõe a passar apenas a idéia básica sobre o assunto. Temos capacidade de gerar ou ler streams com arquivos zipados, serializar objetos (artifício utilizado para comunicação remota) e mesmo acessar arquivos de maneira não sequencial. Introducao ao Swing O pacote Swing é parte da JavaTM Foundation Classes (JFC) na plataforma Java. Existe na linguagem como pacote de extensão desde a versão 1.1, e serve basicamente para auxiliar as pessoas a construirem GUI's (Guided User Interface). O Swing fornece todos os componentes básicos, de botões a tabelas. Seu primeiro Swing A maneira mais fácil de ensinar a utilizar o Swing mostrando código. Vamos a um programa bem simples, que exibe “Alo Mundo”. import javax.swing.*; public class HelloWorldSwing { public static void main(String[] args) { JFrame frame = new JFrame("HelloWorldSwing"); final JLabel label = new JLabel("Hello World"); frame.getContentPane().add(label); frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); frame.pack(); 14
  • 15. frame.setVisible(true); } } Esta é a aplicação mais simples que se pode escrever. Vamos analisar o código linha a linha. Inicialmente, como sempre, importamos os pacotes que iremos utilizar. No caso, javax.swing.*. A outra linha interessante é a onde se define nossa raiz, ou container. Ele é o elemento principal, e onde iremos “dependurar” tudo que queremos que apareca em nossa tela. No nosso caso, eh o JFrame. Ele permite que outros componentes sejam adicionados a ele, e tem a capacidade de gerenciar eventos. Existem outros 2 containers Swing: JDialog e JApplet (esse último, utilizado apenas para Applets). Cada objeto JFrame implementa uma única janela principal, que possui decorações. Elas são a borda, o título e botões para maximizar, minimizar e fechar a janela. Uma aplicação Swing usa normalmente pelo menos um JFrame. Nosso frame tem um componente. Um label, onde escrevemos “Alo Mundo”. As duas linhas de código abaixo constroem e adicionam o componente ao frame: final JLabel label = new JLabel("Hello World"); frame.getContentPane().add(label); Para fechar a janela quando o botão de fechar é clicado, devemos incluir a linha abaixo no nosso programa: frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); O comportamento padrão de um frame quando o botão de fechar é clicado é esconder a janela, coisa que não desejamos. A linha onde consta o método pack() determina o tamanho do frame de modo que todos os componentes estejam em um tamanho padrão. Esse método utiliza algumas propriedades do sistema para criar e colocar o frame em um tamanho considerado adequado. A última linha, que chama o método setVisible(), faz com que o frame apareça na tela. Veja o resultado: 15
  • 16. Notas sobre o Swing: Para aparecer na tela, todos os componentes devem ser adicionados e estarem presentes em alguma parte de hierarquia, que se inicia na raiz (JFrame, JDialog ou JApplet). Todos os componentes raiz possuem um content pane, que contém a parte visível do que estamos montando, como mostrado na figura abaixo: Opcionalmente, você pode adicionar um menu a um componente raiz. O menu é posicionado diretamente na raiz, fora do content pane. Bibliografia The Java Tutorial – http://www.sun.com/docs Core Java – Horstmann, Cay S., Cornell, Gary. Makron Books Proibida a alteração, reprodução e cópia de parte deste material para qualquer finalidade sem a permissão do Centro de Computação da Unicamp. A utilização deste material é permitida desde que conste a autoria do mesmo. © 2002 Centro de Computação da Unicamp. 16