Prévia do material em texto
Introduc¸a˜o a` Linguagem de Programac¸a˜o Java Andre´ Leon S. Gradvohl, M.Sc. Centro Nacional de Processamento de Alto Desempenho em Sa˜o Paulo Universidade Estadual de Campinas Dezembro 2008, Versa˜o 1.2 Em portugueˆs: Copyright c©2008 ANDRE LEON S. GRADVOHL & CENTRO NACIONAL DE PROCESSAMENTO DE ALTO DESEMPENHO EM SA˜O PAULO. E´ permitida a co´pia, distribuic¸a˜o ou alterac¸a˜o deste documento sob os termos da Licenc¸a de Documentac¸a˜o Livre GNU, Versa˜o 1.2 ou qualquer versa˜o posterior publicada pela Fundac¸a˜o Software Livre; sem Sec¸o˜es Invariantes, nem Textos de Capa, nem Textos de Contra-Capa. Uma co´pia da licenc¸a pode ser obtida em http://www.gnu.org/licenses /fdl.html. In English: Copyright c©2008 ANDRE LEON S. GRADVOHL & CENTRO NACIONAL DE PROCESSAMENTO DE ALTO DESEMPENHO EM SA˜O PAULO. Permission is granted to copy, distribute and/or modify this document under the terms of the GNU Free Documentation License, Version 1.2 or any later version published by the Free Software Foundation; with no Invariant Sections, no Front-Cover Texts, and no Back- Cover Texts. A copy of the license may be obtained in http://www.gnu.org/licenses /fdl.html. Prefa´cio Muito material existe sobre Java, tanto sobre sua arquitetura quanto sobre a linguagem em si. Enta˜o, por qual motivo se escreve mais um texto a respeito? O objetivo deste material bibliogra´fico e´ dar suporte dida´tico a um curso de curta durac¸a˜o ou servir como base a cursos de maior durac¸a˜o em Java e, em particular, Programac¸a˜o Orientada a Objetos. Java e´ um assunto muito abrangente e cheio de minu´cias em diversas a´reas tecnolo´gicas. Por exemplo, pode-se usar Java em dispositivos sem fio (“wireless”), em dispositivos embarcados (“embedded devices”), para processamento multimı´dia, em televisa˜o interativa, em redes de com- putadores, entre va´rias outras a´reas. A proposta de portabilidade e facilidade de uso prometida pelo Java parece estar sendo cumprida. Essa afirmac¸a˜o pode ser comprovada pela quantidade de publicac¸o˜es que, direta ou indiretamente, citam Java e dos inu´meros sistemas que o utilizam. Apesar de ser um assunto vasto, esse material na˜o pretende ser ta˜o abrangente ou profundo nos conhecimentos sobre Java. Na verdade, o texto pretende mostrar os principais conceitos en- volvidos na arquitetura Java e programac¸a˜o orientada a objetos, bem como demonstrar algumas pra´ticas de programac¸a˜o mais comuns na linguagem. Sendo assim espera-se - ou melhor, deseja-se - que este texto sirva como ponto de partida para maiores incurso˜es neste campo de conhecimento. Para tentar tornar o texto mais motivante, algumas citac¸o˜es de filmes cla´ssicos foram acrescentadas. Tente entender o motivo dessas citac¸o˜es durante a leitura do texto! Bom proveito e boa leitura! i Suma´rio Prefa´cio . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . i Lista de Figuras . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . v Lista de Tabelas . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . vii 1 Introduc¸a˜o 1 1.1 Convenc¸o˜es adotadas . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 2 1.2 Estrutura do Texto . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 3 2 Arquitetura Java 4 2.1 Aplicac¸o˜es X Applets . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 5 2.2 Compilac¸a˜o e Execuc¸a˜o de Programas Java . . . . . . . . . . . . . . . . . . . . . . 6 3 Conceitos de Programac¸a˜o Orientada a Objetos 9 3.1 Conceitos Iniciais . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 10 3.1.1 Restric¸o˜es aos me´todos e atributos . . . . . . . . . . . . . . . . . . . . . . 10 3.2 Conceitos Espec´ıficos . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 11 4 Primeiras Frases na Linguagem Java 13 4.1 O Primeiro Programa . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 13 4.2 Tipos Primitivos . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 14 4.2.1 Declarac¸a˜o de Varia´veis . . . . . . . . . . . . . . . . . . . . . . . . . . . . 15 ii CENAPAD-SP Introduc¸a˜o a` Linguagem de Programac¸a˜o Java 4.3 Arranjos . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 15 4.3.1 Tamanho de um Arranjo . . . . . . . . . . . . . . . . . . . . . . . . . . . . 17 4.4 Operadores . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 17 4.4.1 Operadores Aritme´ticos . . . . . . . . . . . . . . . . . . . . . . . . . . . . 17 4.4.2 Operadores Relacionais e Condicionais . . . . . . . . . . . . . . . . . . . . 17 4.4.3 Operadores de Atribuic¸a˜o . . . . . . . . . . . . . . . . . . . . . . . . . . . 18 4.5 Estruturas de Decisa˜o . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 18 4.5.1 Comando if . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 19 4.5.2 Comando switch . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 20 4.6 Estruturas de Repetic¸a˜o . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 21 4.6.1 Comando while . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 21 4.6.2 Comando do-while . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 21 4.6.3 Comando for . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 21 4.6.4 Comandos de Desvio de Fluxo . . . . . . . . . . . . . . . . . . . . . . . . . 22 4.7 Comenta´rios em Java . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 22 4.8 Importando Classes Existentes . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 23 4.9 Exemplo Geral . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 23 5 Especificando Classes, Instanciando Objetos 27 5.1 Especificac¸a˜o da Classe . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 28 5.1.1 Me´todo Construtor . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 28 5.1.2 Me´todo Destrutor . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 29 5.1.3 Operadores this e super . . . . . . . . . . . . . . . . . . . . . . . . . . . 30 5.1.4 Implementac¸a˜o de Me´todos . . . . . . . . . . . . . . . . . . . . . . . . . . 30 5.1.5 Sobrecarga de Me´todos . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 31 5.1.6 Me´todos esta´ticos . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 32 5.2 Instanciac¸a˜o de Objetos . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 33 5.2.1 Operador new . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 33 5.3 Exemplo Geral . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 34 iii CENAPAD-SP Introduc¸a˜o a` Linguagem de Programac¸a˜o Java 6 Tratamento de Excec¸o˜es 40 6.1 Cla´usulas try-catch . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 41 6.2 Cla´usulas throws e throw . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 42 6.3 Classe Exception . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 43 7 Entrada e Sa´ıda 44 7.1 Streams ou Fluxos . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 44 7.2 Fluxos de Caracteres . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 45 7.2.1 Exemplo de Fluxo de Caracteres . . . . . . . . . . . . . . . . . . . . . . . . 47 7.3 Fluxo de Bytes . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 52 7.3.1 Exemplo de Fluxo de Bytes . . . . . . . . . . . . . . . . . . . . . . . . . . 53 8 Interfaces Gra´ficas 56 8.1 Janelas, o ba´sico . . . . . . . . . . . . . . . . . . .. . . . . . . . . . . . . . . . . 56 8.2 “Look and Feel” . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 58 8.3 Tratamento de Eventos . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 58 8.4 Gerenciadores de Layout . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 60 8.5 “Menus” . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 66 8.6 Campos e A´reas de Texto . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 67 9 Applets 71 9.1 Ciclo de Vida dos Applets . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 72 9.2 Passagem de Outros Paraˆmetros . . . . . . . . . . . . . . . . . . . . . . . . . . . . 72 Refereˆncias Bibliogra´ficas 77 iv Lista de Figuras 2.1 Arquitetura Java . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 5 2.2 Especificac¸a˜o das varia´veis de ambiente do Java . . . . . . . . . . . . . . . . . . . 7 4.1 Primeiro programa em Java. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 14 4.2 Segundo programa em Java. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 16 4.3 Programa em Java que calcula o nu´mero de paraˆmetros na linha de comando. . . 17 4.4 Programa que exemplifica a maioria dos to´picos abordados neste cap´ıtulo. . . . . . 24 4.5 Continuac¸a˜o do Programa da Figura 4.4. . . . . . . . . . . . . . . . . . . . . . . . 25 5.1 Classe NumeroComplexo, utilizada para exemplificar os to´picos deste cap´ıtulo. . . . 35 5.2 Continuac¸a˜o da Classe NumeroComplexo. . . . . . . . . . . . . . . . . . . . . . . . 36 5.3 Segunda continuac¸a˜o da Classe NumeroComplexo. . . . . . . . . . . . . . . . . . . 37 5.4 Terceira continuac¸a˜o da Classe NumeroComplexo. . . . . . . . . . . . . . . . . . . 38 5.5 Quarta continuac¸a˜o da Classe NumeroComplexo. . . . . . . . . . . . . . . . . . . . 39 5.6 Classe Main, que utiliza a classe NumeroComplexo. . . . . . . . . . . . . . . . . . . 39 7.1 ClasseNumeraLinhas, utilizada para mostrar classes que tratam o fluxo de caracteres. 48 7.2 Continuac¸a˜o da classe NumeraLinhas. . . . . . . . . . . . . . . . . . . . . . . . . . 49 7.3 Me´todo de finalizac¸a˜o da da classe NumeraLinhas. . . . . . . . . . . . . . . . . . . 50 7.4 Me´todo main da classe NumeraLinhas. . . . . . . . . . . . . . . . . . . . . . . . . 51 v CENAPAD-SP Introduc¸a˜o a` Linguagem de Programac¸a˜o Java 7.5 Escrita de um objeto da classe NumeroComplexo em um arquivo. . . . . . . . . . . 54 7.6 Leitura de um objeto da classe NumeroComplexo de um arquivo. . . . . . . . . . . 55 8.1 Programa que ilustra a criac¸a˜o de uma janela. . . . . . . . . . . . . . . . . . . . . 58 8.2 Programa que ilustra a criac¸a˜o de uma janela. . . . . . . . . . . . . . . . . . . . . 59 8.3 Classe EventoBotao que trata os eventos do bota˜o no programa anterior. . . . . . 60 8.4 Implementac¸a˜o da janela cujo bota˜o tera´ os eventos capturados. . . . . . . . . . . 61 8.5 Exemplo de BorderLayout. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 62 8.6 Exemplo de BoxLayout . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 63 8.7 Exemplo de FlowLayout . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 64 8.8 Exemplo de GridLayout . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 65 8.9 In´ıcio do exemplo de GridBagLayout . . . . . . . . . . . . . . . . . . . . . . . . . 66 8.10 Continuac¸a˜o do exemplo de GridBagLayout . . . . . . . . . . . . . . . . . . . . . 67 8.11 Exemplo de Menu . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 68 8.12 In´ıcio do programa que exemplifica a utilizac¸a˜o de objetos de texto. . . . . . . . . 69 8.13 Continuac¸a˜o do programa que exemplifica a utilizac¸a˜o de objetos de texto. . . . . 70 9.1 Applet simples . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 73 9.2 Pa´gina HTML que embute o applet da Figura 9.1. . . . . . . . . . . . . . . . . . . 74 9.3 Applet simples com passagem de paraˆmetros. . . . . . . . . . . . . . . . . . . . . 75 9.4 Pa´gina HTML que embute o applet da Figura 9.3. . . . . . . . . . . . . . . . . . . 76 vi Lista de Tabelas 3.1 Tipos de restric¸o˜es a me´todos e atributos . . . . . . . . . . . . . . . . . . . . . . . 11 4.1 Tipos primitivos de dados e suas caracter´ısticas. . . . . . . . . . . . . . . . . . . . 15 4.2 Operadores aritme´ticos. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 18 4.3 Operadores relacionais. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 18 4.4 Operadores condicionais. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 19 4.5 Operadores de atribuic¸a˜o. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 19 7.1 Subclasses da classe Reader e suas descric¸o˜es. . . . . . . . . . . . . . . . . . . . . 45 7.2 Me´todos da classe Reader e herdados por suas subclasses. . . . . . . . . . . . . . 45 7.3 Subclasses da classe Writer e suas descric¸o˜es. . . . . . . . . . . . . . . . . . . . . 46 7.4 Me´todos da classe Writer e herdados por suas subclasses. . . . . . . . . . . . . . 46 7.5 Subclasses da classe InputStream e suas descric¸o˜es. . . . . . . . . . . . . . . . . . 52 7.6 Me´todos da classe InputStream e herdados por suas subclasses. . . . . . . . . . . 52 7.7 Subclasses da classe OutputStream e suas descric¸o˜es. . . . . . . . . . . . . . . . . 53 7.8 Me´todos da classe OutputStream e herdados por suas subclasses. . . . . . . . . . 53 8.1 Tipos de “Listeners” e seus respectivos eventos t´ıpicos. . . . . . . . . . . . . . . . 60 8.2 Alguns atributos das ce´lulas no GridBagLayout . . . . . . . . . . . . . . . . . . . 66 vii CAP´ITULO 1 Introduc¸a˜o “Diferente apenas na sua mente e´. Desaprender aquilo que aprendeu voceˆ deve” Mestre Yoda, em “Star Wars V: The Empire Strikes Back”,1980. Desde o in´ıcio da histo´ria da humanidade, os homens procuram criar utens´ılios para auxilia´- los nas tarefas dia´rias. Quanto mais gene´ricas sa˜o essas ferramentas, i.e. quanto mais problemas elas conseguem resolver sozinhas, mais u´teis sa˜o. Esse e´ o objetivo da arquitetura Java: ser uma ferramenta gene´rica, fa´cil, capaz de resolver o maior nu´mero de problemas poss´ıveis, na maior quantidade de a´reas poss´ıveis. Para conseguir essa proeza, a arquitetura Java foi concebida para ser multiplataforma, ou seja, foi implementada para funcionar em diferentes combinac¸o˜es de hardware e software ba´sico (leia- se sistema operacional). O objetivo e´ permitir que as aplicac¸o˜es desenvolvidas na arquitetura sejam escritas apenas uma vez e executadas em qualquer lugar, qualquer ma´quina. Esse conceito e´ denominado, em ingleˆs, de “write-once, run anywhere”. No bom portugueˆs, isto significa portabilidade. Mais do que porta´vel, o desenvolvimento de aplicac¸o˜es na arquitetura Java deveria ser ra´pida e reaproveita´vel, sempre que poss´ıvel. O paradigma que, na˜o por acaso, mais se adequava a esses 1 CENAPAD-SP Introduc¸a˜o a` Linguagem de Programac¸a˜o Java requisitos era o paradigma de programac¸a˜o orientada a objetos (POO). Assim, juntando todos esses requisitos e conceitos, James Goslin, empregado da SUN Microsystems, criou a arquitetura Java em 1995. Contudo algue´m poderia questionar o porqueˆ de se falar em arquitetura e na˜o da linguagem Java. A resposta e´ que a linguagem e´ apenas um componente da arquitetura Java. A ide´ia e´ complexa para tornar as tarefas simples. No decorrer do texto, todas as du´vidas a esse respeito tentara˜o ser sanadas. Por ora, vale ressaltar que a maior parte do texto concentra-se na linguagem e na˜o na arquitetura Java. Quanto a` linguagem, o objetivo deste texto e´ apresenta´-la ao leitor e mostrarum pouco das bibliotecas mais utilizadas. O texto na˜o pretende se aprofundar em detalhes da arquitetura, tampouco das bibliotecas. Pore´m, ao final do texto, espera-se que o leitor tenha assimilado o mı´nimo necessa´rio para poder desenvolver-se sozinho aprendendo cada vez mais sobre o poder da linguagem Java. 1.1 Convenc¸o˜es adotadas Para facilitar a leitura do texto, algumas convenc¸o˜es foram adotadas. Sa˜o elas: • Palavras estrangeiras sa˜o grafadas entre aspas e em ita´lico, e. g. “threads”. • Comandos ou trechos de programas sa˜o grafados em fonte diferenciada, por exemplo void. Ressalta-se que esse texto na˜o pressupo˜e v´ınculo nenhum do Java com qualquer sistema operacional. Entretanto, todos os testes foram feitos tendo como base o sistema operacional Linux (RedHat, versa˜o 9.0). Sendo assim, na˜o ha´ garantias de que os exemplos funcionara˜o em outro sistema. Outro detalhe diz respeito a` versa˜o da plataforma Java. Na e´poca do desenvolvimento deste texto, a versa˜o esta´vel da plataforma Java utilizada foi a J2SE 1.4.2. Uma outra versa˜o da plataforma ja´ estava em sua versa˜o Beta: a J2SE 1.6. Contudo, optou-se por focalizar o texto na u´ltima versa˜o esta´vel. 2 CENAPAD-SP Introduc¸a˜o a` Linguagem de Programac¸a˜o Java 1.2 Estrutura do Texto O texto foi estruturado da seguinte forma. • O Cap´ıtulo 2 trata brevemente da filosofia Java, ale´m de se explicar como ocorre a com- pilac¸a˜o e a execuc¸a˜o de programas escritos nessa linguagem. • Os conceitos de programac¸a˜o orientada a objetos sa˜o apresentados brevemente no Cap´ıtulo 3. • No Cap´ıtulo 4 sa˜o apresentados os operadores, tipos e comandos ba´sicos da linguagem Java. • O in´ıcio da pra´tica na POO e´ no Cap´ıtulo 5, onde se explica como ocorre a definic¸a˜o de classes e instanciac¸a˜o de objetos com um exemplo pra´tico. • O tratamento de excec¸o˜es e´ mostrado no Cap´ıtulo 6. • O Cap´ıtulo 7 dedica-se a`s classes relativas a entrada e sa´ıda de dados. • As estruturas mais comuns para implementac¸a˜o de interfaces gra´ficas sa˜o descritas breve- mente no Cap´ıtulo 8. • Finalmente, ra´pidos comenta´rios a respeito de applets sa˜o apresentados no Cap´ıtulo 9 3 CAP´ITULO 2 Arquitetura Java “Eu gosto de voceˆ. Ate´ entendo voceˆ de vez em quando. Mas na˜o vou investir meus sentimentos em uma ma´quina” Portia Martin falando para o roboˆ Andrew em “O homem bicentena´rio”, 1999. A arquitetura ou plataforma Java tem, basicamente, dois componentes: a ma´quina virtual Java (JVM) e a interface de programac¸a˜o de aplicac¸o˜es (“Application Programming Interface” - API). A JVM, como o pro´prio nome diz, emula um ambiente computacional. A ma´quina virtual e´ a principal responsa´vel pela portabilidade que a plataforma Java proveˆ, pois uma vez instalada em um ambiente computacional real, qualquer programa Java pode ser executado sobre a JVM. As APIs por sua vez sa˜o equivalentes a`s bibliotecas. Elas teˆm grande utilidade para as aplicac¸o˜es Java pois trazem uma se´rie de funcionalidades ja´ prontas para serem usadas, evitando assim reinventa´-las. Os programas compilados em Java geram um arquivo .class contendo os chamados “by- tecodes”. Os “bytecodes” sa˜o uma espe´cie de co´digo assembler para a JVM. Esse co´digo ja´ 4 CENAPAD-SP Introduc¸a˜o a` Linguagem de Programac¸a˜o Java esta´ otimizado para a JVM que, por sua vez, o interpreta gerando comandos espec´ıficos para o hardware em que esta´ instalada. Por isso se diz que os programas Java sa˜o compilados e interpretados. Ha´ ainda a questa˜o do co´digo nativo, que pode ser chamado a partir de um co´digo Java (“by- tecodes”). O co´digo nativo e´ pro´prio da ma´quina que o executa. Portanto, na˜o e´ recomenda´vel a utilizac¸a˜o desse tipo de co´digo nas aplicac¸o˜es. Essa ac¸a˜o retira a principal caracter´ıstica da plataforma Java: a portabilidade. A Figura 2.1 mostra qual a relac¸a˜o entre esses componentes. JVM Codigo Nativo Bytecodes Sistema Operacional Hardware Figura 2.1: Arquitetura Java 2.1 Aplicac¸o˜es X Applets Os programas desenvolvidos em Java podem estar embutidas em pa´ginas da “World Wide Web” (WWW), chamados “applets”, ou serem aplicac¸o˜es que sa˜o executadas independente da WWW - chamadas aplicac¸o˜es “standalone”. Lembre-se que para serem executados, tanto os “applets” quanto as aplicac¸o˜es precisam da ma´quina virtual. Mas e se a JVM estiver embutida no pro´prio navegador (“browser”) utilizado? E´ exatamente dessa forma que ocorre! A ma´quina virtual e´ um “plug-in”, um software acoplado ao navegador que permite que os “bytecodes” sejam interpretados em uma a´rea dentro da pa´gina WWW sendo visualizada. Obviamente, sem esse “plug-in”, chamado “Java Runtime 5 CENAPAD-SP Introduc¸a˜o a` Linguagem de Programac¸a˜o Java Environment” (JRE), nenhum co´digo Java pode ser interpretado dentro da pa´gina WWW. Ale´m da diferenc¸a expl´ıcita nos para´grafos anteriores, ha´ outra muito importante: a questa˜o da seguranc¸a. No caso dos “applets”, eles funcionam na chamada “sandbox”1. Dentro da “sand- box” tudo e´ permitido. Mas fora dela, existem va´rias restric¸o˜es. As mais comuns sa˜o: impossibi- lidade de gravar conteu´do no disco r´ıgido e impossibilidade de abrir “sockets” ou qualquer outra forma de comunicac¸a˜o. Com isso, os “applets” Java ganharam muita fama na internet. As aplicac¸o˜es na˜o possuem nenhum tipo restric¸a˜o imposta pela JVM. As restric¸o˜es feitas a`s aplicac¸o˜es sa˜o as mesmas impostas pelo sistema operacional a` ma´quina virtual. 2.2 Compilac¸a˜o e Execuc¸a˜o de Programas Java Conforme ja´ mencionado, um co´digo em Java e´ compilado e interpretado. Sendo assim, o primeiro passo depois de se escrever um programa em Java e´ traduz´ı-lo para “bytecodes”. Isto e´ feito com o compilador Java que ja´ vem com o kit padra˜o de desenvolvimento (“Standard Development Kit” - SDK) A sintaxe mı´nima de compilac¸a˜o e´ a seguinte: javac -classpath /meuDir meuArquivo.java Observe quais sa˜o os elementos que compo˜em a sintaxe do comando. • javac e´ o compilador Java. • -classpath especifica onde sera˜o encontrados os arquivos .class. • /meuDir e´ o direto´rio onde esta˜o os arquivos .class utilizados • meuArquivo.java conte´m o programa a ser compilado. Os itens -classpath /meuDir sa˜o opcionais. Eles servem para especificar em que direto´rio esta˜o outros arquivos .class que fazem parte da sua aplicac¸a˜o. Para evitar incluir essa in- formac¸a˜o sempre que precisar compilar o programa, o ideal e´ que se defina a varia´vel de ambiente CLASSPATH. 1“Sandbox” ou caixa de areia em portugueˆs, e´ um local onde as crianc¸as podem brincar a vontade, sem a possibilidade de danificar objetos fora da caixa. 6 CENAPAD-SP Introduc¸a˜o a` Linguagem de Programac¸a˜o Java E´ no caminho especificado na varia´vel de ambiente CLASSPATH que o compilador Java vai buscar todos os arquivos e bibliotecas necessa´rios para a sua aplicac¸a˜o. Ale´m da CLASSPATH, a varia´vel de ambiente PATH tambe´m tem papel importante. E´ com base no caminho especifi- cado nessa varia´vel que se encontram os arquivos executa´veis (programas). Provavelmente, essa varia´vel ja´ se encontra definida em seu sistema operacional. Ainda assim, e´ poss´ıvel altera-la. Em sistemas operacionais Linux (usando o bash shell), recomenda-se que se configure as varia´veis de ambiente de acordo com a Figura 2.2: JAVA_HOME="diretorio_do_java" PATH=${PATH}:${JAVA_HOME}/bin CLASSPATH=${JAVA_HOME}/lib:. Figura 2.2: Especificac¸a˜o das varia´veis de ambiente do Java A varia´vel JAVA HOME especifica em que direto´rio foi instalado o Java SDK (as aspas na˜o devem ser inclu´ıdas). A varia´vel PATH acrescenta a` si mesma o direto´rio bin que esta´ dentro do direto´rioonde foi instalado o Java SDK. Finalmente, a varia´vel CLASSPATH e´ composta do direto´rio lib que esta´ dentro do direto´rio onde foi instalado o Java SDK e do direto´rio atual (representado pelo “.”), onde provavelmente esta˜o os arquivos compilados. Esse mesmo esquema da Figura 2.2 pode ser inclu´ıdo no seu arquivo de inicializac¸a˜o. Facili- tando assim o uso futuro. Esquema semelhante pode ser feito no sistema operacional Windows. Atente apenas para o fato de usar “;” ao inve´s de “:” como separador de direto´rios, tal como na especificac¸a˜o da varia´vel PATH, por exemplo. Uma vez compilado sem erros, o compilador java deve gerar um arquivo com o mesmo nome do arquivo fonte, mas com a extensa˜o .class. Supondo que seja uma aplicac¸a˜o e na˜o um “applet”, a sintaxe para executar esse programa e´ a seguinte: java -classpath /meuDir meuArquivo arg1 arg2 arg3 Onde • java e´ a ma´quina virtual Java. 7 CENAPAD-SP Introduc¸a˜o a` Linguagem de Programac¸a˜o Java • -classpath especifica onde sera˜o encontrados os arquivos .class. • /meuDir e´ o direto´rio onde esta˜o os arquivos .class utilizados • meuArquivo e´ o nome do programa (arquivo que conte´m os “bytecodes” sem a extensa˜o .class. • arg1 arg2 arg3 sa˜o os argumentos para o programa. Note que e´ opcional a utilizac¸a˜o de -classpath /meuDir, se a varia´vel CLASSPATH ja´ estiver sido definida. Sa˜o opcionais tambe´m os argumentos arg1 arg2 arg3. No caso dos “applets” a compilac¸a˜o ocorre da mesma forma. Pore´m, como sua execuc¸a˜o requer a utilizac¸a˜o de um navegador, a execuc¸a˜o torna-se um pouco diferente. No Cap´ıtulo 9, esse assunto sera´ tratado. 8 CAP´ITULO 3 Conceitos de Programac¸a˜o Orientada a Objetos “Receio que tudo o que fizemos foi acordar um gigante adormecido.” Almirante Yamamoto em “Pearl Harbor”, 2001. A programac¸a˜o orientada a objetos (POO) e´ um conceito relativamente antigo, que nasceu antes de 1990. Smalltalk foi uma das primeiras linguagens puramente orientada a objetos. Depois dela Eiffel, Java e outras seguiram essa linha. Entretanto, nem todas puramente orientada a objetos, como o C++, por exemplo. Mas o que difere a programac¸a˜o orientada a objetos da programac¸a˜o convencional, chamada estruturada? A diferenc¸a esta´ na relac¸a˜o entre as estruturas de dados e as rotinas para processa´- los. Na programac¸a˜o estruturada, os dados esta˜o em estruturas separadas das rotinas que os tratara˜o. Em outras palavras, sa˜o declaradas as estruturas de dados em uma parte do programa e as rotinas em outra. Na POO, dados e processamento esta˜o fortemente ligados. Tanto que sa˜o encapsulados em estruturas chamadas classes. As classes contera˜o as estruturas de dados e o co´digo para lidar com essas estruturas em uma u´nica unidade lo´gica por assim dizer. Na abordagem orientada a objetos, e´ mais fa´cil implementar a reutilizac¸a˜o de co´digo. Ale´m 9 CENAPAD-SP Introduc¸a˜o a` Linguagem de Programac¸a˜o Java disso, a forma como os sistemas sa˜o analisados e projetados tambe´m torna-se diferente. Nas pro´ximas sec¸o˜es, os conceitos sera˜o explicados com mais detalhes. 3.1 Conceitos Iniciais Antes de entrar em conceitos mais complexos de POO, e´ preciso comec¸ar pelos mais simples. O primeiro deles e´ o conceito de classes de objetos - ou simplesmente classes. Classes sa˜o unidades que conte´m estruturas de dados e co´digo. As estruturas de dados da classe sa˜o chamadas de atributos, enquanto as rotinas para lidar com essas estruturas sa˜o chamadas me´todos. Para ficar mais claro, imagine que se deseja modelar a classe de objetos “triaˆngulo”. Que atributos poderiam existir em uma classe de objetos “triaˆngulo”? Como exemplo, pode-se ter como atributos basicamente os seguintes itens: comprimento do primeiro lado; comprimento do segundo lado; comprimento do terceiro lado; cor do triaˆngulo. Quais seriam os me´todos dessa classe? Poderiam ser, talvez, os seguintes: alterar primeiro lado; verificar segundo lado; calcular a a´rea do triaˆngulo; verificar a cor do triaˆngulo; entre outros. Note que, mesmo teoricamente, os me´todos esta˜o fortemente ligados aos atributos. Ou seja, os me´todos proveˆem as ferramentas para a manipulac¸a˜o do pro´prio objeto atrave´s dos seus atributos. Mas qual a relac¸a˜o entre um objeto e uma classe? A resposta e´ que um objeto e´ uma instaˆncia de uma classe, i. e. a classe e´ uma definic¸a˜o, enquanto o objeto e´ a materializac¸a˜o (em termos computacionais) dessa definic¸a˜o. 3.1.1 Restric¸o˜es aos me´todos e atributos Ora, mas tal como um objeto real, o objeto computacional pode ter me´todos ou atributos res- tritos. Em outras palavras, alguns me´todos ou atributos so´ sa˜o conhecidos e utilizados atrave´s de me´todos da pro´pria da classe ou daquelas classes cuja definic¸a˜o foi recebida como heranc¸a (conceito tratado adiante, na Sec¸a˜o 3.2). Existem basicamente treˆs formas de restringir os me´todos ou atributos de uma classe. A Tabela 3.1 a seguir explica as diferenc¸as. Desse modo, e´ poss´ıvel restringir o acesso dos me´todos 10 CENAPAD-SP Introduc¸a˜o a` Linguagem de Programac¸a˜o Java e atributos facilitando o encapsulamento. Palavra-chave Restric¸a˜o public Nenhuma. Os me´todos de qual- (pu´blico) quer classe podem acessar. protected Apenas os me´todos das sub- (protegido) classes podem acessar. private Apenas os me´todos da pro´pria (privado) classe podem acessar. Tabela 3.1: Tipos de restric¸o˜es a me´todos e atributos 3.2 Conceitos Espec´ıficos Entre os conceitos que tornam a POO mais forte esta´ o de encapsulamento, ja´ mencionado. Encapsulamento, nesse caso, e´ a criac¸a˜o de mo´dulos auto-suficientes, ou seja, que conte´m todos os me´todos e atributos necessa´rios para gerar informac¸a˜o solicitada e interagir com os demais objetos. Na verdade, o ato de encapsular co´digo significa estar escondendo detalhes da implementac¸a˜o de uma classe. A grande vantagem disso e´ a facilidade que o usua´rio vai ter em usar objetos de tal classe. Nesse caso, para o usua´rio o importante e´ que o objeto desempenhe a tarefa da melhor maneira poss´ıvel, independente de como e´ essa maneira. Outro conceito importante para a POO e que facilita a reutilizac¸a˜o de co´digo e´ o de heranc¸a. Esse conceito e´ o que permite que a definic¸a˜o de uma classe seja aproveitada por outra. Com isso, menos co´digo e´ necessa´rio, uma vez que as definic¸o˜es de me´todos e atributos podem ser reaproveitadas. Voltando ao exemplo da classe “triaˆngulo”, e´ poss´ıvel ter uma subclasse dessa que herda as caracter´ısticas dessa, e.g. a classe “triaˆngulo retaˆngulo”. Nessa nova subclasse, os atributos sera˜o os mesmos, mas e´ poss´ıvel acrescentar novos me´todos. Por exemplo, um me´todo para calcular a hipotenusa. Note que o conceito de heranc¸a foi utilizado para fazer a especializac¸a˜o de uma classe. Mas, 11 CENAPAD-SP Introduc¸a˜o a` Linguagem de Programac¸a˜o Java ao inve´s disso, pode ocorrer o contra´rio: a generalizac¸a˜o. Ou seja, pode-se acrescentar mais me´todos e atributos para tornar uma classe mais gene´rica. Em algumas linguagens de POO, e´ poss´ıvel utilizar o conceito de herenc¸a mu´ltipla, i.e. uma classe pode herdar de duas ou mais classes. A heranc¸a mu´ltipla e´ muito problema´tica pois se duas classes possu´ırem a mesma definic¸a˜o de um me´todo, mas implementac¸o˜es diferentes, qual das duas definic¸o˜es sera˜o aceitas? Para evitar esse conflito, a linguagem Java aceita apenas heranc¸a simples, ou seja, cada classe pode herdar de, no ma´ximo, outra classe. Outro conceito decorrente da heranc¸a e´ o polimorfismo. Observando a composic¸a˜o da palavra e´ poss´ıvel entender seu significado: “poli” e´ equivalente a “muitos” e “morfismo” a “forma”.Assim, no caso de POO, polimorfismo significa que um determinado me´todo pode assumir va´rias formas. Essas formas referem-se a` assinatura (ou proto´tipo) de um me´todo. A assinatura de um me´todo e´ composta dos seguintes itens: tipo de objeto retornado por esse me´todo; nome do me´todo; tipo de objetos passados como paraˆmetros. Um conjunto de me´todos polimo´rficos e´ aquele em que todos os me´todos possuem o mesmo nome, pore´m diferentes tipos de objeto de retorno ou paraˆmetros. Ha´ ainda o conceito de interface. No caso de Java o conceito de interface e´ u´til para garantir o relacionamento entre objetos de classes distintas sem utilizar heranc¸a. Na verdade, ao imple- mentar uma interface, a classe se obriga a implementar todos os me´todos daquela com a mesma assinatura especificada pela pro´pria interface. 12 CAP´ITULO 4 Primeiras Frases na Linguagem Java “Existe uma diferenc¸a entre saber o caminho e trilhar o caminho.” Morpheus em “Matrix”, 1999. Neste cap´ıtulo se inicia a parte pra´tica da linguagem Java. a ide´ia e´ tentar mostrar os tipos primitivos de dados (mais precisamente objetos), os comandos ba´sicos e inclusive comenta´rios. Sempre que poss´ıvel sera˜o ressaltados os conceitos de POO, mencionados nos cap´ıtulos anteriores. Ressalta-se ainda que a linguagem Java e´ “descendente” da linguagem C e portanto, ha´ diferenc¸a entre textos escritos com letras maiu´sculas e minu´sculas. Ale´m disso, a maioria dos comandos ba´sicos teˆm sintaxe similar a`queles da linguagem C. 4.1 O Primeiro Programa O primeiro programa em Java, como na˜o poderia deixar de ser, e´ uma aplicac¸a˜o simples que imprime uma mensagem na tela. Por enquanto, o ideal e´ concentrar-se na estrutura do programa ao inve´s dos comandos. Observe a Figura 4.1 a seguir. Sa˜o boas pra´ticas de programac¸a˜o manter o nome do arquivo com o mesmo nome da classe para evitar confuso˜es posteriores e usar a primeira letra maiu´scula nos nomes das classes. Essas 13 CENAPAD-SP Introduc¸a˜o a` Linguagem de Programac¸a˜o Java class Ola { public static void main(String[ ] args) { System.out.println("Ola Mundo!"); } } Figura 4.1: Primeiro programa em Java. pra´ticas sa˜o recomendadas pelos pro´prios autores da linguagem Java e adotados pela grande maioria dos programadores. Analisando o exemplo da Figura 4.1 percebe-se que a declarac¸a˜o da classe Ola. Nessa classe ha´ apenas o me´todo main. Esse me´todo e´ mandato´rio na classe principal da aplicac¸a˜o. E´ a partir dele que o programa iniciara´ sua execuc¸a˜o. A assinatura do me´todo main e´ sempre a mesma, ou seja ele e´ pu´blico (public), esta´tico (static) e na˜o retorna valores (void). Ale´m disso, ele recebe um arranjo (vetor) de “Strings” como paraˆmetro. Nesse arranjo de “Strings” esta˜o os paraˆmetros passados para a aplicac¸a˜o pela linha de comando. Dentro do me´todo main, o u´nico comando existente e´ a chamada do me´todo println, com a “String” “Ola Mundo!” como paraˆmetro. O me´todo println faz parte do objeto out que e´ atributo do objeto System. 4.2 Tipos Primitivos Como toda linguagem de programac¸a˜o de alto n´ıvel, Java tambe´m possui seus tipos primitivos de dados. A Tabela 4.1 a seguir mostra os tipos primitivos de dados, sua descric¸a˜o e tamanho. Note que, diferente da linguagem C, Java na˜o possui suporte para ponteiros (refereˆncias a` memo´ria). O objetivo dessa decisa˜o e´ tornar a linguagem mais fa´cil de usar. 14 CENAPAD-SP Introduc¸a˜o a` Linguagem de Programac¸a˜o Java Tipo Descric¸a˜o Tamanho void vazio zero boolean lo´gico 1 bit (false/true) byte inteiro 8 bits short inteiro 16 bits char caractere 16 bits int inteiro 32 bits float real 32 bits long inteiro 64 bits double real 64 bits Tabela 4.1: Tipos primitivos de dados e suas caracter´ısticas. 4.2.1 Declarac¸a˜o de Varia´veis Da mesma maneira que a linguagem C, a declarac¸a˜o de varia´veis em Java funciona especificando primeiro o tipo de dado e em seguida o identificador (nome) da varia´vel. Observe o programa da Figura 4.2. Nele, foram declaradas treˆs varia´veis de tipos diferentes. A primeira varia´vel (re) tem tipo float. A segunda (inte) tem tipo int e a terceira (carac) tem tipo textttfloat. Apesar de terem tipos diferentes, essas varia´veis sa˜o compat´ıveis. Contudo, note que na˜o ha´ problemas se uma varia´vel de menos abrangente (int por exemplo) for atribu´ıda a uma varia´vel de tipo mais abrangente (float por exemplo). Todavia, o contra´rio pode gerar erros, caso na˜o seja feita uma conversa˜o expl´ıcita de tipos. Ha´ tambe´m a possibilidade de se declarar varia´veis finais. Esse tipo de varia´vel funciona como uma constante. Por exemplo, se existisse a seguinte declarac¸a˜o: final char c;. Isso significa que c e´ uma constante do tipo char cujo valor final ainda na˜o foi atribu´ıdo. Depois que este valor for atribu´ıdo a` varia´vel, a mesma na˜o podera´ ser alterada. 4.3 Arranjos Arranjos (vetores ou “arrays” em ingleˆs) sa˜o estruturas de dados compostas, homogeˆneas e de tamanho fixo. Isto significa que em um espac¸o de memo´ria de tamanho fixo e cont´ınuo existem 15 CENAPAD-SP Introduc¸a˜o a` Linguagem de Programac¸a˜o Java class Ola { public static void main(String[ ] args) { float re; int inte = 0; char carac = ’a’; re = inte + carac; System.out.println("O valor de re eh:" + re ); } } Figura 4.2: Segundo programa em Java. va´rios objetos de um mesmo tipo. Como a pro´pria definic¸a˜o sugere, usa-se arranjo quando precisa-se armazenar um grupo de objetos do mesmo tipo em um espac¸o de memo´ria facilmente enderec¸a´vel. Para declarar um arranjo, e´ necessa´rio colocar colchetes (“[”,“]”) apo´s o tipo de objeto que o arranjo armazenara´. O ca´lculo de quantos objetos sera˜o armazenados e´ feito a posteriori, quando o arranjo for instanciado. Observe o exemplo a seguir, onde e´ criado um arranjo de nu´meros em ponto flutuante (float), com dez posic¸o˜es. float[ ] vetor = new float[10]; Observe tambe´m o exemplo da Figura 4.2 onde, na lista de paraˆmetros do me´todo main e´ declarado que args e´ um arranjo de Strings. O tamanho do arranjo sera´ calculado em tempo de execuc¸a˜o, dependendo de quantos paraˆmetros foram passados pela linha de comando. Para acessar um objeto em um arranjo de objetos, basta colocar entre colchetes a posic¸a˜o do respectivo objeto, como no exemplo a seguir. vetor[0] = 13.5; vetor[9] = 4.77; Note que a`s posic¸o˜es zero e nove do arranjo vetor foram atribu´ıdos os valores 13.5 e 4.77 respectivamente. Todos os arranjos em Java, se iniciam da posic¸a˜o zero. 16 CENAPAD-SP Introduc¸a˜o a` Linguagem de Programac¸a˜o Java 4.3.1 Tamanho de um Arranjo O tamanho de um arranjo pode ser obtido em tempo de execuc¸a˜o do programa. Lembre-se que o arranjo e´ um objeto e como tal tambe´m tem atributos. Um dos atributos de qualquer arranjo e´ seu tamanho, dado pelo atributo length. Veja como isto pode ser feito no programa ilustrado na Figura 4.3 a seguir: class Parametros { public static void main(String[ ] args) { int numeroParametros; numeroParametros = args.length; System.out.println("O numero de parametros eh:" + numeroParametros ); } } Figura 4.3: Programa em Java que calcula o nu´mero de paraˆmetros na linha de comando. 4.4 Operadores 4.4.1 Operadores Aritme´ticos A Tabela 4.2 a seguir, mostra a lista de operadores aritme´ticos dispon´ıveis na linguagem Java. 4.4.2 Operadores Relacionais e Condicionais Na Tabelas 4.3 e 4.4 a seguir, esta˜o as listas de operadores relacionais e condicionais dispon´ıveis na linguagem Java. Cuidado em relac¸a˜o aos operadores & e |. Quando os operandos que eles tratam forem valores inteiros, as operac¸o˜esrealizadas sa˜o feitas bit-a-bit. Ou seja, respectivamente “e” lo´gico e “ou” lo´gico. 17 CENAPAD-SP Introduc¸a˜o a` Linguagem de Programac¸a˜o Java Operador Exemplo Descric¸a˜o + op1 + op2 Soma op1 com op2. - op1 − op2 Subtrai op1 de op2. * op1 ∗ op2 Multiplica op1 com op2. / op1 / op2 Divide op1 por op2. % op1 % op2 Calcula o resto da divisa˜o de op1 por op2. ++ op1 + + Retorna o valor de op1 e em seguida o incrementa. + + op1 Incrementa op1 e em seguida retorna seu valor. -- op1−− Retorna o valor de op1 e em seguida o decrementa. −− op1 Decrementa op1 e em seguida retorna seu valor. Tabela 4.2: Operadores aritme´ticos. Operador Exemplo Retorna true se == op1 == op2 op1 for igual a op2. != op1 ! = op2 op1 for diferente de op2. > op1 > op2 op1 for maior que op2. >= op1 ≥ op2 op1 for maior ou igual op2. < op1 < op2 op1 for menor que op2. <= op1 ≤ op2 op1 for menor ou igual a op2. Tabela 4.3: Operadores relacionais. 4.4.3 Operadores de Atribuic¸a˜o Os operadores de atribuic¸a˜o em Java esta˜o descritos na Tabela 4.5 a seguir. 4.5 Estruturas de Decisa˜o Na maioria das linguagens de programac¸a˜o existem as chamadas estruturas de decisa˜o. Essas estruturas sa˜o comandos que permitem desviar o fluxo de controle do programa, com base em um teste pre´vio. Existem duas comandos ba´sicos que implementam essas estruturas: os comandos 18 CENAPAD-SP Introduc¸a˜o a` Linguagem de Programac¸a˜o Java Operador Exemplo Retorna true se && op1 && op2 se op1 e op2 forem ambos verdadeiros. op2 e´ avaliado se op1 for verdade. & op1 & op2 se op1 e op2 forem ambos verdadeiros. op1 e op1 sa˜o ambos avaliados. || op1 || op2 se op1 ou op2 forem verdadeiros. op2 e´ avaliado se op1 for falso. | op1 | op2 se op1 ou op2 forem verdadeiros. op1 e op1 sa˜o ambos avaliados. ! !op1 se o valor lo´gico de op1 for falso. ^ op1 ^ op2 se op1 e op2 forem diferentes entre si. Tabela 4.4: Operadores condicionais. Operador Exemplo Equivalenta a += op1 + = op2 op1 = op1 + op2. -= op1 − = op2 op1 = op1 − op2. /= op1 / = op2 op1 = op1 / op2. *= op1 ∗ = op2 op1 = op1 ∗ op2. %= op1 % = op2 op1 = op1 % op2. ?...: op1 = exp? op2 : op3 op1 = op2 se exp for verdade. op1 = op3 se exp for falso. Tabela 4.5: Operadores de atribuic¸a˜o. if e switch. 4.5.1 Comando if Como na linguagem C, existem duas formas ba´sicas do comando if. A primeira, mais simples, possui a seguinte sintaxe: if ( EXPRESS~AO ) COMANDOS 19 CENAPAD-SP Introduc¸a˜o a` Linguagem de Programac¸a˜o Java No lugar de EXPRESS~AO deve estar qualquer expressa˜o que retorne um valor lo´gico (true ou false). No lugar de COMANDOS deve existir um u´nico comando ou, noutro caso, um conjunto de comandos cercado por chaves (“{”e “}”), chamado bloco de comandos. Outra variante do comando if tem a seguinte sintaxe: if ( EXPRESS~AO ) COMANDOS1 else COMANDOS2 Essa variante funciona de forma similar a` primeira forma. Contudo o segundo bloco de comandos COMANDOS2 so´ sera´ executado caso a EXPRESS~AO seja false. Note que os pareˆnteses que cercam a EXPRESS~AO sa˜o obrigato´rios. 4.5.2 Comando switch Outra estrutura de decisa˜o comum a`s linguagens C e Java e´ a switch. Ela permite escolher entre va´rios valores poss´ıveis para uma determinada expressa˜o inteira. As varia´veis devem ser dos tipos ba´sicos, inteiro e caractere, mostrados na Tabela 4.1. A sintaxe do comando switch e´ a seguinte: switch(EXPRESSAO) { case VALOR1: COMANDOS_A case VALOR2: COMANDOS_B default: COMANDOS_C } O resultado da EXPRESSAO deve ser dos tipos inteiro ou caracter. De acordo com esse re- sultado, os case VALOR1 ou VALOR2 sera˜o escolhidos. A partir daquele que for escolhido, os comandos sera˜o executados. No caso da expressa˜o na˜o retornar nenhum valor especificado nos case, os comandos da cla´usula default sera˜o executados. Detalhes: os comandos ou blocos de comandos COMANDOS A, COMANDOS B e COMANDOS C na˜o precisam de chaves; e´ recomendada a utilizac¸a˜o do comando break ao final de cada bloco de comandos para evitar que outros blocos, fora da cla´usula escolhida sejam executados; a cla´usula default e´ opcional. 20 CENAPAD-SP Introduc¸a˜o a` Linguagem de Programac¸a˜o Java 4.6 Estruturas de Repetic¸a˜o Assim como as de decisa˜o, as estruturas de repetic¸a˜o tambe´m sa˜o comuns na maioria das lin- guagens de programac¸a˜o de alto n´ıvel. Existem basicamente treˆs tipos dessas estruturas, while, do-while e for, que sera˜o apresentadas a seguir. 4.6.1 Comando while O comando while testa uma determinada condic¸a˜o e enquanto ela for verdadeira, o bloco de comandos e´ repetido. sua sintaxe e´ a seguinte: while (EXPRESSAO) { COMANDOS } A EXPRESSAO deve retornar um valor lo´gico e, com base nesse valor, COMANDOS sa˜o executados. 4.6.2 Comando do-while O comando do while funciona de forma similar ao while. Entretanto, o teste da condic¸a˜o e´ feita ao final do lac¸o. Enquanto ela for verdadeira, o bloco de comandos e´ repetido. sua sintaxe e´ a seguinte: do { COMANDOS } while (EXPRESSAO); Os COMANDOS sa˜o executados pelo menos uma vez. A EXPRESSAO e´ avaliada e deve retornar um valor lo´gico e, com base nesse valor, o lac¸o e´ repetido. 4.6.3 Comando for O comando for e´ chamado de lac¸o contado, porque e´ poss´ıvel saber de antema˜o quantas vezes ele sera´ executado (na sua forma convencional). Na verdade, o comando for e´ composto de treˆs partes: a inicializac¸a˜o, a condic¸a˜o de te´rmino e o incremento ou decremento. Observe a sintaxe do comando: 21 CENAPAD-SP Introduc¸a˜o a` Linguagem de Programac¸a˜o Java for (INICIALIZACAO ; CONDICAO ; INCREMENTO) { COMANDOS } Normalmente usa-se uma varia´vel de controle do lac¸o. Essa varia´vel e´ inicializada no campo INICIALIZACAO. A condic¸a˜o de te´rmino e´ testada no campo CONDICAO e o incremento ou a` varia´vel de controle e´ feito no campo INCREMENTO. 4.6.4 Comandos de Desvio de Fluxo Existem ainda em java, alguns comandos de desvio de fluxo. Eles sa˜o usados geralmente em lac¸os para desviar o controle de fluxo para fora do lac¸o. Existem dois deles: continue e break. O comando continue, na sua forma sem ro´tulo, executa um desvio para o teste do lac¸o. No caso dos lac¸os com while, a EXPRESSAO e´ avaliada novamente; no for, a varia´vel de controle e´ incrementada e a condic¸a˜o reavaliada. Na forma rotulada e´ necessa´rio especificar um label (qualquer nome seguido de “:”). Nesse caso, o desvio e´ executado para o pro´ximo comando apo´s o label. Quanto ao comando break, conforme sugerido quando o comando case foi abordado, o desvio e´ efetuado para fora do bloco onde o comando esta´.Na sua forma rotulada, o desvio e´ feito para onde o label esta´. 4.7 Comenta´rios em Java Esta sec¸a˜o pode parecer dispensa´vel quando ha´ tanto a ser visto a respeito da linguagem Java. Entretanto, e´ noto´rio que um co´digo bem documentado pode ser muito u´til ate´ para o pro´prio programador. No caso da linguagem Java, o fato do co´digo estar bem comentado pode servir para gerar automaticamente a pro´pria documentac¸a˜o da aplicac¸a˜o. Assim como a linguagem C, Java con- sidera como comenta´rio tudo o que aparece a partir dos caracteres “/*” ate´ os caracteres “*/”. Do mesmo modo, toda linha que se inicia com “//” tambe´m e´ comenta´rio. Ha´ tambe´m uma outra forma de comentar co´digo em java. Tudo o que aparece a partir dos caracteres “/**” ate´ os caracteres “*/”, tambe´m e´ comenta´rio, mas pode ser interpretado pelo 22 CENAPAD-SP Introduc¸a˜o a` Linguagem de Programac¸a˜o Java javadoc, um programa que gera documentac¸a˜o automaticamente. Sempre que esses caracteres aparecem antes da definic¸a˜o de classes, me´todos ou atributos, a documentac¸a˜o e´gerada em uma pa´gina html. Para acessa´-la, abra o arquivo index.html que esta´ no direto´rio onde se encontra seu arquivo fonte. Observe a documentac¸a˜o do exemplo da Sec¸a˜o 4.9 e, como exemplo, gere a documentac¸a˜o automa´tica. Para isto, use a seguinte sintaxe: javadoc nomeArquivo.java Para mais informac¸o˜es execute o programa javadoc sem paraˆmetros. 4.8 Importando Classes Existentes As vezes e´ preciso aproveitar classes previamente existentes e assim fazer reutilizac¸a˜o de co´digo. Para fazer isto, utiliza-se a palavra reservada import seguida da classe que se quer importar. No decorrer do texto, exemplos disso ocorrera˜o. 4.9 Exemplo Geral Nesta sec¸a˜o e´ apresentado um programa exemplo que tenta abordar todos os to´picos tratados neste cap´ıtulo. Obviamente, este na˜o e´ o melhor programa em Java para calcular o fatorial de dois nu´meros. Mas e´ um bom exemplo para resumir tudo o que foi abordado neste cap´ıtulo. Observe os seguintes detalhes: 1. Quanto a` documentac¸a˜o: antes da definic¸a˜o da classe ExemploGeral, no comec¸o da Figura 4.4, e do me´todo main esta˜o os comenta´rios. Atente para os caracteres “/**” antes do in´ıcio e os caracteres “*/” ao final dos comenta´rios. Todo o texto cercado por esses caracteres aparecera´ na documentac¸a˜o gerada pelo javadoc. Veja a Sec¸a˜o 4.7, pa´gina 22 para mais detalhes. 2. No primeiro if que aparece na Figura 4.4 e´ utilizado o operador condicional &. Note que a utilizac¸a˜o do operador && poderia causar um “bug”. Ambas as condic¸o˜es devem ser analisadas e devem ser verdadeiras para que o bloco de comandos do if seja executado. Mais informac¸o˜es a esse respeito esta˜o na Sec¸a˜o 4.4.2, pa´gina 19. 23 CENAPAD-SP Introduc¸a˜o a` Linguagem de Programac¸a˜o Java /** * Classe de demonstracao. */ public class ExemploGeral { /** * Ha apenas esse metodo que calcula o fatorial de dois numeros */ public static void main(String[ ] args) { short n1, n2; long fatorial; n1 = 5; n2 = 105; fatorial = 1; if ( n1 >= 0 & n1 < Integer.MAX_VALUE ) { switch(n1) { case 0: case 1: break; default: for (int i=1; i<=n1; i++) fatorial = fatorial * i; } System.out.println("Fatorial de " + n1 + " eh: " + fatorial); } else System.out.println("Nao existe fatorial de numero negativo!"); Figura 4.4: Programa que exemplifica a maioria dos to´picos abordados neste cap´ıtulo. Continua na Figura 4.5. 3. MAX VALUE e´ um atributo da classe Integer. Isso pode gerar algumas du´vidas: se existe um tipo int, porque e´ preciso existir a classe Integer? Existe alguma relac¸a˜o entre o tipo e a classe? A mesma resposta server a`s duas perguntas: na˜o! Na verdade, a classe Integer faz parte das classes padra˜o do Java. Ela existe para facilitar o trabalho do programador. Por exemplo, nesse caso era preciso saber qual o maior valor inteiro capaz de ser representado. o atributo MAX VALUE, continha essa informac¸a˜o. 24 CENAPAD-SP Introduc¸a˜o a` Linguagem de Programac¸a˜o Java if (!(n2 >= 0)) System.out.println("Nao existe fatorial de numero negativo!"); else { int j=n2; fatorial = 1; while (j > 0) { fatorial *= j; if (fatorial <= Integer.MAX_VALUE) { j--; continue; } else { System.out.println("Nao ha memoria para armazenar o numnero"); break; } } if (j == 0) System.out.println("Fatorial de " + n2 + " eh: " + fatorial); } } } Figura 4.5: Continuac¸a˜o do programa que exemplifica a maioria dos to´picos abordados neste cap´ıtulo. 4. Na Figura 4.4, observe o comando break. Caso o valor de n1 seja zero ou um, sera˜o executados comandos ate´ encontrar o comando break. Ao encontra´-lo, e´ feito um desvio para fora do comando switch. Se o valor de n1 na˜o for nenhum dos valores citados, enta˜o a cla´usula default e´ executada. No caso do comando continue na Figura 4.5, ha´ um desvio para fora do lac¸o controlado pelo while. Com isso, ganha-se uma certa agilidade no programa. Mais detalhes podem ser vistos na Sec¸a˜o 4.6.4, pa´gina 22. 5. Ainda na Figura 4.4, observe que no pro´prio comando for ha´ uma declarac¸a˜o de varia´vel (int i). A declarac¸a˜o de varia´veis e´ poss´ıvel em qualquer parte de um programa Java. Ac¸a˜o semelhante ocorre na Figura 4.5, ao declarar a varia´vel j. Ressalta-se que, essas 25 CENAPAD-SP Introduc¸a˜o a` Linguagem de Programac¸a˜o Java varia´veis teˆm escopo (validade) limitado ao bloco de comandos onde foram declaradas e na˜o fazem parte dos atributos do objeto. 6. Finalmente, note o paraˆmetro passado para os me´todos println. E´ uma “soma” de objetos “String” com varia´veis inteiras. Pode parecer estranho, mas a classe “String” permite essa operac¸a˜o. A “soma” de uma “String” com uma varia´vel inteira, resulta em uma “String”. Mais detalhes sobre isso sera˜o exemplificados no Cap´ıtulo 5, Sec¸a˜o 5.1.5. 26 CAP´ITULO 5 Especificando Classes, Instanciando Objetos “Mama˜e sempre disse que a vida e´ como uma caixa de chocolates. Nunca se sabe o que voceˆ vai encontrar la´.” Forrest Gump em “Forrest Gump: o contador de esto´rias””, 1994. Neste cap´ıtulo o foco e´ a aplicac¸a˜o dos conceitos vistos no Cap´ıtulo 3. A ide´ia e´ mostrar como sa˜o especificadas as classes e como se instanciam os objetos. Lembrando que uma classe e´ uma especificac¸a˜o, enquanto um objeto e´ a materializac¸a˜o dessa especificac¸a˜o na memo´ria do computador. Vale ressaltar que toda classe especificada em Java herda suas definic¸o˜es de uma classe cha- mada Object. Como sa˜o todas subclasses de Object, isso significa que alguns me´todos ja´ esta˜o implementados. Esse me´todos podem ser sobrecarregados para obter comportamentos mais espe´ıficos. Para tornar mais claro as ac¸o˜es para especificac¸a˜o de classes e instanciac¸a˜o de objetos sera´ usado uma aplicac¸a˜o exemplo. O objetivo desse exemplo e´ criar a classe NumeroComplexo. 27 CENAPAD-SP Introduc¸a˜o a` Linguagem de Programac¸a˜o Java 5.1 Especificac¸a˜o da Classe Para ilustrar como as classes sa˜o especificadas, sera´ utilizado o exemplo da classe de nu´meros complexos. Como se sabe, um nu´mero complexo tem duas partes: uma parte real, e uma parte imagina´ria. Matematicamente, um nu´mero complexo ( ̂A) e´ representado da seguinte forma: ̂A = a + bi, onde i e´ o chamado operador imagina´rio e tem valor √−1; a e b sa˜o valores reais. A parte real de um nu´mero complexo e´ dada por ℜ[ ̂A] = a, enquanto a parte imagina´ria e´ dada por ℑm[ ̂A] = b. De posse das informac¸o˜es ba´sicas sobre nu´meros complexos, o pro´ximo passo e´ definir quais os atributos dessa classe. Observe a seguir o in´ıcio dessa especificac¸a˜o. public class NumeroComplexo { private double a; private double b; } Note que a classe NumeroComplexo e´ pu´blica. Isto significa que essa especificac¸a˜o pode ser acessada por qualquer outra classe. Contudo, seus dois atributos a e b sa˜o privados, ou seja, so´ podem ser utilizados dentro da definic¸a˜o da classe. Uma du´vida que poderia surgir e´ se na˜o e´ necessa´rio representar a constante √−1. Em termos de implementac¸a˜o isso na˜o sera´ necessa´rio porque o fato de ser um nu´mero complexo ja´ implica na existeˆncia da constante √−1 e sabe-se que essa constante esta´ sempre vinculada a` componente imagina´ria. 5.1.1 Me´todo Construtor O pro´ximo passo e´ especificar o que se chama de me´todo construtor (ou simplesmente “cons- trutor”) da classe. O construtor e´ o me´todo que e´ chamado sempre que se instancia um objeto dessa classe. Esse me´todo serve principalmente para inicializar alguns atributos da classe. Ape- sar de na˜o ser obrigato´rio, e´ boa pra´tica de programac¸a˜o sempre ter pelo menos um construtor da classe. Em raza˜o do conceitode polimorfismo, e´ poss´ıvel existir mais de um construtor para a mesma classe. Voltando ao exemplo, existem pelo menos treˆs maneiras para se criar um objeto NumeroCom- plexo: sem inicializa´-lo com valor nenhum, inicializando-o apenas com a parte imagina´ria ou 28 CENAPAD-SP Introduc¸a˜o a` Linguagem de Programac¸a˜o Java inicializando-o com ambas as partes real e imagina´ria. Sendo assim, sa˜o necessa´rios treˆs cons- trutores. Observe o co´digo a seguir e perceba que os construtores na˜o teˆm um tipo de objeto de retorno. Isso porque, obviamente, o objeto retornado sera´ um NumeroComplexo. Note tambe´m que os construtores foram declarados como pu´blicos. Caso tenham sido declarados privados (private) seu acesso so´ seria permitido dentro da pro´pria classe. public class NumeroComplexo { private double a; private double b; public NumeroComplexo() { a = b = 0; } public NumeroComplexo(double parteImaginaria) { a = 0; b = parteImaginaria; } public NumeroComplexo(double parteReal, double parteImaginaria) { a = parteReal; b = parteImaginaria; } } 5.1.2 Me´todo Destrutor De forma ana´loga, assim como ha´ um me´todo construtor, tambe´m existe um destrutor. O me´todo finalize pertence a` classe Object. Portanto, tambe´m e´ herdado por todas as demais classes em Java. Esse me´todo pode e recomenda-se ser sobrecarregado com ac¸o˜es que permitam a remoc¸a˜o do objeto da memo´ria sem muitos efeitos colaterais. Por exemplo, se um objeto que representa um arquivo e´ removido da memo´ria sem fechar o arquivo, pode ser que os dados que ainda na˜o foram gravados sejam perdidos. Sendo assim, e´ muito importante a implementac¸a˜o do me´todo finalize, apesar de na˜o ser implicitamente chamado. A chamada a este me´todo e´ feita pela ma´quina virtual quando na˜o existir mais nenhuma refereˆncia ao objeto. 29 CENAPAD-SP Introduc¸a˜o a` Linguagem de Programac¸a˜o Java No pro´ximo cap´ıtulo ha´ um exemplo onde esse me´todo e´ implementado. 5.1.3 Operadores this e super A palavra reservada this em Java representa o objeto atual, enquanto super representa a super- classe desse objeto. A palavra this e´ muito u´til quando e´ preciso referenciar o pro´prio objeto. A t´ıtulo de exemplo, considere a reescrita do construtor NumeroComplexo(double parteReal, double parteImaginaria) a seguir. public NumeroComplexo(double a, double b) { this.a = a; this.b = b; } Note que nesse novo exemplo de construtor, os paraˆmetros possuem o mesmo identificador dos atributos da classe. Mas como saber qual deles esta´ sendo usado a cada momento? Sim- ples. Na primeira atribuic¸a˜o, this.a=a, o atributo a de um objeto da classe NumeroComplexo - referenciado pelo this - esta´ recebendo o valor do paraˆmetro a passado para o me´todo. No decorrer do texto, outros exemplos usando os operadores this e super aparecera˜o. 5.1.4 Implementac¸a˜o de Me´todos Na˜o e´ obrigato´rio, mas os objetos costumam ter me´todos para prover formas de manipulac¸a˜o ou consulta. No exemplo da classe NumeroComplexo, e´ importante que os atributos na˜o sejam alterados por qualquer outra classe. Pore´m, ao mesmo tempo, e´ interessante poder consultar esses valores. Verifique o co´digo a seguir e atente para as restric¸o˜es impostas aos me´todos (os atributos e construtores ja´ vistos na˜o sera˜o repetidos). public class NumeroComplexo { // atributos e construtores. public double real() { return this.a; } public double imaginaria() 30 CENAPAD-SP Introduc¸a˜o a` Linguagem de Programac¸a˜o Java { return this.b; } private void real(double a) { this.a = a; } private void imaginaria(double b) { this.b = b; } } Note que existem dois exemplos de polimorfismo similares. Os me´todos public double real() e public double real(double a) sa˜o me´todos polimo´rficos, conforme discutido na Sec¸a˜o 3.2, pa´gina 12. O mesmo conceito e´ utilizado nos me´todos public double imaginaria() e public double imaginaria(double b). Perceba que a diferenc¸a entre me´todos polimo´rficos e´ o tipo e a quantidade de paraˆmetros que lhes e´ passado e na˜o o tipo de restric¸a˜o imposta. Isto implica que e´ imposs´ıvel declarar me´todos polimo´rficos, com o mesmo nu´mero, mesmo tipo de paraˆmetros, mas restric¸o˜es diferentes. No co´digo anterior, se houvesse um objeto A da classe NumeroComplexo sendo usado em outra classe, seria poss´ıvel usa-lo da forma A.real() para consultar sua parte real, mas seria um erro de compilac¸a˜o usa-lo da forma A.real(2) para alterar sua parte real. 5.1.5 Sobrecarga de Me´todos A classe Object, citada no in´ıcio deste cap´ıtulo, e´ por definic¸a˜o a superclasse de todas as classes definidas em um progrgama Java. Isto implica que alguns me´todos, embora na˜o explicitamente definidos ja´ esta˜o implementados. Um desses me´todos e´ o toString. O me´todo toString retorna uma representac¸a˜o do objeto como uma “String” composta do nome da classe, seguida de “@” e terminada com um co´digo hexadecimal do objeto. Ora, mas as vezes e´ necessa´rio a representac¸a˜o do objeto em uma “String” de forma mais natural. No caso do exemplo considerado, o ideal e´ que um nu´mero complexo fosse apresentado da sua forma natural, “7.8− 12.5i” por exemplo. Veja, a seguir, como ocorre a sobrecarga do me´todo toString na classe NumeroComplexo (os construtores, atributos e demais me´todos ja´ vistos na˜o sera˜o repetidos, estara˜o inclusos na respectiva linha de comenta´rio). 31 CENAPAD-SP Introduc¸a˜o a` Linguagem de Programac¸a˜o Java public class NumeroComplexo { // atributos, construtores e demais metodos. public String toString() { String representacao; if ( this.b >= 0 ) representacao = this.a + "+" + this.b + "i"; else representacao = this.a + "" +this.b + "i"; return representacao; } } O me´todo toString deve manter a mesma assinatura do me´todo original na classe Object. Isto implica que o me´todo deve ser pu´blico, retornar um objeto “String” e na˜o receber paraˆmetros. Como faz parte da classe Object, a utilizac¸a˜o desse me´todo na˜o precisa ser expl´ıcita, ou seja, sempre que for necessa´ria a conversa˜o de um objeto da classe NumeroComplexo para a classe String, isso sera´ feito implicitamente (sem a chamada do me´todo). 5.1.6 Me´todos esta´ticos Lembre-se que os me´todos sa˜o usados geralmente para manipular objetos. Portanto, na maioria das vezes para utilizar um me´todo e´ preciso que exista antes um objeto com aquele me´todo. Entretanto, as vezes e´ necessa´ria a utilizac¸a˜o de me´todos que na˜o esta˜o vinculados a nenhum objeto. Da´ı a necessidade de me´todos esta´ticos ou de classe. Esse tipo de me´todo pertence a` classe, por isso na˜o e´ necessa´ria nenhuma instanciac¸a˜o de objeto para usa-los. Observe o trecho de co´digo a seguir para verificar como sa˜o declarados me´todos esta´ticos. Nesse caso, o me´todo e´ usado para somar dois NumeroComplexos. public static NumeroComplexo Soma(NumeroComplexo x, NumeroComplexo y) { return new NumeroComplexo(x.real() + y.real(), y.imaginaria() + y.imaginaria()); } 32 CENAPAD-SP Introduc¸a˜o a` Linguagem de Programac¸a˜o Java Note que a palavra chave static foi usada apo´s a restric¸a˜o desse me´todo. A forma de utilizac¸a˜o desse me´todo e´ explicada nas linhas de co´digo a seguir. public static void main(String[ ] args) { NumeroComplexo c = new NumeroComplexo(1,-6); NumeroComplexo d = new NumeroComplexo(1,6); NumeroComplexo z; z = NumeroComplexo.Soma(c,d); System.out.println(" c = "+c+"\n d = "+d+"\n z = "+z); } Veja que o me´todo Soma, esta´tico, foi chamado a partir do nome da classe. Nesse me´todo foi criado um novo objeto que sera´ retornado. Mais detalhes sobre me´todos esta´ticospodem ser vistos no exemplo do final desse cap´ıtulo. Quanto a` criac¸a˜o de objetos, a pro´xima sec¸a˜o apresenta os detalhes. 5.2 Instanciac¸a˜o de Objetos Uma vez especificada a classe, seus objetos podem ser criados. Atente para a diferenc¸a entre a declarac¸a˜o de um objeto e sua instanciac¸a˜o. No primeiro caso, informa-se ao compilador que um determinado identificador representara´ um objeto da classe especificada. No segundo caso, ao ser instanciado o objeto passa a existir na memo´ria (incluindo seus me´todos e atributos). 5.2.1 Operador new A instanciac¸a˜o de um objeto e´ feita com o operador new. A sintaxe e´ simples, basta preceder o operador com o construtor da classe do objeto que se pretende criar. O retorno dessa operac¸a˜o e´ o objeto na memo´ria. Veja a seguir um exemplo dessa operac¸a˜o na classe NumeroComplexo e tente perceber a diferenc¸a entre “declarar” e “instanciar”. 33 CENAPAD-SP Introduc¸a˜o a` Linguagem de Programac¸a˜o Java public class NumeroComplexo { // atributos, construtores e demais metodos ja vistos. public static void main(String[ ] args) { NumeroComplexo x; // declaracao do objeto x x = new NumeroComplexo(3,-5); // instanciacao do objeto x System.out.println("X = "+x); // chamada implicita do metodo toString System.out.println("Im[X] = "+x.imaginaria()); } } Nesse co´digo, foi primeiro declarado um objeto x da classe NumeroComplexo e depois instanci- ado. Note que o terceiro construtor, aquele que inicializa tanto a parte real quanto a imagina´ria, foi o escolhido. Nada impede pore´m que ambas as ac¸o˜es sejam feitas em uma u´nica linha. Por exemplo, NumeroComplexo x = new NumeroComplexo();. Nesse caso, o primeiro construtor e´ chamado. 5.3 Exemplo Geral Nessa sec¸a˜o, o exemplo nas figuras 5.1, 5.2, 5.3, 5.4 e 5.5 ilustra a a combinac¸a˜o de todo o conteu´do explorado ate´ agora neste cap´ıtulo. Foi criada ainda uma outra classe chamada Main, mostrada na Figura 5.6, apenas para ilustrar a utilizac¸a˜o de objetos fora da sua classe original. 34 CENAPAD-SP Introduc¸a˜o a` Linguagem de Programac¸a˜o Java /** * Classe responsavel pelas operacoes com numeros complexos */ public class NumeroComplexo { /** * Atributos. * a: parte real de um numero complexo * b: parte imaginaria de um numero complexo */ private double a; private double b; /** Primeiro construtor. */ public NumeroComplexo() { a = b = 0; } /** Segundo construtor. */ public NumeroComplexo(double parteImaginaria) { a = 0; b = parteImaginaria; } /** Terceiro construtor. */ public NumeroComplexo(double a, double b) { this.a = a; this.b = b; } /** Retorna a parte real do objeto NumeroComplexo */ public double real() { return this.a; } /** Retorna a parte imaginaria do objeto NumeroComplexo */ public double imaginaria() { return this.b; } Figura 5.1: Classe NumeroComplexo, utilizada para exemplificar os to´picos deste cap´ıtulo. 35 CENAPAD-SP Introduc¸a˜o a` Linguagem de Programac¸a˜o Java /** * Atribui um valor a parte real do NumeroComplexo. * Metodo Privado! */ private void real(double a) { this.a = a; } /** * Atribui um valor a parte imaginaria do NumeroComplexo. * Metodo Privado! */ private void imaginaria(double b) { this.b = b; } /** Metodo para criar uma representacao desse objeto em String*/ public String toString() { String representacao; if ( this.b>=0 ) representacao = this.a + "+" + this.b + "i"; else representacao = this.a + ""+ this.b + "i"; return representacao; } /** * Calcula o conjugado de um NumeroComplexo. * Conjugado de a + bi = a - bi. */ public NumeroComplexo Conjugado() { return new NumeroComplexo(this.real(),-this.imaginaria()); } Figura 5.2: Continuac¸a˜o da epecificac¸a˜o da classe NumeroComplexo, na Figura 5.1. 36 CENAPAD-SP Introduc¸a˜o a` Linguagem de Programac¸a˜o Java /** Soma um NumeroComplexos a este e retorna um novo NumeroComplexo.*/ public NumeroComplexo Soma(NumeroComplexo z) { return new NumeroComplexo(this.real() + z.real(), this.imaginaria() + z.imaginaria()); } /** Subtrai um NumeroComplexos a este e retorna um novo NumeroComplexo.*/ public NumeroComplexo Subtrai(NumeroComplexo z) { return new NumeroComplexo(this.real() - z.real(), this.imaginaria() - z.imaginaria()); } /** * Multiplica um NumeroComplexos por este e retorna um novo * NumeroComplexo. * ( a + bi ) * ( c + di) = ac + bci + adi + bdi^2 = * = (ac - bd) + (ad + bc)i */ public NumeroComplexo Multiplica(NumeroComplexo z) { return new NumeroComplexo( this.real() * z.real() - this.imaginaria() * z.imaginaria(), this.real() * z.imaginaria() + this.imaginaria() * z.real()); } /** * Divide um NumeroComplexos por este e retorna um novo NumeroComplexo. * A divisao e feita multiplicando o numerador e o denominador pelo * conjugado do denominador. */ public NumeroComplexo Divide(NumeroComplexo z) { NumeroComplexo numerador, denominador; numerador = this.Multiplica(z.Conjugado()); denominador = z.Multiplica(z.Conjugado()); return new NumeroComplexo(numerador.real()/denominador.real(), numerador.imaginaria()/denominador.real()); } Figura 5.3: Continuac¸a˜o da especificac¸a˜o da classe NumeroComplexo, na Figura 5.2. 37 CENAPAD-SP Introduc¸a˜o a` Linguagem de Programac¸a˜o Java /** * Calcula o conjugado de um NumeroComplexo. * Metodo Estatico. */ public static NumeroComplexo Conjugado(NumeroComplexo z) { return new NumeroComplexo(z.real(),-z.imaginaria());} /** Soma dois NumeroComplexos e retorna um novo NumeroComplexo. * Metodo Estatico. */ public static NumeroComplexo Soma(NumeroComplexo x, NumeroComplexo y) { return new NumeroComplexo(x.real() + y.real(), y.imaginaria() + y.imaginaria()); } /** Subtrai um NumeroComplexos a este e retorna um novo NumeroComplexo. * Metodo estatico */ public static NumeroComplexo Subtrai(NumeroComplexo x, NumeroComplexo y) { return new NumeroComplexo(x.real() - y.real(), x.imaginaria() - y.imaginaria()); } /** * Multiplica dois NumeroComplexos e retorna um novo NumeroComplexo. * Metodo estatico */ public static NumeroComplexo Multiplica(NumeroComplexo x, NumeroComplexo y) { return new NumeroComplexo( x.real() * y.real() - x.imaginaria() * y.imaginaria(), x.real() * y.imaginaria() + x.imaginaria() * y.real()); } Figura 5.4: Continuac¸a˜o da epecificac¸a˜o da classe NumeroComplexo, na Figura 5.3. 38 CENAPAD-SP Introduc¸a˜o a` Linguagem de Programac¸a˜o Java /** * Divide um NumeroComplexos por este e retorna um novo NumeroComplexo. * Metodo estatico */ public NumeroComplexo Divide(NumeroComplexo x, NumeroComplexo y) { NumeroComplexo numerador, denominador; numerador = NumeroComplexo.Multiplica(x,y.Conjugado()); denominador = NumeroComplexo.Multiplica(y,y.Conjugado()); return new NumeroComplexo(numerador.real()/denominador.real(), numerador.imaginaria()/denominador.real()); } } // fim da definicao da classe NumeroComplexo. Figura 5.5: Continuac¸a˜o da epecificac¸a˜o da classe NumeroComplexo, na Figura 5.4. Uma vez definida a classe NumeroComplexo, e´ poss´ıvel dentro de outra classe, usar os objetos da classe NumeroComplexo. Observe a classe Main no exemplo a seguir. public class Main { public static void main(String[ ] args) { NumeroComplexo x = new NumeroComplexo(1,-6); NumeroComplexo y = new NumeroComplexo(1,6); // Chamada ao metodo Soma estatico NumeroComplexo z = NumeroComplexo.Soma(x,y); // Observe a utilizacao implicita do metodo toString System.out.println("X = "+x); System.out.println("Y = "+y); System.out.println("Conjugado deX ="+ x.Conjugado()); System.out.println("X+Y = "+x.Soma(y)); System.out.println("X/Y = "+ NumeroComplexo.Divide(z,y)); } } Figura 5.6: Classe Main, que utiliza a classe NumeroComplexo. 39 CAP´ITULO 6 Tratamento de Excec¸o˜es “Sem dor, sem sacrif´ıcio, na˜o ter´ıamos nada.” Tyler Durden em “O Clube da Luta”, 1999. Tudo parece estar indo bem com seu programa quando, de repente, o usua´rio digita um valor que o programa na˜o esperava ou, ao ler o disco r´ıgido ha´ uma pane. Quem ja´ na˜o passou por uma situac¸a˜o como essas ou situac¸o˜es semelhantes? Essas sa˜o as chamadas “excec¸o˜es”. Em outras palavras, sa˜o eventos que ocorrem durante a execuc¸a˜o de um programa e desviam o fluxo normal de instruc¸o˜es. Parodiando O. Bilac nos versos do in´ıcio deste cap´ıtulo: ora, questionais se esses eventos na˜o poderiam ser tratados pelo pro´prio sistema operacional. Eu vos direi no entanto que se seu pro´prio programa ja´ cuidar desses eventos inesperados o sistema operacional ficara´ menos sobrecarregado e, com isso, continuara´ suas tarefas sem muitas interrupc¸o˜es. 40 CENAPAD-SP Introduc¸a˜o a` Linguagem de Programac¸a˜o Java Esse tratamento podedria ser feito incluindo uma enorme quantidade de ifs no programa. Entretanto, Java oferece formas de tratar excec¸o˜es e evitar assim a sobrecarga do sistema. 6.1 Cla´usulas try-catch Sempre que um determinado bloco de programa em Java for suspeito, i.e. se houver uma grande probabilidade de ocorrer uma excec¸a˜o em um determinado trecho de co´digo, e´ poss´ıvel criar um tratamento espec´ıfico para tal excec¸a˜o. Para isso, utilizam-se as cla´usulas try-catch. Observe o trecho a seguir. float[ ] vetor = new float[5]; float x; int y, z; z = 13; y = 5; try{ z = (z - (y + 1)) * 2 / 7; x = vetor[y / (z - 2)]; } catch (ArithmeticException exc1){ System.err.println("Divisao por zero"); exc1.printStackTrace(); } catch (ArrayIndexOutOfBoundsException exc2) { System.err.println("Indice do arranjo fora dos limites!"); exc2.printStackTrace(); } Existem duas poss´ıveis causas de excec¸o˜es neste trecho. A primeira delas e´ em relac¸a˜o a` operac¸a˜o y/(z-2). Perceba que se o valor de z for 2, ha´ uma divisa˜o de y por zero, o que em computac¸a˜o seria inconceb´ıvel1. A outra e´ em relac¸a˜o ao ı´ndice do arranjo vetor. Se o valor desse ı´ndice for menor que zero ou maior que o limite do arranjo, isso tambe´m pode causar uma excec¸a˜o. Portanto, o trecho de programa suspeito e´ colocado no bloco try{ ... }, enquanto o tra- tamento de poss´ıveis excec¸o˜es e´ colocado no bloco catch( ... ){ ... }. O ideal e´ que, para 1Em teoria a divisa˜o por zero resultaria em infinito. Esse valor e´ imposs´ıvel de representar computacionalmente. 41 CENAPAD-SP Introduc¸a˜o a` Linguagem de Programac¸a˜o Java cada tipo de excec¸a˜o, haja um catch espec´ıfico. As excec¸o˜es sa˜o lanc¸adas ate´ haver algum catch espec´ıfico para trata´-las. Por ser objeto de uma classe. as excec¸o˜es tambe´m teˆm uma hierarquia. No maior n´ıvel dessa hierarquia esta´ a classe Exception. Portanto, na du´vida coloque um objeto da classe Exception como paraˆmetro para o catch. Quando lanc¸adas, as excec¸o˜es podem ser tratadas localmente. Na˜o havendo um tratamento local, a excec¸a˜o e´ lanc¸ada para o objeto que invocou o me´todo do objeto local e assim sucessi- vamente. Na˜o existindo nenhum objeto que trate a excec¸a˜o, ela e´ lanc¸ada pela ma´quina virtual e o programa encerrado. Sendo assim, quanto mais pro´ximo da ocorreˆncia e´ o tratamento da excec¸a˜o, menor a possibilidade de pane da aplicac¸a˜o. 6.2 Cla´usulas throws e throw Normalmente, Java na˜o exige que trechos suspeitos de programas sejam colocados em cla´usulas try-catch. Entretanto, ha´ algumas classes que exigem que seus me´todos tenham tratamento em caso de excec¸a˜o. Na compilac¸a˜o, essa exigeˆncia e´ cobrada. E´ poss´ıvel especificar que um determinado me´todo pode lanc¸ar uma excec¸a˜o. Nesses me´todos existe a cla´usula throws (em portugueˆs “lanc¸ar”). Voltando ao exemplo do nu´mero complexo, no cap´ıtulo anterior, observe a especificac¸a˜o do me´todo Divide a seguir. public NumeroComplexo Divide(NumeroComplexo z) throws ArithmeticException { NumeroComplexo numerador, denominador; numerador = this.Multiplica(z.Conjugado()); denominador = z.Multiplica(z.Conjugado()); if (denominador.real() == 0) throw new AritmeticException(); return new NumeroComplexo(numerador.real()/denominador.real(), numerador.imaginaria()/denominador.real()); } Perceba que, caso a parte real do denominador seja igual a zero, havera´ uma divisa˜o por zero. Nesse caso, deve-se criar e lanc¸ar uma excec¸a˜o. Isso e´ feito com a cla´usula throw. No caso do 42 CENAPAD-SP Introduc¸a˜o a` Linguagem de Programac¸a˜o Java exemplo, foi criado um objeto da classe ArithmeticException e em seguida, lanc¸ado para quem chamou o me´todo. 6.3 Classe Exception Conforme ja´ mencionado, a classe Exception e´ a superclasse de todas aquelas que implementam excec¸o˜es. Alguns me´todos dessa classe sa˜o passados via heranc¸a a`s demais. Sendo assim, e´ u´til conhecer alguns me´todos dessa classe. Os mais importantes sa˜o: • os construtores Exception() e Exception(String mensagem): o segundo construtor per- mite incluir uma mensagem espec´ıfica. • String getMessage() retorna a mensagem do objeto (inclu´ıda pelo construtor). • void printStackTrace() imprime a pilha de ativac¸a˜o de me´todos ate´ o ponto onde houve o erro. O me´todo printStackTrace() e´ u´til especialmente na fase de testes. Esse me´todo imprime em que ponto do co´digo fonte o erro aconteceu e, com isso, fica mais fa´cil encontrar o problema. 43 CAP´ITULO 7 Entrada e Sa´ıda “Vamos nos concentrar no problema, pessoal. Na˜o deixemos as coisas piores tentando adivinhar.” Gene Kranz em “Apollo 13”, 1995. As ac¸o˜es de entrada e sa´ıda (E/S) de programas sa˜o muito importantes. Elas permitem que o mesmo programa atue como uma func¸a˜o onde, para diferentes valores de entrada, diferentes resultados sa˜o obtidos. Este cap´ıtulo concentra-se nas principais classes que implementam E/S. Em particular, E/S dos dispositivos padra˜o (teclado, monitor) e arquivos (discos). As classes que lidam com entrada e sa´ıda esta˜o em um pacote chamado java.io que deve ser importado no in´ıcio de cada programa. 7.1 Streams ou Fluxos Fluxos ou “Streams” em ingleˆs funcionam como dutos onde se injetam dados de um lado e recuperam-se no outro. Existem dois tipos ba´sicos de “Stream”: de caracteres ou de “bytes”. O primeiro tipo leˆ e escreve caracteres de 16 bits, enquanto o segundo transfere dados de 8 bits. Ambos sera˜o vistos nas sec¸o˜es a seguir. 44 CENAPAD-SP Introduc¸a˜o a` Linguagem de Programac¸a˜o Java 7.2 Fluxos de Caracteres As superclasse dos fluxos de caracteres sa˜o a classe Reader, para a leitura, e a classe Writer para escrita. A classe Reader e´ uma classe abstrata, ou seja, ela apenas especifica me´todos ba´sicos que as suas subclasses devem implementar. Algumas classes que herdam da classe Reader esta˜o na Tabela 7.1 a seguir. Os me´todos dessa classe esta˜o na Tabela 7.2. Subclasse Descric¸a˜o BufferedReader Leˆ textos de um fluxo de entrada de caracteres, utilizando um “buffer” interno. CharArrayReader Implementa um “buffer” de caracteres. InputStreamReader Leˆ “bytes” e os decodifica em caracteres. PipedReader Implementa um “pipe” de leitura (conexa˜o entre entradas e sa´ıdas). Tabela 7.1: Subclasses da classe Reader e suas descric¸o˜es. Me´todos da classe Reader Descric¸a˜o void close() Encerra um fluxo. int read() Leˆ um u´nico caractere. int read(char[ ] cbuf) Leˆ caracteres e os armazena em cbuf int read(char[ ]