Baixe o app para aproveitar ainda mais
Prévia do material em texto
Java Fundamentals Java Fundamentals I SumárioSumárioSumárioSumário 1.1.1.1. A tecnologia Java e configuração do ambieA tecnologia Java e configuração do ambieA tecnologia Java e configuração do ambieA tecnologia Java e configuração do ambientententente........................................................ 1111----1111 Objetivos .......................................................................................................................1-2 O que é Java? .............................................................................................................1-3 Simples e orientada a objetos ...................................................................................1-5 Uma linguagem robusta.............................................................................................1-7 Multiplataforma e interpretada ................................................................................1-9 A Java Virtual Machine - JVM .................................................................................1-11 Uma Linguagem Segura e Dinâmica.....................................................................1-14 Aspectos de segurança ...........................................................................................1-16 O Just in Time Compiler - JIT .....................................................................................1-18 O Java Standard Development Kit – J2SDK..........................................................1-19 Configurando o ambiente.......................................................................................1-22 API’s da linguagem ...................................................................................................1-23 2.2.2.2. Tipos e OTipos e OTipos e OTipos e Operadoresperadoresperadoresperadores ................................................................................................................................................................................................................ 2222----1111 Objetivos .......................................................................................................................2-2 Variáveis ........................................................................................................................2-3 Tipos primitivos e tipos compostos ............................................................................2-4 Tipos Primitivos ..............................................................................................................2-6 Declarando um tipo primitivo..................................................................................2-10 Tipo caracter – char..................................................................................................2-12 Tipo booleano – boolean.........................................................................................2-14 Tipos inteiros - byte, short, int e long .......................................................................2-15 Tipos de ponto flutuante - float e double..............................................................2-17 Tipo composto – String..............................................................................................2-19 Conversões de tipos – casting.................................................................................2-20 Tipos de referência....................................................................................................2-22 Expressões e operadores..........................................................................................2-23 Sumário de operadores............................................................................................2-25 Precedência...............................................................................................................2-27 Associatividade..........................................................................................................2-28 Tipos de operadores: unários e binários ................................................................2-29 3.3.3.3. Criando classes e objetosCriando classes e objetosCriando classes e objetosCriando classes e objetos ............................................................................................................................................................................ 3333----1111 Objetivos .......................................................................................................................3-2 Classes e Objetos.........................................................................................................3-3 Criando uma classe ....................................................................................................3-4 Padrões..........................................................................................................................3-6 Java Fundamentals II Criando e importando pacotes................................................................................3-9 Static import................................................................................................................3-11 Criando objetos .........................................................................................................3-12 O que é a referência null? .......................................................................................3-13 Atribuindo referências...............................................................................................3-15 Visibilidade aplicada a classes ...............................................................................3-16 Definindo operações ................................................................................................3-18 Comando return ........................................................................................................3-21 Visibilidade para operações ...................................................................................3-22 Definindo atributos ....................................................................................................3-25 Visibilidade aplicada a atributos ............................................................................3-26 Acessando atributos .................................................................................................3-32 Comentários no código fonte.................................................................................3-33 Escopo das variáveis.................................................................................................3-36 Passando Tipos Primitivos para Métodos ...............................................................3-39 Passando Referências para Métodos ....................................................................3-40 Exercícios.....................................................................................................................3-42 4.4.4.4. Comandos da LinguagemComandos da LinguagemComandos da LinguagemComandos da Linguagem ............................................................................................................................................................................ 4444----1111 Objetivos .......................................................................................................................4-2 Comandos ....................................................................................................................4-3 Comando if / else / else if ..........................................................................................4-4 Seqüência de Cláusulas else if ..................................................................................4-7 Operador ternário .......................................................................................................4-9Comando switch .......................................................................................................4-10 Comando while .........................................................................................................4-13 Comando do .............................................................................................................4-14 Comando for..............................................................................................................4-15 Comando “for-each” ...............................................................................................4-18 Comando break ........................................................................................................4-19 Comando continue ..................................................................................................4-21 Exercícios.....................................................................................................................4-24 5.5.5.5. Aprofundando o estudo sobre ClassesAprofundando o estudo sobre ClassesAprofundando o estudo sobre ClassesAprofundando o estudo sobre Classes.................................................................................................... 5555----1111 Objetivos .......................................................................................................................5-2 Visão Geral ...................................................................................................................5-3 Overloading – sobrecarga de operação ...............................................................5-4 Métodos construtores .................................................................................................5-6 Referência this..............................................................................................................5-9 Compartilhando código entre Construtores ........................................................5-11 Método destrutor – finalize() ....................................................................................5-12 Variáveis de instância...............................................................................................5-13 Métodos de instância ...............................................................................................5-15 Variáveis de classe ....................................................................................................5-16 Inicializando Variáveis de Classe ............................................................................5-19 Métodos de classe ....................................................................................................5-20 Java Fundamentals III Exemplos de variáveis e métodos estáticos .........................................................5-22 O mecanismo de herança entre classes ..............................................................5-23 Herdando estrutura e comportamento.................................................................5-24 Especificando herança em Java ...........................................................................5-25 Objetos de subclasses...............................................................................................5-26 Chamando construtores da superclasse...............................................................5-27 Overloading e Overriding de métodos..................................................................5-29 Redefinindo métodos – overriding..........................................................................5-30 Referência super........................................................................................................5-33 Invocando métodos da superclasse......................................................................5-35 Visibilidade protected ..............................................................................................5-36 Varargs ........................................................................................................................5-37 Polimorfismo................................................................................................................5-39 Modificador final........................................................................................................5-41 Enums...........................................................................................................................5-43 Exercícios.....................................................................................................................5-46 6.6.6.6. Coleções, Arrays, Strings, e Wrapper ClassesColeções, Arrays, Strings, e Wrapper ClassesColeções, Arrays, Strings, e Wrapper ClassesColeções, Arrays, Strings, e Wrapper Classes ............................................................ 6666----1111 Objetivos .......................................................................................................................6-2 Strings .............................................................................................................................6-3 Criando Strings .............................................................................................................6-4 Concatenando Strings................................................................................................6-5 Executando operações em objetos String..............................................................6-6 Comparando duas Strings .........................................................................................6-8 Obtendo strings a partir de objetos..........................................................................6-9 Convertendo tipos primitivos em strings ................................................................6-10 Wrapper Classes ........................................................................................................6-11 Conversões com Wrapper Classes .........................................................................6-12 StringBuffer e StringBuilder ........................................................................................6-13 Arrays ...........................................................................................................................6-14 Arrays de tipos primitivos ..........................................................................................6-15 Declarando arrays de tipos primitivos....................................................................6-16 Criando arrays............................................................................................................6-17 Inicializando arrays ....................................................................................................6-18 Arrays de objetos .......................................................................................................6-20 Declarando arrays de objetos ................................................................................6-21 Inicializando arrays de objetos................................................................................6-22 Utilizando arrays de objetos .....................................................................................6-23 Arrays e Exceções......................................................................................................6-24 Arrays multidimensionais...........................................................................................6-25 O método main(String[] args) ........................................................................6-26 API Colletion ...............................................................................................................6-27 A interface Iterator ....................................................................................................6-28 A interface Enumeration ..........................................................................................6-29Interfaces do framework ..........................................................................................6-30 A classe ArrayList........................................................................................................6-31 A classe Vector ..........................................................................................................6-32 Java Fundamentals IV A classe Hashtable ....................................................................................................6-34 A classe LinkedList......................................................................................................6-35 Generics ......................................................................................................................6-36 Autoboxing .................................................................................................................6-39 Exercícios.....................................................................................................................6-43 7.7.7.7. Tratamento de ExceçõesTratamento de ExceçõesTratamento de ExceçõesTratamento de Exceções.................................................................................................................................................................................... 7777----1111 Objetivos .......................................................................................................................7-2 Introdução ....................................................................................................................7-3 1a Vantagem: Separação de Código.....................................................................7-4 2a Vantagem: Propagação de Erros........................................................................7-6 3a Vantagem: Agrupar Tipos de Erros ......................................................................7-8 4a Vantagem: Exceções não são Ignoradas........................................................7-10 Manipulando Exceções............................................................................................7-11 Tratando Exceções....................................................................................................7-13 Manipulando Exceções............................................................................................7-14 Manipulando Exceções: Exemplo Prático.............................................................7-16 Propagando Exceções.............................................................................................7-17 Lançando Exceções .................................................................................................7-18 Criando Exceções .....................................................................................................7-19 Capturando Exceções e Levantando Exceções Diferentes..............................7-20 Exercícios.....................................................................................................................7-22 8.8.8.8. Classes abstratas e InterfacesClasses abstratas e InterfacesClasses abstratas e InterfacesClasses abstratas e Interfaces .................................................................................................................................................... 8888----1111 Objetivos .......................................................................................................................8-2 Abstração .....................................................................................................................8-3 Definindo classes abstratas........................................................................................8-4 Métodos Abstratos.......................................................................................................8-6 Definindo métodos abstratos ....................................................................................8-7 Interfaces ......................................................................................................................8-8 Exemplos de interfaces...............................................................................................8-9 Definindo Interfaces ..................................................................................................8-10 Implementando Interfaces ......................................................................................8-11 Exercícios.....................................................................................................................8-13 Java Fundamentals 1-1 11.. AA tteeccnnoollooggiiaa JJaavvaa ee ccoonnffiigguurraaççããoo ddoo aammbbiieennttee A tecnologia java e configuração do ambiente 1-2 Objetivos • Compreender os fundamentos da tecnologia Java • Discutir vantagens da tecnologia • Entender o funcionamento da JVM (Java Virtual Machine) • Configurar o ambiente de desenvolvimento para o programador A tecnologia java e configuração do ambiente 1-3 O que é Java? • Linguagem orientada a objetos, simples, portável, interpretada, distribuída, robusta, segura, dinâmica, de alto desempenho, multi-thread e independente de plataforma • Projetada pela Sun Microsystems inicialmente para dispositivos eletrônicos • Utilizada posteriormente em navegadores web, para permitir que uma aplicação pudesse ser desenvolvida e “executada na web”. Aqui é o nascimento da tecnologia applet • Uma linguagem muito utilizada atualmente para desenvolvimento de sistemas que precisam rodar na web bem como sistemas desktop Breve Histórico Java começou em 1991, quando um grupo de analistas da Sun, liderados por Patrick Naughton e James Gosling, procurou desenvolver uma linguagem de computador que fosse usada em equipamentos domésticos, tais como comutadores de canais para TV a cabo, videocassetes e outros. Como estes equipamentos não dispõem de muita memória ou velocidade, a linguagem tinha de ser reduzida e gerar código eficiente. Além disto, como diferentes fabricantes poderiam escolher diferentes CPUs, tal linguagem não poderia se restringir a uma única arquitetura. O projeto ficou conhecido como Green Project. DUKE, um dos símbolos do Java Visando satisfazer todas estas exigências, a equipe de analistas optou por uma linguagem que gerasse código intermediário (os famosos bytecodes Java), e que a interpretação deste código não fosse feita diretamente pelo hardware e sim por uma máquina virtual disposta sobre ele (conhecida hoje como JVM – Java Virtual Machine). Esta linguagem foi batizada inicialmente com o nome Oak (que, em português significa carvalho). Possivelmente o nome escolhido por Gosling se deve a um carvalho que existia em frente a sua janela na Sun MicroSystems. A tecnologia java e configuração do ambiente 1-4 Posteriormente se descobriu que Oak já era o nome de uma outra linguagem, e o nome foi então trocado para Java. Java não obteve muito sucesso como linguagem de controle de eletrodomésticos (e isto nós podemos muito bem atestar :-). Em vão, a equipe do Green Project tentou vender a idéia para fabricantes de tais dispositivos. Dissolvida a equipe, por absoluta falta de êxito econômico, alguns dos antigos componentes perceberam que uma das possíveis utilidades para tal linguagem seria embuti-la em navegadores, como os encontrados no mercado. Tais aplicativos exigiam justamente uma linguagem independente de plataforma, confiável, segura e em tempo real: todas as características “estranhas” que Java possuía. A tecnologia java e configuração do ambiente 1-5 Simples e orientada a objetos • Uma linguagem simples e orientada a objetos • Baseada em Smalltalk e C++ • A tecnologia de objetospara esta linguagem foi baseada em Smalltalk • Reaproveitou grande parte da sintaxe utilizada pelo C e C++ • Eliminou construções de C++ consideradas complexas ou desnecessárias • Reduzido conjunto de palavras reservadas e um grande poder de expressão Uma Linguagem Orientada a Objetos Problemas surgidos na área de engenharia de software, tais como aumento explosivo da complexidade dos sistemas, dificuldades na manutenção e evolução dos softwares existentes, fraca robustez apresentada pelos aplicativos e outros, fizeram com que os paradigmas de análise e desenvolvimento de software fossem alterados. Java surge junto com o “boom” da orientação por objetos, à ampla aceitação deste paradigma pelos técnicos de informática como o mais adequado a enfrentar os problemas encontrados. A cultura dos técnicos da equipe de desenvolvimento da Sun Microsystems fez com que, entre as linguagens orientadas por objetos conhecidas, escolhessem C++ como modelo para o desenvolvimento de Java. C++ era então uma das mais difundidas linguagens de programação orientada por objetos em voga no mundo UNIX. Mas C++ era complexa demais. Várias construções em C++ eram de questionável utilidade e de difícil implementação por parte dos construtores de compiladores. Herança múltipla e sobrecarga de operadores, por exemplo, eram construções que demandavam grande esforço por parte dos implementadores e que não fazem parte do núcleo mínimo exigido pelo paradigma. Desta forma alguns recursos ficaram de fora e decidiu-se manter inicialmente uma gama menor de recursos para viabilizar o projeto e manter o mesmo mais somples. Atualmente alguns recuros mais sofisticados como “Generics” foram incluídos. Os recursos básicos que foram atendidos na época são: • Abstração A tecnologia java e configuração do ambiente 1-6 • Encapsulamento • Herança • Polimorfismo Decidiram então simplificar: • A linguagem não seria compilada para uma plataforma nativa e sim para uma máquina virtual. Esta técnica que dá ao java a possibilidade de rodar em múltiplas plataformas foi baseada no Smalltalk • Não haveria programação genérica (na época, mas a partir da versão 1.5 este recurso já é suportado) • Não haveria sobrecarga de operadores • Herança múltipla seria substituída pelo mecanismo de interfaces, mais simples e com poder de expressão equivalente • A velha sintaxe, tomada de empréstimo da linguagem C, seria enxugada, de modo a conter somente as palavras reservadas necessárias Destas idéias iniciais surge então a tecnologia Java. Claro que há muito mais coisas presentes no java do que as listadas acima. Atualmente o java é uma tecnologia tão completa que permite você desenvolver aplicações para rodar na Web, em máquinas cliente, Celulares, Palm Tops e muito mais. A tecnologia java e configuração do ambiente 1-7 Uma linguagem robusta • Java é uma linguagem fortemente tipada • Ampla verificação de erros e checagem de tipos em tempo de compilação • Não existem apontadores na linguagem • Linguagem multiplataforma • Gerência automática da memória (garbage collection) Erro de Ponteiro? Um dos principais objetivos dos projetistas da linguagem era conseguir conciliar a flexibilidade e o poder da orientação por objetos com a segurança e a robustez da checagem de tipos e erros em tempo de compilação. Java é uma linguagem fortemente tipada. E o que queremos dizer com isto? Que, em tempo de compilação, são checados todos os problemas referentes à passagem de parâmetros e atribuições de variáveis no que diz respeito à compatibilidade de tipos entre a variável que recebe o valor e a variável atribuída. Outra importante característica da linguagem Java é fato de não possuir apontadores, com o sentido que tal termo possui em C ou em C++. Em C ou C++ é perfeitamente possível navegarmos despreocupadamente pela memória do processo: basta, para tal, declararmos um apontador para uma região de memória e sairmos a incrementá-lo ou decrementá-lo. Toda a aritmética com apontadores não só é permitida pela linguagem, como também incentivada. Em Java não há apontadores explícitos, nem tampouco aritmética de apontadores, mas sim referências feitas a objetos criados. Objetos são criados através do operador new e o espaço de memória que ocupam é automaticamente gerenciado por um sistema de coleta de lixo (garbage collection) , que o libera tão logo não haja mais referências a um objeto. A tecnologia java e configuração do ambiente 1-8 Com isto, não existem em Java os erros de ponteiro (dangling pointers, memory leak e outros) tão conhecidos de linguagens como C e C++. A tecnologia java e configuração do ambiente 1-9 Multiplataforma e interpretada Ao contrário das outras tecnologias onde os programas são compilados para um sistema operacional específico, os fontes Java são compilados para uma máquina virtual. Isto significa que após a compilação os mesmos, são executados por uma máquina virtual (JVM) e não diretamente pelo sistema operacional. Abaixo veja a forma tradicional de compilação dos programas e mais abaixo a forma como funciona o Java. Figura 1-1: Compilação em C++. Em linguagens tradicionais como C, C++ ou pascal, o código fonte é convertido para um conjunto de instruções de máquina da plataforma de hardware onde a compilação teve lugar. Este programa é executado diretamente pela CPU da máquina e está vinculado à plataforma em que foi compilado: só poderá ser executado por CPUs que compartilhem o mesmo conjunto de instruções, o que geralmente significa ficar limitado a um determinado fabricante de hardware ou a uma família de produtos. Figura 1-2: Compilação em Java. A tecnologia java e configuração do ambiente 1-10 Java adota uma filosofia diferente. Os fontes Java não são convertidos diretamente para instruções de máquina. Ao contrário, a partir da compilação dos fontes são gerados arquivos contendo código intermediário que independe de plataforma. O código intermediário Java, conhecido como “bytecode” Java, foi projetado para uma máquina hipotética. Contém instruções similares a de uma máquina real (operações aritméticas, controle de fluxo, etc.), mas não tem em vista, e nem se limita, a uma determinada arquitetura de computador. Em vez de ser executado diretamente pelo hardware, este código é interpretado por uma JVM (Máquina Virtual Java Java Virtual Machine). Desta forma, em qualquer arquitetura onde exista uma JVM será possível executar um programa Java sem a necessidade de se re-compilar os fontes. Os binários Java (código intermediário ou Java bytecode) são independentes de plataforma ou, dito de outra maneira, neutros quanto à arquitetura da máquina. Os fontes Java são armazenados em arquivos com a extensão .java. A compilação dos arquivos .java trará como resultado arquivos com a extensão .class. Arquivos com a extensão .class contém somente Java bytecodes e são também conhecidos como binários Java. Cabe novamente ressaltar que os binários Java (arquivos .class) não são executados diretamente pelo hardware e sim interpretados pela JVM. Sem a JVM não há como executar nenhum programa Java. A tecnologia java e configuração do ambiente 1-11 A Java Virtual Machine - JVM • Camada intermediária e isolante entre o sistema operacional e as aplicações Java. • Elimina a dependência do código quanto à arquitetura e quanto às facilidades do SO. • Responsável pela interpretação dos bytecodes Java. • Traduz os bytecodes em instruções de máquina e em chamadas de sistema (API do SO). • Pode ser implementada através de um programa avulso ou estar embutida em um navegador(Browser). A máquina virtual Java (ou, como é comumente chamada, JVM, Java Virtual Machine) integra o ambiente de programação e execução Java. Ela é responsável por interpretar os bytecodes Java e traduzi-los em instruções reais de máquina e em chamadas de sistema (syscalls). Figura 1-3: Esquema de independência da JVM. Desta forma, as requisições feitas por um programa Java a recursos do sistema são mapeadas pela JVM em requisições feita ao SO sobre o qual a JVM executa. O SO responde a tais requisições e estas respostas são encaminhadas ao código Java em execução. Uma vez compilado um programa Java, os binários (bytecodes Java) podem ser executados em toda a plataforma para a qual já a JVM já tenha sido portada. Atualmente, a grande maioria dos sistemas operacionais conhecidos possui uma implementação da JVM (Solaris, Windows98, WindowsNT, Linux, MacOS, HP-UX, AIX, etc.). A tecnologia java e configuração do ambiente 1-12 A JVM pode ser implementada através de um programa avulso, pode estar embutida em um navegador, fazer parte do núcleo de um banco de dados, ou mesmo integrar o kernel de um SO. A única exigência que se faz à execução de um aplicativo Java é a existência da JVM para aquele ambiente. Como executam os programas java A linguagem Java é orientada a objetos, com linhas de execução (threads) dinâmicas e muitos outros recursos. Mas o que faz a diferença é o modo como os programas Java são executados. Eles rodam dentro de máquinas virtuais (virtual machines), que ficam dentro do computador. Por isso, um programa Java não tem contato com o computador real, ele conhece apenas a máquina virtual. Logo, os programas Java são independentes de plataforma. Se você já precisou desenvolver programas para vários sistemas operacionais, sabe que isso é uma grande vantagem. Quando você escreve um programa Java e o compila, ele está pronto para ser executado em qualquer PC que contenha a máquina virtual Java. De certa forma, você está escrevendo para apenas uma plataforma: a máquina virtual. A virtual machine determina o que os programas Java podem ou não fazer. Os programas escritos em linguagens compiladas, como C ou C++, são executados diretamente pelo sistema operacional. Assim sendo, eles têm acesso direto a todos os recursos do sistema, incluindo memória e sistema de arquivos. Como os programas Java são executados de dentro da máquina virtual, as pessoas (programadores e desenvolvedores) que criam a máquina virtual podem decidir o que um programa pode ou não fazer no computador. O ambiente criado para os programas Java chama-se ambiente de runtime. A máquina virtual age como um firewall (barreira) entre o computador e o programa Java. Um programa nunca acessa os dispositivos de entrada e saída, o sistema de arquivos ou mesmo a memória do seu computador. Em vez disso, ele pede que a máquina virtual faça isso. Quando rodamos as applets, elas são descarregadas para uma máquina virtual que proíbe o acesso ao sistema de arquivos. Assim, ela só permite acesso indireto aos recursos do sistema. Por ser uma linguagem interpretada, isso explica a independência de plataforma Java. A tecnologia java e configuração do ambiente 1-13 Por que interpretada? Porque o compilador Java gera o bytecode (código especial Java), que será executado por uma máquina virtual implementada em software, chamada de JVM – Java Virtual Machine (Máquina Virtual Java). A diferença entre o Java que é uma linguagem interpretada, comparada com uma linguagem compilada, como o caso do C ou C++ é que enquanto nessas linguagens tradicionais, para cada plataforma precisamos que o compilador gere um código especifico, como por exemplo, para um PC. Se quisermos que o mesmo programa rode em um Macintosh, precisaremos compilá-lo para rodar em Macintosh e assim por diante. Já com o Java isso não aconteceria, pois para rodarmos um programa feito em Java, usamos o interpretador Java (contido na JVM) para executar o bytecode resultante da compilação. Como o bytecode Java é independente de plataforma, os programas Java podem rodar em qualquer plataforma para a qual a JVM tenha sido portada. A JVM inclui o interpretador mais o sistema de runtime. Em um ambiente interpretado, a fase de linkagem que existem no desenvolvimento de programas tradicionais compilados praticamente desaparece. O equivalente em Java à fase de linkagem consiste apenas do processo de carregar novas classes no ambiente de execução da JVM. Esse é um processo leve e incremental, que ocorre em tempo de execução. Isso é diferente do ciclo compilar-linkar-rodar, mais trabalhoso, comum em linguagens como C e C++. O resultado é uma redução no tempo de desenvolvimento dos programas. Agora, depois dessa explicação, fica claro o que eles quiseram dizer com a frase "Write once, Compile once and Run anywhere" – ("Escreva uma vez, compile uma vez e rode em qualquer lugar"), frase esta que se tornou uma das marcas registradas de Java. A tecnologia java e configuração do ambiente 1-14 Uma Linguagem Segura e Dinâmica • Os bytecodes de Java são constantemente policiados pela JVM • Instruções não autorizadas levantam exceções de segurança • A carga das classes é feita de maneira dinâmica • Uma classe pode ser carregada através da rede ou do disco local da máquina Figura 1-4: Fluxo de compilação e execução de uma classe Java Durante a execução de um programa Java, a JVM pode importar código de qualquer lugar. A fim de tornar, a linguagem segura, é necessário ou nos certificarmos de que o local de onde o código se origina é seguro, ou policiarmos constantemente o código inseguro contra eventuais violações de segurança. A primeira opção é implementada através de sistemas de assinatura digital de código. A segunda opção, por sua vez, é de responsabilidade do sistema de runtime. Cabe a este policiar a execução dos bytecodes Java, verificando se não há, entre eles, nenhuma instrução não autorizada, que viole as regras de segurança estabelecidas pela linguagem. A tecnologia java e configuração do ambiente 1-15 O carregador de classes do sistema de runtime assegura que classes com origem em uma fonte local (classes Built-in) e classes provenientes da rede sejam armazenadas separadamente. Durante a execução, o sistema de runtime sempre procura resolver primeiro uma referência nas classes locais. Isto garante que classes locais não sejam substituídas por classes carregadas a partir da rede (fonte insegura). Elimina a possibilidade de sobrescrita de classes seguras (spoofing) por classes não confiáveis. O acesso ao sistema de arquivos locais e aos recursos de rede é controlado por classes da linguagem (Built-in classes). Estas classes são restritivas por default. Se código importado e classificado como inseguro tenta acessar o sistema de arquivos, os mecanismos de segurança avisam imediatamente ao usuário. A tecnologia java e configuração do ambiente 1-16 Aspectos de segurança Talvez pelo fato de Java estar fortemente associado à Internet, um dos aspectos mais divulgados da linguagem é sua segurança. Isso é natural: sem a certeza da segurança, provavelmente ninguém iria querer baixar código de um site desconhecido na Internet e deixar que ele rodasse em seu computador.E no entanto, isso já está sendo feito todos os dias com os applets Java. Java foi projetado com a segurança em mente. Por isso, oferece várias camadas de controles de segurança que protegem contra código malicioso, permitindo que os usuários rodem tranqüilamente programas de origem desconhecida, como os applets. No nível mais baixo, a segurança é uma conseqüência da robustez de Java. Como já vimos, os programas Java não podem forjar ponteirospara a memória, nem estourar arrays, nem ler memória que esteja fora das fronteiras de um array ou string. Esses recursos são uma das principais defesas de Java contra código malicioso. Ao impedir totalmente qualquer acesso direto à memória, toda uma enorme classe de ataques à segurança é evitada. A segunda barreira contra código malicioso é o processo de verificação do bytecode que é executado pelo interpretador Java sobre qualquer código de origem desconhecida que é carregado. Essa verificação assegura que o código seja bem formado – isto é, que ele não avance na memória que fica acima ou abaixo dos limites da pilha (stack overflow ou underflow), nem implemente bytecode ilegal. Se esse passo de verificação do bytecode não existisse, código corrompido por incompetência ou má fé poderia tirar partido de pontos fracos na implementação de um interpretador Java. Outra camada de proteção para segurança é comumente chamada de modelo de caixa de areia (sandbox): o código de origem desconhecida pode rodar, mas é mantido isolado dentro de uma caixa de areia, onde pode rodar em segurança sem causar qualquer dano ao "mundo real", que é o ambiente Java como um todo. Quando um applet, ou outro código de origem desconhecida está rodando dentro da caixa de areia, ele fica submetido a diversas restrições sobre o que pode fazer. A mais óbvia dessas restrições é que ele não tem acesso de nenhum tipo ao sistema de arquivos local. Existem ainda várias outras restrições à caixa de areia. Na verdade, existe uma classe, chamada SecurityManager, especialmente para cuidar da implementação dessas restrições. Para assegurar o funcionamento do modelo de segurança, todas as classes do núcleo Java que executam operações de risco, como acesso ao sistema de arquivos, primeiro pedem permissão ao SecurityManager atualmente instalado. Se a chamada está sendo feita, direta ou indiretamente, por código de origem desconhecida, o gerenciador de segurança lança uma exceção, impedindo a operação. A tecnologia java e configuração do ambiente 1-17 A versão Java 1.1, implementa um recurso adicional à questão da segurança: a assinatura digital. Anexando uma assinatura digital ao código Java, a origem desse código pode ser estabelecida de uma forma criptograficamente segura e impossível de falsificar. Desta forma, o usuário pode definir que uma determinada pessoa ou organização merece sua confiança. A partir daí, o código que traz a assinatura digital dessa entidade merece confiança mesmo que seja carregado através da rede, podendo rodar sem as restrições do modelo de caixa de areia. Porém, quando se trata de segurança, é preciso ser realista. Da mesma forma que nunca se pode garantir que um programa seja 100% livre de bugs, nenhuma linguagem ou ambiente pode ter a garantia de ser 100% seguro. Dentro desses limites, Java com certeza oferece um bom nível de segurança para a maioria das aplicações práticas. Java antecipa e se defende contra a maioria das técnicas que têm sido usadas para fazer com que software tenha comportamento malicioso. A segurança de Java foi intensamente testada por experts em segurança e também por hackers. Desta forma, foi possível sanar alguns furos de segurança encontrados nas primeiras versões de Java. É igualmente razoável esperar que quaisquer furos que venham a ser descobertos no futuro sejam sanados com a mesma rapidez. A tecnologia java e configuração do ambiente 1-18 O Just in Time Compiler - JIT • Traduzem bytecodes Java para instruções nativas da máquina. • Evitam a reinterpretação de blocos de código Java. • Úteis se o mesmo bloco de código é executado mais de uma vez. • Otimizam a execução de blocos de código repetitivos, como laços (for/while). A JVM transforma os bytecodes Java em instruções nativa de máquina. Se um bloco de código é executado diversas vezes, a JVM tem o trabalho reinterpretar este mesmo bloco de código toda vez que o fluxo de execução o atingir. Mas porque interpretar um bloco de código que não muda e já foi uma vez interpretado? Uma nova técnica, conhecida como compilação sob demanda (Just-in- Time Compilation ou JIT Compilation), foi então desenvolvida para contornar este tipo de situação. Compiladores JIT, quando encontram um bloco de bytecodes Java pela primeira vez, o traduzem de maneira definitiva para instruções nativas de máquina. Se o mesmo bloco é executado novamente, não há porque novamente interpretá-lo: as instruções nativas de máquina resultado da compilação Just-in- Time assumem o controle da execução, dispensando a necessidade de interpretação. Compiladores JIT aumentam o desempenho de programas Java, fazendo-os rodar mais rapidamente, uma vez que dispensam a necessidade de traduções sucessivas e “inúteis” de um mesmo bloco de bytecodes Java. Os ganhos de desempenho são mais significativos quando da otimização de laços e funções recursivas, em que um mesmo bloco de código é exaustivamente repetido. A tecnologia java e configuração do ambiente 1-19 O Java Standard Development Kit – J2SDK Abaixo temos uma figura que mostra toda a plataforma java de desenvolvimento. Observe que existem muitas tecnologias presentes nesta plataforma. Você não precisa saber todas elas para trabalhar com java. Colocamos esta figura de forma que você possa ver algumas importantes, as quais listamos abaixo: • [ javac ] – Compilador Java, traduz programas Java para bytecodes • [ java ] – Interpretador de bytecodes, para executar programas java • [ appletviewer ] – Visualizador de applets, lê uma página HTML, carrega o applet referenciado pela página e o executa, mostrando em sua própria tela a entrada e saída do applet • [ javadoc ] – Gerador de documentação, ferramenta que gera automaticamente documentação em HTML a partir dos comentários do código fonte Java • [ jar ] – Empacotador de aplicações java, para a geração e manutenção de archives (jar). O formato de arquivos JAR possibilita o agrupamento de múltiplos arquivos em um único, que recebe o nome de Java Archive (ou .jar). Desta forma, um único arquivo .jar tipicamente contém vários binários Java (arquivos .class) e arquivos auxiliares de recursos utilizados pelo applet ou application Java • [ javap ] – Disassembler, ferramenta recebe como entrada um binário Java (arquivo .class) e fornece como saída uma lista de comandos assembly da máquina virtual Java referentes ao binário analisado, ou uma lista de protótipos de classes encontradas no binário • [ Swing ] – Framework para criação de interfaces dráficas • [ Java Web Start ] – Tecnologia para distribuição de software • [ JDBC ] – Framework para conexão com banco de dados A tecnologia java e configuração do ambiente 1-20 Arquitetura da tecnologia java Na figura abaixo você tem listadas as tecnologias que fazem parte da versão 5.0 do Java. Estas tecnologias são parte do JRE (Java Runtime Environment) e do JDK ( Java Development Kit). Figura 1-5: Estrutura do JDK e JRE A tecnologia java e configuração do ambiente 1-21 Figura 1-6: Relação dos grupos de tecnologias A tecnologia java e configuração do ambiente 1-22 Configurando o ambiente Para trabalhar com a linguagem java na sua máquina é preciso configurar algumas coisas antes de escrever o promeiro programa. Estas configurações não são necessárias na máquina do usuário que irá rodar a sua aplicação, sendo configurações somente para a máquina do desenvolvedor. Você precisará adicionar as seguintes variáveis de ambiente ao sistema operacional que estiver utilizando: 1) JAVA_HOME - local onde foi instalado o java na sua máquina. Esta variávelé utilizada por programas para localizar a máquina virtual java e o compilador 2) CLASSPATH – esta variável contém o caminho onde estão as classes/bibliotecas java que o programa irá utilizar. Se você baixar algum pacote jar da internet com classes que desejar utilizar, será necessário colocar o caminho deste pacote nesta variável para que as classes do mesmo sejam localizadas no momento da compilação 3) PATH – esta variável é importante estar configurada para poder rodar os programas que estão localizados dentro do diretório bin da sua instalação do java Versão para windows: JAVA_HOME=C:\jdk1.5 CLASSPATH=%JAVA_HOME%\lib\tools.jar PATH=%JAVA_HOME%\BIN;%PATH% Codigo 1-1: Configuração das variáveis de ambiente para windows Versão para linux: JAVA_HOME=/jdk1.5 CLASSPATH=$JAVA_HOME/lib/tools.jar PATH=$JAVA_HOME/bin;$PATH Codigo 1-2: Configuração das variáveis de ambiente para linux A tecnologia java e configuração do ambiente 1-23 API’s da linguagem Java possui um conjuntomuito grande classes para serem utilizadas no desenvolvimento de palicações. Estas classes estão organizadas em pacotes que fazem parte do JDK. Abaixo você tem alguns dos principais pacotes que serão utilizados para o desenvolviemtno de aplicações. Para ter uma visão do todo basta acessar a documentação do JDK através de um browser. Siga o seguinte link para isto: http://java.sun.com/j2se/1.5.0/docs/api/ java.applet Fornece as classes necessárias para a criação de um applet e para a comunicação que posteriormente se estabelece entre o applet e o contexto em que executa. java.awt Contém todas as classes para a criação de interfaces gráficas do usuário e controle de imagens. java.beans Contém as classes relacionadas aos desenvolvimento de Java Beans. java.io Permite entrada e saída através de data streams, serialization e sistema de arquivos. java.lang Classes relacionadas ao próprio projeto da linguagem Java, referindo-se à manipulação e conversão de tipos, strings, threads e ambiente de execução. java.math Classes utilizadas para aritmética de inteiros de precisão arbitrária (BigInteger) e para a aritmética de decimais de precisão arbitrária (BigDecimal) java.net Classes contendo facilidades de comunicação em rede (manipulação sockets, resolução de nomes, estabelecimento de canais de comunicação). java.security Classes e interfaces relacionadas às questões de segurança. java.sql Classes que permitem interface com o banco de dados (JDBC) java.text Classes e interfaces para manipulação de texto, datas, números e mensagens. java.util Miscelânea de classes auxiliares: tratamento do tempo, gerador de números aleatórios, vetores de bits, internacionalização do aplicativo, manipulação de archives Java, etc. javax.swing Conjunto de componentes visuais “peso leve” que, com o máximo grau de compatibilidade possível, funcionam da A tecnologia java e configuração do ambiente 1-24 mesma maneira em todas as plataformas. Tabela 1-1: Pacotes mais comuns da API J2SDK A tecnologia java e configuração do ambiente 1-25 Espaço para anotações Java Fundamentals 2-1 22.. TTiippooss ee OOppeerraaddoorreess Tipos e operadores 2-2 Objetivos • Compreender as seguintes estruturas: o Variáveis o Tipos Primitivos o Literais • Compreender os tipos de dados primitivos: o char o boolean o byte, short, int, long o float, double • Compreender os tipos de dados compostos • Apreender conversões de tipos • Conceituar expressões e operadores • Definir precedência e associatividade entre estruturas Tipos e operadores 2-3 Variáveis Java é uma linguagem fortemente tipada. Isto significa que a utilização de qualquer variável deve ser compatível com a sua prévia definição. Compete ao compilador da linguagem verificar, antes mesmo da execução do programa (isto é, de maneira estática), se há a referida compatibilidade entre definição e uso de uma variável. Os contextos em que uma variável pode ser validamente empregada são determinados pelo seu tipo. O tipo determina a utilização: restringe as operações aplicáveis e concede sentido ao resultado de uma operação válida (semântica da operação). Seria contra-senso somarmos um tipo booleano com outro tipo booleano ou, ainda pior, multiplicarmos um booleano por um número fracionário. Qual a resposta esperada para estas operações? Não há resposta, porque a operação frente aos tipos carece de coerência. Ao definirmos um inteiro (ou um número real, ou um booleano, etc.), estamos a dizer quais operações são válidas quando aplicadas a este inteiro (real, booleano, etc.) e quais simplesmente carecem de sentido. Decorrem do fato de Java ser fortemente tipada: • Todas as variáveis em Java devem ter um tipo associado (a fim de que se possa avaliar futuramente se os empregos dados a esta variável são ou não corretos) • A utilização de uma variável deve ser posterior à sua definição • As conversões forçadas de tipo (casts) devem ser rigidamente controladas pela linguagem, tanto sob o aspecto estático (não se permitindo conversões entre tipos distintos, e autorizando tão somente a conversão entre tipos derivados), quanto sob o aspecto dinâmico (controle em tempo de execução das conversões de tipo efetuadas). • Não se permitem conversões implícitas de tipo. Todas as conversões de tipo devem ocorrer de maneira expressa. Tipos e operadores 2-4 Tipos primitivos e tipos compostos Tipos primitivos são aqueles tipos já embutidos na linguagem java e estudados no capítulo anterior, enquanto tipos compostos são todas as classes da linguagem java ou classes que você venha a criar. Variáveis de tipos primitivos são tratadas de uma maneira bem diferente de variáveis de referências para objetos ( variáveis de tipos compostos). É bastante importante saber quais são estas diferenças e porque Java foi projetada desta forma. Variáveis de tipos primitivos Quando você declara uma variável de um tipo primitivo, Java aloca um pedaço de memória que é grande o suficiente para guardar valores do tipo primitivo declarado. Se você define uma variável de tipo primitivo como uma variável de instância, a variável é inicializada para 0 se for inteira, para false se for booleana e para '\0' se for caractere. Variáveis de tipos primitivos armazenam o seu valor diretamente. Se você, por exemplo, declara uma variável do tipo int e atribui um valor 3 para esta variável, o valor é armazenado diretamente nos quatro bytes reservados para a variável. Variáveis de referências para objetos (tipos compostos) Quando você declara uma variável de referência, você também recebe um pedaço de memória, mas esta memória é grande o suficiente para armazenar apenas uma referência para o objeto. Talvez seja útil pensar em uma referência como um apontador para o objeto. Como mencionado antes, declarar uma variável de referência não cria um objeto do tipo especificado. Conseqüentemente, uma variável de instância é inicializada para null a fim de indicar que ainda não recebeu referência para nenhum objeto ainda. Tipos e operadores 2-5 Use o operador de atribuição para fazer com que uma variável de referência se refira a uma instância de uma classe. A atribuição pode ser para um objeto existente ou para um objeto recém criado através do operador new. Tipos e operadores 2-6 Tipos Primitivos Tipos primitivos são aqueles fornecidos diretamente pela linguagem, ou seja, tipos já embutidos na linguagem. São tipos atômicos, indivisíveis e sobre os quaisa linguagem, de ante mão, já oferece operações pré-definidas. Exemplos de tipos primitivos são inteiros e booleanos. Para usá-los, basta associá-los a uma variável. A maior parte das linguagens permite ao programador criar tipos compostos. Tipos compostos procuram representar de maneira conjunta e unificada os vários atributos de uma entidade modelada. Um catálogo telefônico pode ser representado dentro de um programa como uma lista de Strings contendo nomes, outra contendo os endereços e, por fim, uma outra contendo os telefones. Todas as informações necessárias à pesquisa ou à manipulação do catálogo estão presentes em tais listas. Mas esta definitivamente não é a melhor maneira de se representar um catálogo telefônico. Se perguntarmos a alguém o que é um catálogo, dificilmente ouviremos como resposta uma lista de nomes, endereços e telefones. A resposta mais provável é uma lista de assinantes. Um assinante, por sua vez, é identificado pelo nome que possui ou endereço onde reside. Ao procurarmos descobrir o telefone de um assinante, pesquisaremos pelas chaves que o identificam: nome ou endereço. A representação estruturada da informação é, em si, informação relevante. Ao modelarmos um catálogo como uma lista de assinantes e identificarmos um assinante pelo seu nome ou endereço, estamos trazendo para dentro do programa não apenas informação contida em um catálogo, mas também a própria estrutura de um catálogo: informação sobre como a informação é organizada. Os tipos compostos não são apenas armazéns de dados. A sua função principal não é conter o dado, pois para isto já temos tipos primitivos. O seu objetivo principal é organizar a informação. Aproximar a estrutura empregada na confecção do modelo da estrutura existente no mundo real modelado. Tornar a tarefa de programar mais intuitiva, permitindo uma relação direta entre o modelo e o objeto modelado. A representação do dado dentro do programa facilita a compreensão do próprio programa como modelo. Não basta fazer um programa (modelo) que funcione. É necessária tanto uma compreensão do mundo real através do programa, quanto uma compreensão do próprio programa como modelo do mundo real. Tipos compostos são construídos tendo como blocos construtores tipos primitivos ou, de maneira recursiva, outros tipos compostos. Em última análise, os tipos primitivos são os únicos responsáveis pela construção dos tipos compostos. Um tipo composto nada mais é que um conjunto organizado de tipos primitivos. Tipos compostos serão vistos em capítulos posteriores. Tipos e operadores 2-7 Java possui oito tipos primitivos: boolean, char, byte, short, int, long, float e double. Cada um destes tipos será estudado de maneira mais detalhada nas seções seguintes. A tabela abaixo apresenta um resumo dos tipos primitivos encontrados na linguagem Java. Cumpre observar que o tamanho do tipo em bytes e a sinalização fazem parte da especificação da linguagem. Ou seja, um char em Java ocupará sempre 16 bits, um int 32 bits, um long 64 bits, e assim por diante, independente da plataforma em que o programa esteja sendo executado. Tipos e operadores 2-8 Tabela 2-1: Tipos primitivos e suas características. Ao contrário do que acontece com outras linguagens de programação, as características dos tipos de dados listados acima idependem da plataforma em que o programa deverá ser executado. Dessa forma, os tipos de dados primitivos são realmente únicos e garantem a capacidade de intercâmbio de informações entre diversos tipos de Tipo Contém Default Tamanho Faixa de valores boolean true ou false false 1 bit Pode assumir o valor true ou o valor false char caracter Unicode \u0000 16 bits Serve para a armazenagem de dados alfanuméricos. Também pode ser usado como um dado inteiro com valores na faixa entre: 0 e 65535 (\u0000 a \uFFFF) byte inteiro com sinal 0 8 bits Inteiro de 8 bits em notação de complemento de dois. Pode assumir valores entre: -27 a 27-1 short inteiro com sinal 0 16 bits Inteiro de 16 bits em notação de complemento de dois. Os valores possívels cobrem a faixa entre: -215 a 215-1 int inteiro com sinal 0 32 bits Inteiro de 32 bits em notação de complemento de dois. Pode assumir valores entre: -231 a 231-1 long inteiro com sinal 0 64 bits Inteiro de 64 bits em notação de complemento de dois. Pode assumir valores entre: -263 a 263-1 float ponto flutuante 0.0 32 bits Representa números em notação de ponto flutuante. A sua representação é exponencial, sendo alguns bits utilizados para base e outros para o expoente. double ponto flutuante 0.0 64 bits Representa números em notação de ponto flutuante. A sua representação é exponencial, sendo alguns bits utilizados para base e outros para o expoente. Tipos e operadores 2-9 computadores, aliviando o programador da preocupação e da árdua tarefa de converter dados em formatos apropriados para a portagem. Tipos e operadores 2-10 Declarando um tipo primitivo São oito os tipos primitivos de Java: boolean, char, byte, short, int, long, float e double. Quarenta e quatro são os operadores que podem ser utilizados na manipulação destes tipos primitivos. Declarar e inicializar uma variável de um tipo primitivo é extremamente fácil. Basta, a exemplo da seguinte linha de código, associar ao identificador escolhido pelo usuário para a variável um dos tipos acima, atribuindo, logo em seguida, um literal para esta variável. Código 2-1: Literais primitivos. O que é uma literal? Uma resposta simples seria: constantes para cada um dos tipos primitivos de uma linguagem. Na verdade, literais são construções sintáticas fornecidas pela linguagem para exprimir valores constantes para cada um dos tipos primitivos. Tais construções determinam como devem ser escritos um caractere, um inteiro, um valor booleano, etc. A maior parte das linguagens permite que haja mais de uma forma de se escrever um valor inteiro, ora transcrevendo o valor inteiro em uma base de numeração Octal, ora transcrevendo-o em uma base Decimal, ora em uma base Hexadecimal. O mesmo ocorre para os números em ponto flutuantes: a maior parte das linguagens permite que ora sejam escritos em notação convencional (parte inteira + caractere separador + parte fracionária), ora em notação científica (número fracionário + expoente em potência decimal). Conjunto de Caracteres Unicode Tipos e operadores 2-11 Os programas Java são escritos usando o conjunto de caracteres Unicode. Ao contrário da codificação de 7 bits ASCII, que é útil somente para a língua inglesa, e codificações de 8 bits, tais como ISO Latin-1, que é útil somente para a maior parte das línguas da Europa Ocidental, a codificação Unicode, de 16 bits, consegue representar praticamente todas as linguagens de uso freqüente no planeta. Entretanto, poucos editores de texto suportam caracteres Unicode, e na prática, a maior parte dos programas são escritos em ASCII. Os caracteres Unicode, de 16 bits, são usualmente escritos em arquivos usando uma codificação conhecida como UTF-8, que converte os caracteres de 16 bits em uma seqüência de bytes. O formato é projetado de forma que um texto escrito em ASCII ou em ISO Latin-1 são seqüências de bytes UTF-8 válidas. Desta forma, você pode simplesmente escrever programas em ASCII e eles se comportarão, graças às características de projeto da codificação UTF-8, como textos Unicode válidos. Se você quiser inserir um caracter Unicode dentro de um programa Java escrito em ASCII, basta usar a seqüência de escape especial para caracteres Unicode \uxxxx. Isto é, uma contrabarra mais a letra u em minúscula seguida de quatro caracteres hexadecimais.A seqüência de escape \u0020 representa caracter de espaço, e a seqüência \u3c00 é o caracter pi. Você pode usar caracteres Unicode em qualquer lugar em um programa Java, incluindo comentários e nome de variáveis. Podemos encontrar a tabela unicode no seguinte endereço: http://www.unicode.org Tipos e operadores 2-12 Tipo caracter – char O tipo char representa caracteres Unicode. É motivo de surpresa para experientes programadores descobrir que valores char em Java possuem 16 bits de extensão. Na prática, no entanto, isto fica completamente transparente.Um literal caracter em Java sempre vem entre aspas simples. Código 2-2: Declarando um tipo char Você pode, é claro, usar qualquer caracter Unicode como um literal caracter, sendo necessário tão somente o emprego de seqüências de escape \uxxxx Unicode. Java suporta também várias outras seqüências de escape que facilitam a representação de caracteres ASCII não visíveis, tais como nova linha ou backspace, e permitem o escape na construção de literais contendo caracteres de pontuação com significado especial, tais como aspas duplas ( “ ) e aspas simples ( ‘ ). Por exemplo: Código 2-3: Exemplos de char especiais char a = ′A′, espaco = ′ ′; char tab = ′\t′, apostrofe = ′\′′, nulo = ′′; char unicode = ′\u05D0′; Tipos e operadores 2-13 A tabela abaixo mostra os caracteres de escape que podem ser utilizados na construção de um literal caracter. Seqüência de escape Valor do caracter \b backspace \t tabulação horizontal \n nova linha \f alimentação de formulário \r retorno de carro \” aspas duplas \’ aspas simples \\ contrabarra \uxxxx Caracter Unicode com codificação xxxx, onde xxxx são quatro dígitos hexadecimais. Tabela 2-2: Caracteres de escape do tipo char Estas seqüências de escape podem também ser usadas em literais para Strings. Valores do tipo char não podem ser convertidos para e a partir de tipos inteiros. Ao contrário de byte, short, int e long, o tipo char é um tipo não sinalizado (unsigned). A classe Character vários métodos estáticos (static methods) para trabalhar com caracteres, incluindo isLowerCase() e toUpperCase(). Tipos e operadores 2-14 Tipo booleano – boolean O tipo boolean procura representar predicados. Há somente dois valores possíveis para este tipo, representando os dois estados booleanos: ligado ou desligado, sim ou não, verdadeiro ou falso. Java reserva as palavras true e false para representar estes dois valores booleanos. Programadores C e C++ devem ter notar que Java é bem restritiva quanto à utilização do tipo booleano: valores booleanos não podem ser diretamente convertidos para outros tipos de dados, nem estes podem ser convertidos para booleanos. Em especial, o valor booleano não é um tipo inteiro (onde false é representado por 0 e true por qualquer valor diferente de 0), e valores inteiros não podem ser usados no lugar de um valor booleano. Os exemplos abaixo mostram a utilização incorreta de valores booleanos. No primeiro exemplo, um booleano é esperado e um inteiro é fornecido. Errado Correto int i = 10; while(i) { ... i--; } int i = 10; while(i!=0) { ... i--; } Tabela 2-3: Utilização do tipo boolean em C++ e Java Não há (como ocorre com C e C++) conversão, implícita ou forçada, entre booleanos e inteiros (ou outro tipo primitivo qualquer). Tipos e operadores 2-15 Tipos inteiros - byte, short, int e long Os tipos inteiros em Java são byte, short, int e long. Os tipos inteiros diferem exclusivamente no número de bits usados para a representação do número e, portanto, na extensão da faixa de números que conseguem representar. Todos os tipos inteiros são sinalizados. Não existe em Java nada equivalente à especificação unsigned de C ou C++. Literais inteiros para cada um destes tipos são construídos da maneira esperada: uma seqüência de números decimais. Qualquer literal inteiro pode ser precedido por um operador unário menos, a fim de indicar um número negativo. Alguns literais inteiros: Código 2-4: Literais inteiros int Literais inteiros podem ser expressos também em notação octal ou hexadecimal. Um literal que começa com 0x ou 0X é interpretado como um número hexadecimal, valendo-se das letras A a F (ou a a f) para os dígitos restantes requeridos em números de base 16. Literais inteiros que têm um dígito 0 em seu início são interpretados como números octais (base 8) e, portanto, entre os dígitos subseqüentes não podem figurar os algarismos 8 e 9. Java não permite que literais inteiros sejam expressos em notação binária (base 2). Literais inteiros octais e decimais válidos: Código 2-5: Literais inteiros int em hexa e octal Literais inteiros exprimem valores de 32 bits, a menos que terminem com o caracter L ou l, indicando, neste caso, serem tais literais valores de 64 bits. 0 1 -123 -4200 0xff // decimal 255 expresso em hexa 0377 // mesmo número expresso em octa 1234 // um valor int 1234L // um valor long 0xffL // outro valor long Tipos e operadores 2-16 Código 2-6: Literais inteiros int e long A aritmética inteira em Java é modular. Não há transbordo ou estouro na manipulação de números inteiros. Ao contrário, ao exceder a faixa de um determinado tipo inteiro, em uma das extremidades, o resultado da operação avança de maneira circular sobre a extremidade oposta. Por exemplo: Código 2-7: Exemplo de expressão byte com aritmética circular Nem o compilador Java, nem a JVM avisará quando ocorrer transbordo em aritmética inteira. Desta maneira, ao manipular inteiros, você deve ter certeza que o tipo que está usando é grande o suficiente para os propósitos que tem em mente. Que a faixa de números oferecida pelo tipo é larga o suficiente para as operações pretendidas. Divisões inteiras por zero e operações módulo zero não são aceitas e lançam a exceção ArithmeticException. Cada tipo inteiro tem uma classe invólucro correspondente (wrapper classes): Byte, Short, Integer e Long. Cada uma dessas classes define as constantes MIN_VALUE e MAX_VALUE que descrevem as extremidades da faixa de números suportada pelo tipo. Estas classes também definem vários métodos estáticos extremamente úteis, tais como Byte.parseByte() e Integer.parseInt(), empregados na conversão de strings para inteiros. byte b1 = 127, b2 = 1; byte sum = b1 + b2; // sum = -128, que é o menor byte Tipos e operadores 2-17 Tipos de ponto flutuante - float e double Números reais são representados em Java com os tipos float e double. Como mostrado anteriormente, o tipo float representa um valor de ponto flutuante, de 32 bits, de precisão simples, enquanto o tipo double representa um valor de ponto flutuante de 64 bits, de precisão dupla. Ambos os tipos seguem o padrão IEEE 754-1985, que especifica tanto o formato dos números quanto o comportamento da aritmética com estes números. Literais de ponto flutuante podem ser representados em Java como uma seqüência opcional de dígitos decimais seguido por um ponto e outra seqüência de dígitos decimais. Alguns exemplos: Código 2-8: Literais float e double Literais de ponto flutuante também podem ser representados através de notação científica, na qual um número é seguido pela letra e ou E (assinalando o expoente) e por um outro número. Este segundo número representa a potência de dez pela qual o primeiro número é multiplicado. Por exemplo: Código 2-9: Literais float em notação científica Números de ponto flutuante são double por default. Para representar um literal de ponto flutuante floatem um programa, basta acrescentar o caracter f ou F no final do número. Código 2-10: Literais float e double em notação científica Literais de ponto flutuante não podem ser representados em notação hexadecimal ou octal. A maior parte dos números reais, pela sua natureza, não 123.45f // float 0.0 // double .02 // double 1.2345E02 // 1.2345 x 102 ou 123.45 1e-6 // 1 x 10-6 ou 0.000001 6.02e23 // No. de Avogrado 6.02 x 1023 double d = 6.02e23; float f = 6.02e23f; Tipos e operadores 2-18 pode ser representada exatamente em um número finito de bits. Portanto, é importante se lembrar que os valores double e float são apenas aproximações dos números que eles procuram efetivamente representar. Um float é uma aproximação de 32 bits, o que resulta em pelo menos 6 dígitos decimais significativos, e o double é uma aproximação de 64 bits, o que, por sua vez, resulta em pelo menos 15 dígitos decimais significativos. Na prática, estes tipos são suficientes para a maior parte das computações de ponto flutuante. Tipos e operadores 2-19 Tipo composto – String Além dos tipos primitivos caracter, booleano, inteiro e real, Java também possui um tipo de dado próprio para trabalhar com seqüências de texto (Strings). O tipo String, no entanto, não é um tipo primitivo da linguagem. Devido ao uso extremamente freqüente de Strings em um programa, Java permite uma sintaxe especial para a representação de literais Strings. Um literal String consiste de uma porção arbitrária de texto delimitada por aspas duplas. Por exemplo: Código 2-11: Literias Strings Literais Strings podem conter qualquer uma das seqüências de escapes permitidas para um valor char. Utilize a seqüência \" para incluir aspas duplas dentro de um literal String. String e literais Strings serão discutidos com mais detalhes a seguir. "Hello, World" "Isto é uma string \n" Tipos e operadores 2-20 Conversões de tipos – casting Java permite conversão entre valores inteiros e valores reais. Além disto, por corresponder todo caracter a um número na codificação Unicode, o tipo char pode ser convertido para e a partir de um tipo inteiro ou de ponto flutuante. De fato, o tipo boolean é o único tipo que não pode ser convertido para ou a partir de um outro tipo primitivo em Java. Há dois tipos de conversão. Uma conversão de ampliação (widening conversion) ocorre quando um valor de um tipo é convertido para outro tipo mais amplo um tipo que possui mais bits de representação e, portanto, uma faixa mais ampla de valores representados. Uma conversão de redução (narrowing conversion) ocorre quando um valor é convertido para outro que possui menos bits de representação. Java automaticamente se encarrega das conversões de ampliação quando, por exemplo, uma variável double recebe um valor int, ou um literal char é atribuído a uma variável int. Conversões de redução são um problema a parte, e nem sempre são seguras. É razoável, por exemplo, converter o valor inteiro (int) 13 para um byte, mas não o é fazer a mesma conversão para o valor 13000, pois o tipo byte suporta somente valores entre –128 e 127. A informação pode ser perdida em conversões de redução e o compilador Java sempre reclama quando há uma tentativa de efetuar uma conversão de redução, ainda que o valor sendo convertido se situe entre os valores aceitos pela faixa mais estreita do novo tipo. Código 2-12: Atribuição de valor inteiro int não permitida para byte A única exceção a esta regra é que você pode atribuir um literal inteiro (portanto, um valor int) para uma variável byte e short, se o literal pertencer à faixa de representação desta variável. Se você precisa de conversões de redução e está confiante que o pode fazer sem perda de informação ou precisão, você pode forçar Java a executar a conversão usando uma construção da linguagem conhecida como cast (conversão explícita). A conversão explícita é feita colocando-se o nome do tipo pretendido entre parênteses antes da variável a ser convertida. Por exemplo: int i = 13; byte b = i; // Erro em tempo de compilação. int i = 13; byte b = (byte) i; i = (int) 13.456; Tipos e operadores 2-21 Código 2-13: Conversão forçada de tipos primitivos Casting de tipos primitivos são mais freqüentes em conversões de números reais para inteiros. Quando isto ocorre, a parte fracional do número real é simplesmente truncada (o valor de ponto flutuante é arredondado para zero e não para o inteiro mais próximo). Os métodos Math.round(), Math.floor() e Math.ceil() permitem outros tipos de arredondamento. Código 2-14: Atribuição de valores implícitos e expressos O tipo char funciona como um tipo inteiro a maior parte das vezes, podendo, portanto, ser usado em qualquer lugar em que se espere um int ou long. Lembre-se, no entanto, que o tipo char é não sinalizado e se comporta de maneira diferente do tipo short, embora ambos possuam 16 bits. short s = (short) 0xffff; char c = '\uffff'; int i1 = s; int i2 = c; Tipos e operadores 2-22 Tipos de referência Além dos oito tipos primitivos, Java define duas outras categorias de tipos: classes e vetores. Programas em Java são construídos através de definições de classes; cada classe define um novo tipo de dado que pode ser manipulado por programas Java. Um programa pode, por exemplo, definir uma classe chamada Ponto e usá- la para armazenar coordenadas (x,y) de um sistema cartesiano de coordenadas. Com isto, Ponto passa a ser um novo tipo de dado em um programa. Um tipo vetor representa uma lista de valores de um determinado tipo. int é um tipo de dado, e um vetor de valores do tipo int é outro tipo de dado, escrito em Java como int[]. Um vetor de objetos do tipo Ponto também é um tipo, escrito como Ponto[]. E um vetor de vetores de Ponto é também um outro tipo, escrito em Java como Ponto[][]. Como você pode ver, há um número infinito de tipos de dados de classes e vetores possíveis. Basta o programador defini-los. Estes tipos são conhecidos coletivamente como tipos de referência. A razão para este nome ficará clara logo a seguir. Por enquanto, é importante compreender apenas que classes e vetores são tipos de dados diferentes dos tipos primitivos. Tipos de dados de classes e vetores são conhecidos como tipos compostos. Um tipo de dado primitivo guarda somente um único valor. Classes e vetores são tipos agregados que contém vários valores. O tipo Ponto, por exemplo, armazena dois valores double representando as coordenadas x e y do ponto. Classes e vetores serão retomados logo adiante. Código 2-15: Tipos de referências: arrays e Strings int[] vet = {1,2,3}; String str = new String(“Java”); Tipos e operadores 2-23 Expressões e operadores Até o presente momento, aprendemos sobre os tipos primitivos que os programas Java são capazes de manipular e vimos como construir literais para cada um destes tipos. Utilizamos também variáveis, nomes simbólicos que representam e armazenam um valor. Literais e variáveis são importantes tokens com os quais programas são construídos em Java. Expressões são o próximo nível de estrutura de um programa Java. O interpretador Java (JVM) avalia uma expressão para determinar o seu resultado. As expressões mais simples são chamadas expressões primárias e consistem de apenas um literal ou uma variável. São exemplos de expressões primárias: Código 2-16: Expressões primárias Quando o interpretador Java avalia uma expressão literal, o resultado da avaliação é o próprio literal. Quando o interpretador avalia uma expressão contendo uma
Compartilhar