Baixe Java Fundamentals I Objetivos 1-2 O que é Java 1-3 Simples e orient e outras Notas de estudo em PDF para Análise de Sistemas de Engenharia, somente na Docsity! Java Fundamentals 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. Coleções, Arrays, Strings, e Wrapper Classes ............... 6-1 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-29 Interfaces 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. Tratamento de Exceções............................................. 7-1 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. Classes abstratas e Interfaces ..................................... 8-1 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 1. A tecnologia Java e configuração do ambiente 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 objetos para 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-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-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 ponteiros para 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-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-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 2. Tipos e Operadores 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 quais a 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-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 π. 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-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-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-24 Código 2-18: Expressões válidas e combinadas Tipos e operadores 2-25 Sumário de operadores Os tipos de expressões que você pode escrever em uma linguagem de programação dependem completamente do conjunto de operadores que a linguagem disponibiliza. A tabela abaixo apresenta síntese dos operadores disponíveis em Java. A colunas P e A desta tabela indicam, respectivamente, a precedência e a associatividade de cada grupo de operadores correlatos. Neste curso veremos alguns operadores listados na tabela abaixo, os demais serão vistos a medida do estudo da linguagem. Operadores Tipo de operando Operação executada . objeto, membro acesso a membro do objeto [] vetor, inteiro acesso a elemento do vetor ( args ) método, lista de args invocação do método ++, -- variável pós incremento, pós decremento ++, -- variável pré incremento, pré decremento +, - número mais unário, menos unário ~ inteiro complemento (NOT bit a bit) ! booleano NOT booleano new classe, lista de args criação de objetos (type) tipo, qualquer coisa cast (conversão explícita de tipo) *, /, % número, número multiplicação, divisão e resto +, - número, número adição e subtração + string, qqr coisa concatenação de strings <, <= número, número menor que, menor que ou igual >, >= número, número maior que, maior que ou igual instanceof referência, tipo comparação de tipos == primitivo, primitivo igual (o mesmo valor) != primitivo, primitivo não igual (valores diferentes) Tipos e operadores 2-26 == referência, referência igual (o mesmo objeto) != referência, referência não igual (objetos diferentes) & inteiro, inteiro AND bit a bit & booleano, booleano AND booleano ^ inteiro, inteiro XOR bit a bit ^ booleano, booleano XOR booleano | inteiro, inteiro OR bit a bit | booleano, booleano OR booleano && booleano, booleano AND booleano com curto circuito || booleano, booleano OR booleano com curto circuito ? : booleano, qqr coisa, qqr coisa operador ternário condicional = variável, qqr coisa atribuição *=, /=, %=, +=, -=, <<=, >>=, >>>=, &=, ^=, |= variável, qqr coisa atribuição geminada com operação Tabela 2-4:Sumário de Operadores Tipos e operadores 2-29 Tipos de operadores: unários e binários A quarta coluna da tabela acima especifica o número e o tipo dos operandos esperados para cada operador. Alguns operadores atuam somente sobre um único operando; são chamados operadores unários. A maior parte dos operadores, no entanto, são operadores binários e atuam sobre dois operandos. Exemplo operador unário: i++ é igual a i = i + 1 Exemplo operador binário: res = x + y Tipos e operadores 2-30 Espaço para anotações Tipos e operadores 2-31 Criando classes e objetos 3-3 Classes e Objetos Uma classe é um gabarito utilizado para criar múltiplos objetos. Uma classe encapsula todos os dados e comportamentos que definem um objeto. Quando você pede ao interpretador Java para criar ou instanciar um objeto, Java usa a definição de classes como gabarito para a criação de novos objetos. Uma classe pode conter atributos que são atribuídos a todos os novos objetos desta classe. Atributos são informações ou dados que descrevem, categorizam ou quantificam um objeto. Cada novo objeto de uma dada classe terá seu próprio conjunto de atributos de classe. Um objeto da classe Cliente, por exemplo, terá um nome, um endereço e um número telefônico como atributos. Dados armazenados em um objeto podem ser tanto primitivos, tais como inteiros ou caracteres, ou referências para outros objetos. Uma classe pode conter também métodos ou funções que especifiquem o comportamento ou ações que a classe consegue realizar. A classe Cliente, por exemplo, pode alugar um carro, efetuar um pagamento ou alterar o seu endereço. Java utiliza pacotes para agrupar classes que estão logicamente relacionadas. Pacotes consistem de classes fisicamente localizadas em um mesmo diretório. Pacotes também são usados para controlar o acesso de classes definidas fora do pacote. Criando classes e objetos 3-4 Criando uma classe O bloco contendo a definição de uma classe começa pela palavra reservada class. No código abaixo temos a criação de uma classe para reprensentar um Produto. Código 3-1: Declaração da classe Produto Uma classe – o bloco de construção básico para uma linguagem orientada a objetos – é uma coleção de dados e de métodos que manipulam estes dados. A classe é um modelo abstrato, a partir do qual serão criadas instâncias desta classe, contendo os dados e os métodos nela definidos. Observe que a definição da classe acima é muito simples e a mesma é feita através da palavra reservada class. O par de chaves utilizado serve para delimitar o corpo da classe, ou seja, onde iremos colocar as operações e atributos da mesma. Veremos mais adiante como colocar os atributos e operações Os dados referentes a uma classe são armazenados em variáveis e as operações efetuadas sobre estes dados são implementadas através de métodos. Seguindo os passos contidos nesta lição você conseguirá criar e executar sua primeira Java Application. Para isto vamos adicionar um método especial nesta classe que nos permitirá executar a máquina virtual e executar algum código. Tomaremos como exemplo, para a primeira Java Application, o consagrado “Hello World”. Este programa, bastante simples, imprime na tela do computador a mensagem “Hello World”. Usando um editor de texto, crie um arquivo de nome HelloWorld.java contendo as seguintes linhas. Código 3-2: Exemplo de HelloWorld Java class Produto { } class HelloWorld { public static void main( String[] args ) { System.out.println( "Hello World!" ); } } Criando classes e objetos 3-5 O arquivo fonte pode ser compilado através de seu IDE ou usando o compilador javac através de linha de comando como mostrado abaixo Código 3-3: Compilando uma classe Java Obtendo êxito na compilação, o arquivo HelloWorld.class, contendo os bytecodes Java, será criado pelo compilador no mesmo diretório em que se encontra o arquivo fonte. Caso o compilador tenha reportado alguma falha, verifique se não digitou algo incorretamente, prestando atenção para o uso de maiúsculas e minúsculas. Certifique-se também de ter dado ao arquivo o nome correto. Execute a aplicação Java usando a máquina virtual fornecida pelo JDK (java): Código 3-4: Executando uma classe Java sem pacote Você verá a mensagem “Hello World!” escrita na tela de seu computador. C:\> javac HelloWorld.java C:\>java HelloWorld Hello World! Criando classes e objetos 3-8 Nome de pacotes Pacotes devem possuir nomes significativos e não devem ter seus nomes separados por caracteres como “_”. Seus nomes devem ser escritos sempre com todas as letras em minúsculo e os nomes de pacotes seprados pelo caractere ponto (“.”). Veja o exemplo abaixo: Exemplo: com.targettrust.database Observe que o nome do pacote foi iniciado com a palvra “com” e em seguida com a palavra targettrust. Normalmente começamos o nome de um pacote com o inverso do domínio da empresa. Isto explica o porque utilizar com.targettrust no início do nome do pacote. Criando classes e objetos 3-9 Criando e importando pacotes Java fornece o mecanismo de pacote como uma maneira de agrupar as classes relacionadas. A declaração de pacote, caso exista, deve estar no início do arquivo de origem. Ela pode ser precedida apenas de espaços em branco e comentários. Somente uma declaração de pacote é permitida e influencia todo o arquivo de origem. Os nomes de pacote são hierárquicos e separados por pontos. Convencionalmente, os elementos do nome de pacote estão normalmente em letras minúsculas. O nome de classe, entretanto, geralmente começa com letra maiúscula e pode usar maiúsculas para separar as palavras do nome. Veja o exemplo a seguir: Código 3-5: Definindo um pacote para uma classe Compilando e executando: Código 3-6: Compilando um classe com pacote e realizando sua execução. A opção –d indica o deretório de destino para o byte-code Código 3-7: Sintaxe para importar pacotes package com.targettrust.java; class HelloWorld { public static void main( String[] args ) { System.out.println( "Hello World!" ); } } C:\> javac –d . HelloWorld.java C:\> java com.targettrust.java.HelloWorld Hello World! package com.targettrut.java; import java.sql.*; import java.io.*; import java.net.*; import javax.swing.JFrame; Criando classes e objetos 3-10 Criando classes e objetos 3-13 O que é a referência null? Sempre que declararmos uma referência e esta não receber valor teremos um valor null “dentro” da mesma. Desta forma é importante estudarmos um pouco este valor null, pois muito erros em tempo de execução na linguagem java ocorrem em função desta palavra. Considere o seguinte comando: Código 3-13: Atribuindo null para a referência de Produto Ele declara uma variável/referência prod e a inicializa com null. Isto indica que a variável de referência prod não se refere a nenhum objeto ainda, em outras palavras, ela somente foi delarada. null é uma palavra reservada na linguagem Java. Você pode usá-la com o operador de igualdade para verificar se uma variável de referência já recebeu uma referência válida a um objeto ou mesmo para saber se duas referências apontam para o mesmo objeto Código 3-14: Teste entre uma referência e a palavra reservada null Quando você tiver terminado de usar um objeto, você pode atribuir o valor null para a variável que o referencia. Isto indica que a variável não mais se refere ao objeto. Quando nenhuma referência houver para um objeto, o objeto será marcado como inacessível e será considerado pelo coletor de lixo (garbage collector). Iremos estudar com mais detalhes o coletor de lixo nos próximos capítulos. Na prática, somente em casos muito especiais você precisa atribuir null para uma variável. A JVM automaticamente decrementa o número de referências ativas para um objeto sempre que a variável que o referencia recebe Produto prod = null; if( prod == null ) { ... ... } ... prod == prodRef ... Criando classes e objetos 3-14 o valor null, sai de fora de escopo ou então recebe o valor de uma referência para outro objeto. Criando classes e objetos 3-15 Atribuindo referências Como mencionamos antes, quando você declara uma variável de referência para um objeto, esta variável tem o seu valor inicializado para null. Antes que você possa usar esta variável (ou seja, acessar o objeto a que ela referencia), você tem de inicializá-la. Todos os atributos de uma classe que forem de tipos compostos (Classes) serão inicializados automaticamente pela JVM no momento da criação de um objeto da classe para o valor null. Quandor declaramos uma referência para um objeto e na mesma linha já criamos este objeto, estamos inicializado a referência com um valor diferente de null, ou seja, o endereço do objeto criado.V eja código abaixo: Código 3-15: Criação do produto prod Podemos também fazer atribuição de referência, para isto basta utiliza o operador de atribuição. Neste caso as duas referências irão apontar para o mesmo objeto. Veja o código abaixo: Código 3-16: Atribuição da referência prod1 para prod2 Esta sintaxe está perfeitamente correta, mas vale frisar que há apenas um objeto Produto criado. Quando você atribui uma referência para um objeto para outra referência, você termina com duas referências para o mesmo objeto, e não uma cópia do objeto. Você pode acessar o mesmo objeto através de ambas as referências, entretanto, há apenas um único objeto. Este objeto é conhecido como objeto de referência. É importante se lembrar disto, principalmente ao passar uma referência para uma operação . Isto será visto em maiores detalhes adiante. Você pode alterar uma referência (mudando o valor da variável de referência), sem que isto afete a outra referência (o valor da outra variável de referência). Caso você precise de um outro objeto, ao invés de ter múltiplas referências para o mesmo objeto, você terá de criar este novo objeto. Produto prod = new Produto(); Produto prod1 = prod2; Criando classes e objetos 3-18 Definindo operações Quando você define uma classe é necessário definir também as operações que farão parte desta classe. As operações são definidas dentro das chaves das classes. Cada operação terá uma implementação específica que é conhecida como método. Um método, portanto, é a implementação de uma operação. Um método em Java é equivalente a uma função, procedimento ou sub- rotina em outras linguagens, com a diferença que ele deve ser definido dentro da declaração da classe. Em outras palavras, não existe em Java métodos globais (completamente desvinculados de uma classe). Todo método deve ser definido dentro de uma classe. Anteriormente quando criamos uma classe, definimos uma operação chamada “main”, agora iremos estudar a anatomia das operações bem como definir outras operações em uma classe. Anatomia de uma operação: Abaixo temos uma operação definda dentro da classe Produto. Observe os elementos que fazem parte desta operação: public class Produto { public void foo(String arg, int cod) { } } Código 3-19: Declaração da operação Os elementos integrantes de uma operação são: • Modificador de acesso: utilizados para restringirem o acesso as operações. Pode ser public, default, protected ou private. public void foo(String arg, int cod) { } Código 3-20: Visibilidade da operação Criando classes e objetos 3-19 • Tipo de retorno: pode ser um tipo primitivo (como int ou char – tipos primitivos serão estudados mais adiante), ou um tipo composto (um objeto String ou Produto, por exemplo), ou mesmo não haver retorno algum. Neste caso deverá constar void como tipo de retorno. Em resumo: toda operação em java deve indicar o tipo de retorno. public void foo(String arg, int cod) { } public String getDescricao() { } Código 3-21: Tipo de retorno das operações • Nome da operação: O nome da operação deve expressar o que a operação faz. Normalmente este nome deve ser um verbo ou estar no imperativo dando a idéia de uma ação. public String getDescricao() { } Código 3-22: Nome da operação Parâmetros: representam os valores que podemos passar para a operação. Toda operação pode receber parâmetros, sendo assim a operação pode definir logo após o seu nome um ou uma lista de parâmetros. Se o método recebe vários parâmetros, cada um deles deve ser separado dos demais por vírgula. Uma operação também pode não receber parâmetros. Havendo ou não parâmetros, os mesmos devem ser representados entre parênteses. public void foo(String arg, int cod) { } public String getDescricao() { } Código 3-23: Parâmetros da operação Criando classes e objetos 3-20 • Corpo da operação: é o local onde fica a implementação da mesma. Este código deve ficar entre chaves, que representam o início e fim do bloco. public void foo(String arg, int cod) { System.out.println( arg ); System.out.println( cod ); } Código 3-24: Corpo da operação. Impressão dos valores passados como parâmetros Criando classes e objetos 3-23 private A visibilidade private restringe o acesso a esta operação ao próprio objeto que a contém. Uma operação privada portanto não pode ser acessada por outro objeto a não ser aquela que a definiu. Operações privadas não são comuns e se existirei representam um serviço interno do próprio objeto. Veja abaixo como pode ser definida uma operação privada: public class Produto { private void foo() { … } } Código 3-28: Visibilidade provada Esta operação foo() é uma operação que pode ser chamada somente através de outras operações da própria classe, veja abaixo: public class Produto { private void foo() { … } public void salvar() { foo(); } } Código 3-29: Chamando operação com visibiliade privada Criando classes e objetos 3-24 O código abaixo não é permitido, pois veja que agora a operação foo() esta definida com sendo privada. public class CriaObjetos { public static void main(String[] args) { Produto prod = new Produto(); prod.foo(); } } Código 3-30: Chamada de operação privada fora da classe protected O uso desta visibilidade, assim como para os atributos está ligada ao uso de herança, desta forma iremos deixar este tipo de visibilidade para ser demonstrado mais adiante quando estudarmos o mecanismo de herança. Uma operação protegida é uma operação visível para objetos de classes que estão no mesmo pacote daquela classe que define a operação ou para uma classe filha desta classe que contém a operação protegida. package/defalut Uma operação com visibilidade de pacote/default é uma operação que tem comportamento de pública dento do pacote que a contém. Normalmente uma operação não é definida como package, mas sim como public ou private. Para definir uma operação com esa visibilidade não se deve especificar nenhum modificador de acesso, isto a tornará default/package. Veja abaixo na classe Produto como ficaria a operação com esta visibilidade: public class Produto { void foo() { … } } Código 3-31: Visibilidade default Criando classes e objetos 3-25 Definindo atributos Os atributos de uma classe definem a estrutura dos objetos. Estes atributos são declarados dentro do bloco que define a classe. Veja no exemplo abaixo a declaração de alguns atributos para a classe produto: public class Produto { String descricao; float preco; boolean emVenda; } Código 3-32: Atributos da classe produto Observe que na declaração acima os atributos ficam dentro do bloco de código da claase. Estes atributos são atributos com visibilidade default. Logo estudaremos os tipos de visibilidade que podem ser aplicadas aos atributos. Estes atributos especificados acima são conhecidos como atrubutos de intância e para serem acessados precisam que um objeto da classe que os contém seja criado. Um atributo pode ser inicializado com valores já no momento da sua declaração como mostrado no código abaixo. Isto fará com que quando um objeto da classe que o contém for criado o mesmo já possua um determinado valor. O atributo emVenda irá possuir o valor true, neste caso, para todos os objetos criados public class Produto { String descricao; float preco; boolean emVenda = true; } Código 3-33: Inicialização do atributo Criando classes e objetos 3-28 private A visibilidade provate é a visibilidade recomendada pela orientação a objetos para os atributos de uma classe. Você estudou estes tipos de visibilidade e a importância do uso das mesmas nos cursos anteriores, então vejamos agora como ficaria esta visibilidade aplicada aos atributos. public class Produto { private String descricao; private float preco; private boolean emVenda; } Código 3-36: Definindo atributos provados O acesso agora aos atributos não poderia mais ser feito de forma direta como na visibilidade pública. Veja o código abaixo e observe que nas linhas onde tentamos acessar os atributos teríamos um erro sendo reportado pelo compilador dizendo que o atributo é privado e não pode ser acessado desta forma. public class Consulta { public static void main(String[] args) { Produto prod = new Produto(); prod.descricao = “Notebook”; prod.preco = 3500.0f; prod.emVenda = false; } } Código 3-37: Acessando atributos privados Como então deve ser feito o acesso a atributos privados. O acesso a atributos com visibilidade privada deve ser feito através de operações públicas que serão especificadas na classe. Já vimos como definir operações, então veja agora como ficaria o acesso a estes atributos. Primeiramente teríamos que modificar a classe Produto adicionando métodos públicos para fazer este acesso. Veja abaixo: Criando classes e objetos 3-29 public class Produto { private String descricao; private float preco; private boolean emVenda; public void setDescricao(String novaDescricao) { descricao = novaDescricao; } public String getDescricao() { return descricao; } ... } Código 3-38: Definindo operações para acesso aos atributos Logo depois de modificarmos a classe Produto podemos fazer acesso a seus atributos através das operações. Veja abaixo: public class Consulta { public static void main(String[] args) { Produto prod = new Produto(); prod.setDescricao(“Notebook”); prod.setPreco(3500.0f); prod.setEmVenda(false); } } Código 3-39: Utilizando as operações para acesso aos atributos Criando classes e objetos 3-30 package/default Um atributo com visibilidade de pacote/default é um atributo que pode ser acessado diretamente como se fosse público por classes que estiverem no memo pacote. Para definir um atributo com esta visibilidade não é necessário colocar modificador antes do mesmo. Este é o modificador padrão para visibilidades quando as mesmas não forem definidas. Abaixo veja a nova versão da classe Produto: package com.targettrust.java; public class Produto { String descricao; float preco; boolean emVenda; } Código 3-40: Visibilidade default Observe que a classe acima está dentro de um pacote chamado com.targettrust.java e que a mesma será utilizada por outra classe que está no mesmo pacote. package com.targettrust.java; public class Consulta { public static void main(String[] args) { Produto prod = new Produto(); prod.descricao = “Notebook”; prod.preco = 3500.0f; prod.emVenda = false; } } Código 3-41: Acesso a visibilidade defalut Criando classes e objetos 3-33 Comentários no código fonte Os comentários de código fonte estão presentem em todas as linguagens de programação, e como java não poderia ficar de fora o mesmo possui 3 tipos de comentários. Os comentários são importantes pois são um mecanismo para o programador explicar dentro do fonte com as suas próprias palavras o que significa ou faz os elementos que o mesmo está escrevendo. Java possui um tipo de cometário que pode ser utilizado por um gerador de documentação a fim do mesmo criar um conjunto de páginas HTML com informações sobre a classe. O programador interessado em utilizar aquela clase não precise olhar o fonte da mesma para saber do que ele dispõe, mas sim basta olhar em qualquer browser esta documentação em formato HTML. Na linguagem java existem os seguintes tipos de comentários: 1 – Comentário de linha 2 – Comentário de múltiplas linhas 3 – Comentário de documentação Comentário de linha O comentário de linha é um comentário bastante prático e muito utilizado. Seve para podermos colocar em qualquer ponto do código uma documentação. No entanto esta documentação é feita somente em uma linha, não podendo haver múltiplas linhas como no anterior. Veja o exemplo abaixo: public class Produto { public float calcularPreco() { // para calcular o preço deve ser descontado o desconto preco = preco – desconto; ... } } Código 3-44: Comentário de linha Criando classes e objetos 3-34 Comentário de múltiplas linhas O comentário de múltiplas linhas pode ser utilizado em qualquer ponto do código. Este tipo de comentário não fará parte da documentação gerado pelo javadoc. O programador pode escrever mais de uma linha documentando o código. Os caracteres /* e */ representam o início e fim deste tipo de comentário. public class Produto { public void imprimir() { /* Mostra os dados do produto. Estes dados mostrados são: nome, descrição e preço */ System.out.println(“Dados do produto:”); ... } } Código 3-45: Comentário de múltiplas linhas Comentário de documentação Este tipo de cometário deve ser colocado antes do elemento que se quer documentar, ou seja antes da definição de uma classe ou operação. As marcações /** e */ indicam o início e fim de um comentário de documentação. Todo o conteúdo colocado dentro destas marcações será capturado pelo utilitário javadoc para montar a documentação da classe em formato HTML. /** Classe para representar um produto da loja. Um produto deve conter sempre um código e uma descrição Criada dia 05-05-2005 */ public class Produto { /** Método para mostrar os dados de um produto */ public void imprimir() { } } Código 3-46: Comentário de documentação para classe e operação Criando classes e objetos 3-35 Os comentários de documentação podem ter algumas marcações especiais para serem capturadas pelo javadoc e adicionadas na documentação HTML da classe. Estas marcação são as seguintes: @return Representa o tipo de retorno de uma operação. Pode conter texto para explicar o que é o tipo de retorno @param Representa o parâmetro de uma operação. Deve conter uma descrição do que significa este parâmetro. Tabela 3-1: macros para documentação Veja código de exemplo abaixo: public class Produto { /** Calcula o custo de um produto. @param arg um argumento a ser utilizado para calcular o custo @param cod código do produto a ser utilizado no calculo @return float indicando o custo do produto */ public float calcularCusto(String arg, int cod) { … } } Código 3-47: Comentário de documentação para a classe Produto