Baixe o app para aproveitar ainda mais
Prévia do material em texto
UNIVERSIDADE ESTÁCIO DE SÁ SISTEMAS DE INFORMAÇÃO PROGRAMAÇÃO ORIENTADA A OBJETOS – JAVA SWING Prof. Fernando André da Silva 1º Semestre/2013 2 INDICE INTRODUÇÃ O À LINGUAGEM JAVA .................................................................................................. 4 BREVE HISTÓRIA DO JAVA ........................................................................................ 4 VANTAGENS DA LINGUAGEM JAVA .......................................................................... 4 PROGRAMAÇÃO ORIENTADA A OBJETOS .................................................................. 8 CLASSE ..................................................................................................................... 8 CONSTRUTORES ...................................................................................................... 15 MÉTODOS ............................................................................................................... 17 O TIPO BOOLEAN .................................................................................................... 19 CONTROLE DE FLUXO – ESTRUTURAS DE SELEÇÃO E REPETIÇÃO .......................... 21 ENCAPSULAMENTO ................................................................................................. 25 SOBRECARGA DE MÉTODOS .................................................................................... 28 INTERFACES ............................................................................................................ 29 TRY-CATCH-FINALLY .............................................................................................. 33 INTERFACES GRÁFICAS USANDO JFC/SWING .............................................................................. 40 INTRODUÇÃO .......................................................................................................... 40 Componentes Swing .......................................................................................................... 41 Componentes A.W.T. ......................................................................................................... 41 Look and Feel ................................................................................................................... 41 HIERARQUIA DE CLASSE ......................................................................................... 43 java.lang.Object ................................................................................................................ 43 java.awt.Component ......................................................................................................... 44 java.awt.Container ............................................................................................................ 46 javax.swing.JCompontent ................................................................................................. 47 1 DESENVOLVENDO APLICAÇÃO JAVA COM SWING ................................................................. 49 1.1 JOPTIONPANE ................................................................................................... 49 1.1.1 showInputDialog ...................................................................................................... 51 1.1.2 showMessageDialog ................................................................................................ 52 1.1.3 showConfirmDialog ................................................................................................. 52 1.1.4 showOptionDialog ................................................................................................... 54 1.1.5 Exercícios ................................................................................................................. 57 1.2 JFRAME ............................................................................................................. 59 1.3 JPAINEL ............................................................................................................ 61 1.3.1 Gerenciador de Layout ............................................................................................ 61 1.3.1.1 FlowLayout .................................................................................................... 62 1.3.1.2 BorderLayout ................................................................................................. 65 1.3.1.3 GridLayout ..................................................................................................... 67 1.3.1.4 BoxLayout ..................................................................................................... 69 1.4 JLABEL ............................................................................................................. 70 1.5 JTEXTFIELD ...................................................................................................... 72 1.5.1 setBounds ................................................................................................................. 74 1.5.2 Exercicios ................................................................................................................. 76 1.6 JBUTTON........................................................................................................... 78 1.6.1 Exercícios ................................................................................................................. 80 1.7 JCOMBOBOX ..................................................................................................... 84 1.7.1 Exercícios ................................................................................................................. 85 1.8 JRADIOBUTTON ................................................................................................ 87 1.8.1 Exercícios ................................................................................................................. 88 1.9 JCHEKBOX........................................................................................................ 90 1.9.1 Exercícios ................................................................................................................. 93 1.10 JTABBEDPANE ................................................................................................ 94 1.11 JTEXTAREA .................................................................................................... 99 1.12 JPASSWORDFIELD ......................................................................................... 102 3 1.13 VARIAÇÃO DE COMPONENTES VISUAIS......................................................... 105 1.14 JLIST ............................................................................................................. 117 1.15 JTABLE ......................................................................................................... 119 1.17 JPROGRESSBAR ............................................................................................ 121 1.18 JTEXTAREA .................................................................................................. 123 2 – TRATAMENTO DE EVENTOS ....................................................................................................... 124 2.1 ACTIONLISTENER ........................................................................................... 124 2.2 MOUSELISTENER ............................................................................................ 129 2.3 KEYLISTENER ................................................................................................. 135 2.4 EXERCICIOS COM EVENTOS .............................................................................141 3 - MENUS ................................................................................................................................................. 150 3.1 JMENUBAR ..................................................................................................... 150 3.2 JMENU ............................................................................................................ 150 3.3 JMENUITEM .................................................................................................... 150 3.4 JSEPARATOR ................................................................................................... 150 3.5 EXERCÍCIOS .................................................................................................... 152 4 - JINTERNALFRAME .......................................................................................................................... 163 5 - THREADS ............................................................................................................................................ 168 5.1 A CLASSE THREAD ......................................................................................... 168 5.2 CRIAÇÃO DE THREADS .................................................................................... 169 5.3 MANIPULAÇÃO DE THREADS .......................................................................... 172 5.4 A INTERFACE RUNNABLE................................................................................ 175 5.5 SYNCHRONIZED (USO CONCORRENTE DE RECURSOS) ...................................... 183 5.6 THREAD/SWING .............................................................................................. 190 5.7 EXERCÍCIOS COM THREADS ............................................................................ 193 6 - EXEMPLOS DO LIVRO .................................................................................................................... 195 4 INTRODUÇÃ O À LINGUAGEM JAVA Breve História do Java A Sun criou um time (conhecido como Green Team) para desenvolver inovações tecnológicas em 1992. Esse time foi liderado por James Gosling, considerado o pai do Java. O time voltou com a idéia de criar um interpretador (já era uma máquina virtual, veremos o que é isso mais a frente) para pequenos dispositivos, facilitando a reescrita de software para aparelhos eletrônicos, como vídeo cassete, televisão e aparelhos de TV a cabo. A idéia não deu certo. Tentaram fechar diversos contratos com grandes fabricantes de eletrônicos, como Panasonic e outras, mas não houve êxito devido ao conflito de interesses. Hoje, sabemos que o Java domina o mercado de aplicações para célulares com mais de 2.5 bilhões de dispositivos compatíveis, porém em 1994 ainda era muito cedo para isso. Com o advento da web, a Sun percebeu que poderia utilizar a idéia criada em 1992 para rodar pequenas aplicações dentro do browser. A semelhança era que na internet havia uma grande quantidade de sistemas operacionais e browsers, e com isso seria grande vantagem poder programar numa única linguagem, independente da plataforma. Foi aí que o Java 1.0 foi lançado: focado em transformar o browser de apenas um cliente fino (thin client ou terminal burro) para uma aplicação que possa também realizar operações, não apenas renderizar html. Atualmente os applets realmente não são o foco da Sun. É curioso notar que a tecnologia Java nasceu com um objetivo em mente, foi lançado com outro, mas, no final, decolou mesmo no desenvolvimento de aplicações do lado do servidor. Sorte? Você pode ler a história da linguagem Java em: http://java.sun.com/java2/whatis/1996/ storyofjava.html Em 2009 a Oracle comprou a Sun, fortalecendo a marca. A Oracle sempre foi, junto com a IBM, uma das empresas que mais investiram e fizeram negócios com tecnologias Java. No Brasil, diversos grupos de usuários se juntaram para tentar disseminar o conhecimento da linguagem. Um deles é o GUJ (http://www.guj.com.br), uma comunidade virtual com artigos, tutoriais e fórum para tirar dúvidas, o maior em língua portuguesa. Encorajamos todos os alunos a usar muito os fóruns do mesmo, pois é uma das melhores maneiras para achar soluções para pequenos problemas que acontecem com grande freqüência. Vantagens da Linguagem Java Quando a linguagem Java foi criada, a equipe de desenvolvimento tinha como principal objetivo fazer do Java uma linguagem melhor do que as ja existentes no mercado. Baseando-se nas linguagens C/C++, a equipe de Gosling pensou em algo robusto, portável, seguro, com código limpo e fácil de programar. 5 Quando falamos em facilidade para programar, estamos falando em simplificar certas coisas que "atrapalham" o dia a dia do programador, fazendo-o de modo seguro, ou seja, simplificar não significa deixar de usar e sim facilitar algo de modo seguro e concreto. As vezes quando falamos em facilidades, algumas pessoas enxergam desvantagens. A equipe de James Gosling viu vantagens na linguagem que haviam criado. Alguns programadores hoje acham essas vantagens negativas para eles, mas na verdade, nem sempre é. Algumas vantagens que a linguagem Java possui Independência de Plataforma Essa talvez seja o grande trunfo da linguagem Java. Ser independente de plataforma significa muito nos dias atuais. quando falamos em uma linguagem multiplataforma, queremos dizer que Java não depende de nenhum Sistema Operacional para rodar, ou seja, tanto faz em qual SO você irá rodar o seu bytecode (arquivo .class). quando a Sun criou a JVM (Java Virtual Machine), ela especificou que, para diversos SO's haveriam máquinas virtuais diferentes, ou seja, para tornar a linguagem multiplataforma, a Sun desenvolveu não só JVM's para sistemas Operacionais diferentes, como J2SDK's diferentes também, ou seja, para diferentes SO's (Windows, Linux, Solaris, etc) há a JVM e o JSDK. Se você desenvolve um programa em windows, por exemplo, compila ele no windows, pode-se muito bem rodar ele na JVM de um Linux. este exemplo caracteriza a multiplataforma do java. Java não usa explicitamente ponteiros Nem todos acham essa uma vantagem, mas só quem trabalhou com linguagens que tem ponteiros que manipulam endereço de memória diretamente sabem o trabalho que dá. Pensando nisso, os desenvolvedores da linguagem java, eliminaram a manipulação direta de ponteiros. O que ocorre é o apontamento para um endereço de memória, ou seja, quando você cria um objeto, você está apontando em qual endereço de memória esse objeto ficará alocado. Não implementa herança múltipla Não é exatamente uma vantagem mas facilita o trabalho do programador. A única forma de fazer herança multipla, de forma indireta, é quando uma classe herda uma outra classe e implementa interface (classe que contém apenas declaração dos métodos). Possui "Coleta de Lixo" automática. Isso significa que ela desaloca automaticamente qualquer espaço de memória não utilizado sem que o programador se preocupe com isso. Robustez Os recursos da linguagem e do ambiente para o tempo de execução garantem que o código não derrube o sistema de alguém que "tropece" em uma home page contendo uma animação. Orientação a Objetos Java é uma linguagem totalmente orientada a objetos, o que permite a herança e a reutilização de códigos de forma dinâmica e estática. 6 Alto Desempenho A linguagem Java suporta vários recursos de alto desempenho, como multithreading, compilação just-in-time e utilização de código nativo. O byte-code doJava possui um desempenho aproximadamente 20 vezes inferior que o de um código nativo do processador (ou linguagem de máquina), mas que em comparação com linguagens Script, como o HTML, o JavaScript ou o VBScript, ou até mesmo o próprio byte-code do VB (Visual Basic), possui uma performance muitas vezes superior. Esta performance, pela quantidade de esforços aplicados sobre a sua otimização pelos desenvolvedores de Java, está cada vez mais sendo aumentada, podendo um dia comparar-se com uma linguagem compilada para o processador em específico (linguagem nativa). Inclusive já foram criados processadores para suportar diretamente o byte-code da linguagem Java. Facilidade A linguagem é derivada da linguagem C e C++, sendo assim familiar. Além disso, o ambiente retira do programador a responsabilidade de gerenciar a memória e os ponteiros. Além dessas vantagens, a linguagem Java está agora incorporando suporte a operações em Banco de Dados. O JDBC, que é uma biblioteca de classes para acesso a banco de dados, permite uma conexão remota a servidores SQL que possuam driver OBDC ou compatível. Transações no estilo de Compras, Vendas, Cadastramentos, Alteração de dados pessoais controlada por senha via Internet, são exemplos do que o JDBC permite que seja realizado. Desvantagens da Linguagem Apesar disso, a linguagem também possui as seguintes desvantagens: Performance reduzida: por ser uma linguagem não projetada para gerar código nativo para cada arquitetura, os programas em Java costumam ter um desempenho menor que os escritos em linguagens como C++. Eles também costumam ocupar mais espaço em memória. Mas à medida que a linguagem vem sendo refinada, tal desvantagem vem diminuindo cada vez mais. Programas em Java geralmente demoram mais tempo para compilar. Programas que realizam cálculo com números em ponto flutuante tendem a possuir baixo desempenho. A Linguagem Java É uma linguagem de progração que permite o desenvolvimento de aplicações para uma série de plataformas. É possível ter software Java desde de dispositivos pequenos, como telefones célulares, até computadores de grande porte, como os mainframes, por exemplo. Devido a essa característica, a linguagem Java conta com três conhecidos ambientes de desenvolvimento: JSE ou J2SE (Java Standard Edition); JEE ou J2EE (Java Enterprise Edition); JME ou J2ME (Java Micro Edition). 7 JSE O JSE (Java Standard Edition) é o ambiente de desenvolvimento mais utilizado. Isso porque seu uso é voltado a PCs e servidores, onde há bem mais necessidade de aplicações. Além disso, pode-se dizer que essa é a plataforma principal, já que, de uma forma ou de outra, o JEE e o JME tem sua base aqui. Pode-se dizer também que esses ambientes de desenvolvimento são versões aprimoradas do JSE para as aplicações a que se propõem. Por ser a plataforma mais abrangente do Java, o JSE é a mais indicada para quem quer aprender a linguagem. JEE O JEE (Java Enterprise Edition) é a plataforma Java voltada para redes, internet, intranets e afins. Assim, ela contém bibliotecas especialmente desenvolvidas para o acesso a servidores, a sistemas de e-mail, a banco de dados, etc. Por essas características, o JEE foi desenvolvido para suportar uma grande quantidade de usuários simultâneos. JME O JME (Java Micro Edition) é o ambiente de desenvolvimento para dispositivos móveis ou portáteis, como telefones célulares e palmtops. Como a linguagem Java já era conhecida e a adaptação ao JME não é complicada, logo surgiram diversos tipos de aplicativos para tais dispositivos, como jogos e agendas eletrônicas. As empresas saíram ganhando com isso porque, desde que seus dispositivos tenham uma JVM (Java Virtual Machine - Máquina Virtual Java), é possível, com poucas modificações, implementar os aplicativos em qualquer aparelho, sendo o único limite a capacidade do hardware. A plataforma JME contém configurações e bibliotecas trabalhadas especialmente para a atuação em dispositivos portáteis. Assim, o desenvolvedor tem maior facilidade para lidar com as limitações de processamento e memória, por exemplo. Um exemplo disso é a configuração chamada CLDC (Connected Limited Device Configuration), destinada a dispositivos com recursos de hardware bastante limitados, como processadores de 16 bits e memórias com 512 KB de capacidade. Essa configuração contém uma JVM e um conjunto básico de bibliotecas que permite o funcionamento da aplicação Java em dispositivos com tais características. A imagem a seguir mostra um jogo em Java que roda em dois dispositivos móveis diferentes (tirada do site http://www.msmobile.com/): 8 Finalizando A tecnologia Java é bastante abrangente e permite o desenvolvimento de soluções para uma infinidade de aplicações. São tantos recursos, que até mesmo desenvolvedores experientes podem se confundir em um determinado momento. Felizmente, a comunidade Java é organizada e não é difícil encontrar auxílio em sites ou fóruns especializados. Caso queira mais informações sobre Java, visite o site oficial: java.sun.com. Programação Orientada a Objetos A programação orientada a objeto não é somente uma nova forma de programar é uma nova forma de pensar um problema, de forma abstrata, utilizando conceitos do mundo real e não conceitos computacionais. Os conceitos de objetos devem acompanhar todo o ciclo de desenvolvimento de um software. A programação orientada a objeto também inclui uma nova notação e exige por parte do analista/programador o conhecimento desta notação (diagramas). Conceitos fundamentais em POO Classe Objeto Atributos Métodos Sobrecarga Herança Encapsulamento Polimorfismo Classe Para a Programação Orientada a Objetos (POO), uma classe é um conjunto de códigos de programação, que incluem a definição dos atributos e dos métodos necessários para a criação de um ou mais objetos. A classe contém toda a descrição da forma do objeto, é um molde para criação de objetos, é uma matriz geradora de objetos, é uma fábrica de objetos. Uma classe é a unidade de encapsulamento dos atributos e dos métodos. Dentro da classe é que declaramos os atributos, os métodos e seus controles de acesso. Vamos ver o protótipo para declarar e definir uma classe. 9 Definição de classes em Java A forma geral da declaração de uma classe é a seguinte: [modificadores] class [nome classe] extends [nome super] public class Funcionario extends Pessoa{ String nome; int idade; float altura; Funcionario(){} // Construtor de classe public static void digita(){} // Metodo para a digitacao public static void imprime(){} // Metodo para imprimir da tela } Modificadores Os modificadores de uma classe determinam como uma classe será manipulada mais tarde no decorrer do desenvolvimento do programa. Public; Private; Protected; Static; Abstract; Final. public A instrução public indica que a classe, método ou variável assim declarada possa ser acessada em qualquer lugar e a qualquer momento da execução do programa. Private O modificador de acesso "private" quando aplicado a um atributo ou a um método indica que os mesmos só podem ser acessados de dentro da classe que os criou (encapsulamento). Uma classe que herde de uma superclasse com atributos declarados como "private" só poderáter acesso a eles através dos métodos públicos da própria superclasse, caso contrário, não haverá acesso a estes atributos. O modificador de acesso private deixa o atributo visível apenas para a classe em que o mesmo se encontra. Protected Deixa o atributo visível para todas as outras classes e subclasses que pertencem ao mesmo pacote. Neste caso apenas as classes do mesmo pacote tem acesso ao membro, enquanto nem mesmo pacotes de suas subclasses tem acesso. Static Quando usar o modificador static ? 10 Não pensem que a palavra-chave static define que uma variável não possa mudar de valor. O uso da palavra-chave static é confundido por muitos programadores, até por alguns mais experientes. Quando uma variável ou método é declarado static, estes são carregados na memória pela JVM. Para acessar um método static você só pode fazê-lo de duas maneiras, ou acessa de dentro de outro método static ou cria uma instância (sem ser static) e a partir daí pode fazer o que quiser e de dentro de um método não static você pode acessar tanto um método static como um não static de forma direta. No java, quando uma classe é usada (seja por instância ou diretamente nos membros estáticos), suas váriaveis e seus métodos estáticos ganham um lugar na mémoria RAM do computador enquanto o programa é executado. Mas, este lugar (ou endereço) é usado pela classe, ou seja, todas as instâncias dessa classe, quando utilizam esta variável, estão na verdade utilizando a variável da classe, e não do objeto. Assim, todas as instâncias dessa classe terão o mesmo valor para aquela variável estática. Vejamos isso no código! Exemplo public class TestaStatic { public static int minhaVariavelStatic; public static void main(String args[]){ TestaStatic.minhaVariavelStatic = 3; TestaStatic a = new TestaStatic(); TestaStatic b = new TestaStatic(); TestaStatic c = new TestaStatic(); System.out.println("Valor minha variavel: " + minhaVariavelStatic); a.minhaVariavelStatic = 5; System.out.println("Valor objeto a: " + a.minhaVariavelStatic); System.out.println("Valor objeto b: " + b.minhaVariavelStatic); System.out.println("Valor objeto c: " + c.minhaVariavelStatic); } } Quando executarmos, vemos a saída: Valor minha variavel: 3 Valor objeto a: 5 Valor objeto b: 5 Valor objeto c: 5 CONSTRUÍDO COM SUCESSO (tempo total: 2 segundos) Podemos acessar minhaVariavelStatic diretamente pela classe, sem precisar instanciar um novo objeto para seu uso. Neste momento a JVM carrega todos os métodos e variáveis estáticos, da classe TestaStatic na memória. Isto acontece agora, porque é a primeira utilização da classe pelo programa. (A JVM só utiliza memória, quando realmente é necessário.) Instânciamos três objetos a partir da classe TestaStatic. 11 imprimimos o valor da variável a partir do objeto a mudamos o valor da variável para 5 a partir do objeto a imprimimos o valor da variável a partir do objeto b e c. A saída foi 3 e depois 5 depois 5 Como pode isto a partir de objetos diferentes? Atribuimos o valor 3 para a variável minhaVariavelStatic diretamente na classe TestaStatic, e quando imprimos pelo objeto a a invés da saída ser 0(zero), foi 3. E quando mudamos o valor da variável estática a partir do objeto a para 5, podemos perceber que essa mudança esta presente também no objeto b e c, porque quando imprimos a saída foi 5, 5 e 5. Isto acontece porque variáveis estáticas possuem somente um único valor para todas as instâncias de sua classe. A variável estática pertence a Classe e não a instância(ou objeto). Ao contrário de membros não- estáticos que só podem ser acessados a partir de uma instância. Pois seus valores são individuais para cada objeto. Vantagem no uso desse modificador static Alguns programadores não tem essa percepção mas é muito útil quando se necessita compartilhar uma informação entre todos os objetos de determinada classe, como alguma contagem ou totalização, até mesmo o ponteiro de uma conexão com um banco de dados. Outra utilidade para static é pode utilizar as coisas de forma direta sem precisar criar instâncias. Uma classe ou método static não tem o seu conteúdo “zerado” toda vez que é criada uma nova instância. Por isto que o método executável do java, o método main, é estático: public static void main(String args[]){} A JVM não poderia saber por onde começar a execução do programa sem um método que possa ser acessado diretamente, sem precisar de uma instância. Já pensou se a JVM tivesse que instanciar a classe até achar o método main, iria ficar muito lento, além do uso da memória. E se eu tiver dois métodos public e static? A JVM entende que o método main (escrito e minusculas) é o método de inicialização do programa, assim você pode ter outros métodos estáticos em suas classes, sem nenhum problema. Isto é padrão da JVM. Existem também os blocos de código static que são executados assim que a classe que o contenha é usada, antes mesmo do método main, se a classe o tiver. package Programas; public class Inicio { static { System.out.println("Executou o bloco estático!"); } public static void main(String[] args) { System.out.println("Executou o método main"); } } A execução dessa classe gerará a saída: Executou o bloco estático! Executou o método main 12 Para que servem esses blocos de código static? Os blocos de códigos estáticos são como um construtor de uma classe, servem quando se precisa inicializar, tratar ou pesquisar os valores de variaveis estáticas, as únicas que podem ser acessadas neste instante, antes mesmo do método main ou o método construtor possa ser executado. É praticamente um método construtor sem nome, sem argumentos (parâmetros) e nenhum tipo de retorno. Ele é sem nome porque não há necessidade de se referir a ele. Serve somente para trabalhar com os membros estáticos da classe antes de seu construtor ou do método main (caso seja a classe executável). package Programas; public class Inicio { public static String data; static { data = "10/08/2008"; } public static void main(String[] args) { System.out.println("A data que escrevi este artigo era " + data); } } Deste modo, usando os blocos de código estáticos, podemos tratar as variáveis estáticas antes de qualquer coisa. Abstract Classes abstratas são aquelas que contém ao menos um método incompleto. Desse modo uma classe abstrata não pode ser instanciada, mas pode ser derivada. Neste caso, a subclasse deve prover o corpo do método para que possa ser instanciada. Isto é muito útil quando desejamos definir em uma classe regras gerais para o comportamento de uma parte do programa, para que, mais tarde, as regras mais específicas sejam introduzidas por subclasses. Final Uma classe final pode ser instanciada, mas não pode ser derivada, isto é, não pode ser superclasse de nenhuma subclasse. Algumas classes predefinidas no ambiente Java têm esta propriedade. A palavra reservada final impede que o método seja sobreposto em uma subclasse isso é, ele pode ser herdado porém não pode ser sobrescrito. O que podemos dizer é que quando criamos um método uma classe ou até mesmo variáveis do tipo final não podemos sobrescrevê-las. O método serve para que quando uma subclasse a chame da mesma maneira que foi criada, sem que haja mudanças em seu comportamento.Já quando isso acontece com uma classe ela não pode ser herdada, isso quer dizer que eu não posso usá-la como uma subclasse, ele já é a classe final e está no seu auge do perfeccionismo. Já uma variável ela não pode mudar seu valor quando recebe seu valor inicial, por exemplo, final int a = 5; até o final do programa ou da execução do seu bloco a variável a sempre será 5, é importante saber que seu valor não muda. Friendly Se nenhum modificador de classe for especificado, então a classe será considerada friendly. 13 Apenas os objetos integrantes do mesmo package podem utilizar uma classe friendly. Convenção para nomes de objetos Identificadores são seqüências de caracteres Unicode, que devem obedecer às seguintes regras: Embora não seja obrigatório, o conhecimento e uso da seguinte convenção padrão para atribuir nomes em Java pode facilitar bastante a manutenção de um programa: Nomes de classes são iniciados por letras maiúsculas. Nomes de métodos, atributos e variáveis são iniciados por letras minúsculas. Em nomes compostos, cada palavra do nome é iniciada por letra maiúscula -- as palavras não são separadas por nenhum símbolo. Um nome pode ser composto por letras, por dígitos e pelos símbolos _ e $. Um nome não pode ser iniciado por um dígito (0 a 9). Letras maiúsculas são diferenciadas de letras minúsculas. Uma palavra-chave da linguagem Java não pode ser um identificador. Tipo de objeto Formato do nome Variáveis nomeVariavel Constantes NOME_CONSTANTE Nome de classes NomeClasse Nome de métodos/funções nomeMetodo() Atributos nomeAtributo Atributos estáticos nomeAtributo Nome de classes derivadas Deve lembrar a classe base Regras para a escolha de nomes de variáveis e constantes em Java Cada linguagem de programação tem seu conjunto próprio de regras e convenções para os tipos de nomes que você pode usar, e Java não é diferente. As regras e convenções para nomear variáveis em Java são as seguintes: Nomes de variáveis são sensitivos a minúsculas e maiúsculas. Isso quer dizer que "cliente" é diferente de "Cliente". O nome de uma variável pode ser qualquer identificador legal: Uma sequência sem limites de tamanho de letras Unicode e dígitos, começando com uma letra, "$" ou o caractere de sublinhado "_" (underscore). A convenção, contudo, é sempre começar um nome de variável com uma letra e não "$" ou "_". Além disso, por convenção, o caractere $ nunca é usado. Você pode encontrar situações em que nomes gerados automaticamente podem conter o sinal $, mas evite usá-lo sempre que possível. O mesmo acontece com "_". Embora permitido, evite começar nomes de variáveis com "_". Espaços não são permitidos em nomes de variáveis. Caracteres subsequentes podem ser letras, dígitos, $ ou "_". Convenções (e senso comum) se aplicam a esta regra também. Quando escolher nomes para suas variáveis, use nomes completos em vez de abreviações confusas. Isso tornará seu código mais legível. Nomes tais como "cliente", "nota", "quantidade", etc, são bem mais fáceis de entender e lembrar que "cl", "n", "qt", etc. Tenha também em mente que palavras-chaves e palavras reservadas da linguagem não podem ser usadas como nomes de variáveis. 14 Se o nome de variável que você escolher consistir de apenas um palavra, escreva-a toda em letras minúsculas. Ex.: cliente. Se consistir de mais de uma palavra, escreva a primeira letra da segunda palavra usando letra maiúscula. Ex.: nomeCliente. Se o nome for de uma constante, ele deve ser escrito todo em letras maiúsculas. Ex.: MODELO = 102. Se o nome da constante possuir mais de uma palavra, separe-as com o caractere "_". Ex.: NIVEL_BOLETO = 2. Lembre-se: as letras maiúsculas e as minúsculas são consideradas diferentes. Detalhes sobre as convenções de codificação sugeridas pelos projetistas da linguagem Java podem ser encontrados no documento Code Conventions for the Java TM Programming Language. Super Classes Um dos aspectos mais importantes da OOP é a capacidade de usar campos e métodos de uma classe previamente construída. Por meio da extensão de classes simples podemos construir classes maiores, acrescentando àquelas mais campos e métodos, obtendo com isto mais funcionalidades. Neste processo, há uma grande economia no esforço de codificação. Sem esse recurso, freqüentemente seria necessário recodificar grande parte dos programas para acrescentar-lhes funcionalidade ou fazer modificações significativas. Ao derivar uma classe, estamos primeiramente fazendo uma cópia da classe parente. É exatamente isto que obtemos se deixarmos vazio o corpo da subclasse. Tal classe se comportaria exatamente como sua superclasse. Entretanto, podemos acrescentar novos campos e métodos à subclasse, além de sobrepor métodos existentes na superclasse, declarando-os exatamente como na superclasse, exceto por dar um corpo diferente. As classes são definidas através do uso da palavra-chave class. Para definir uma classe, utiliza- se a construção: [modif] class NomeDaClasse { // corpo da classe... } A primeira linha é um comando que inicia a declaração da classe. Após a palavra-chave class, segue-se o nome da classe, que deve ser um identificador válido para a linguagem. O modificador modif é opcional; se presente, pode ser uma combinação de public e abstract ou final. 15 Definindo a Classe A definição da classe propriamente dita está entre as chaves { e }, que delimitam blocos na linguagem Java. Este corpo da classe usualmente obedece à seguinte seqüência de definição: 1. As variáveis de classe, iniciando pelas public, seguidos pelas protected, pelas com visibilidade padrão (sem modificador) e finalmente pelas private. 2. Os atributos (ou variáveis de instância) dos objetos dessa classe, seguindo a mesma ordenação definida para as variáveis de classe. 3. Os construtores de objetos dessa classe. 4. Os métodos da classe, geralmente agrupados por funcionalidade. Toda classe pode também ter um método main associado, que será utilizado pelo interpretador Java para dar início à execução de uma aplicação. Java também oferece outra estrutura, denominada interface, com sintaxe similar à de classes mas contendo apenas a especificação da funcionalidade que uma classe deve conter, sem determinar como essa funcionalidade deve ser implementada. Propriedades de uma classe (meta-informação) podem ser obtidas através das funcionalidades oferecidas na classe java.lang.Class. Variáveis da classe Cada objeto definido a partir de uma classe terá sua cópia separada dos atributos definidos para a classe. No entanto, há situações em que é interessante que todos os objetos compartilhem a mesma variável, similarmente ao que ocorre com variáveis globais em linguagens de programação tradicional. O mecanismo para realizar esse compartilhamento é a definição de variáveis da classe. Uma variável de classe tem sua declaração precedida pela palavra-chave static. Várias constantes são definidas em Java como public static final. Por exemplo, a classe Math de Java define as constantes E (2.71828...) e PI (3.14159...). Para ter acesso a esses valores, basta precedê-los com o nome da classe e um ponto, como em double pi2 = Math.PI/2; Outro exemplo de variável public static final é a variável out da classe System. Essa variável, System.out, está associada a um objeto que representa a saídapadrão (o monitor, tipicamente), sendo utilizada sempre que se deseja enviar um valor para essa saída. Construtores Um construtor é um (pseudo-)método especial, definido para cada classe. O corpo desse método determina as atividades associadas à inicialização de cada objeto criado. Assim, o construtor é apenas invocado no momento da criação do objeto através do operador new. A assinatura de um construtor diferencia-se das assinaturas dos outros métodos por não ter nenhum tipo de retorno (nem mesmo void). Além disto, o nome do construtor deve ser o próprio nome da classe. O construtor pode receber argumentos, como qualquer método. Usando o mecanismo de sobrecarga, mais de um construtor pode ser definido para uma classe. 16 Toda classe tem pelo menos um construtor sempre definido. Se nenhum construtor for explicitamente definido pelo programador da classe, um construtor default, que não recebe argumentos, é criado pelo compilador Java. No entanto, se o programador da classe criar pelo menos um método construtor, o construtor default não será criado automaticamente -- se ele o desejar, deverá criar um construtor sem argumentos explicitamente. No momento em que um construtor é invocado, a seguinte seqüência de ações é executada para a criação de um objeto: 1. O espaço para o objeto é alocado e seu conteúdo é inicializado (bitwise) com zeros. 2. O construtor da classe base é invocado. 3. Os membros da classe são inicializados para o objeto, seguindo a ordem em que foram declarados na classe. 4. O restante do corpo do construtor é executado. Seguir essa seqüência é uma necessidade de forma a garantir que, quando o corpo de um construtor esteja sendo executado, o objeto já terá à disposição as funcionalidades mínimas necessárias, quais sejam aquelas definidas por seus ancestrais. O primeiro passo garante que nenhum campo do objeto terá um valor arbitrário, que possa tornar erros de não inicialização difíceis de detectar. Classes em UML Em UML (Unified Modeling Language), a representação para uma classe no diagrama de classes é expressa graficamente como: Os atributos são membros da classe que descrevem suas propriedades. Para cada atributo especifica-se o nome, tipo (primitivo ou outra classe), uma especificação de visibilidade e, opcionalmente, um valor inicial. A especificação de visibilidade pode ser, se definida, privativa (-, nenhuma visibilidade externa), pública (+, visibilidade externa total) ou protegido (#, visibilidade externa limitada a objetos de classes derivadas). Os métodos são membros da classe que descrevem suas funcionalidades, ou seja, o que pode ser feito com um objeto da classe. Para cada método, especifica-se o nome, o tipo de retorno (void se não houver nenhum), a lista de argumentos (o tipo e opcionalmente um identificador para cada parâmetro) e visibilidade (como para atributos, define o quão acessível é um método a partir de objetos de outros classes). 17 Atributos A todo objeto podemos relacionar alguns atributos (propriedades). No exemplo de um relógio a hora, a data. Na programação orientada a objeto, os atributos são definidos na classe e armazenados de forma individual ou coletiva pelos objetos. Podemos relacionar alguns atributos (propriedades) a todo objeto. No exemplo do relógio, a hora e a data. Na programação orientada a objeto, os atributos são definidos na classe e armazenados de forma individual ou coletiva pelos objetos. A definição de atributos de uma classe Java reflete de forma quase direta a informação que estaria contida na representação da classe em um diagrama UML. Para tanto, a sintaxe utilizada para definir um atributo de um objeto é: [modificador] tipo nome [ = default]; onde o modificador (opcional) é uma combinação de o public, protected ou private; o final; e o static. o tipo deve ser um dos tipos primitivos da linguagem Java ou o nome de uma classe ou interface; nome deve ser um identificador válido; default (opcional) é a especificação de um valor inicial para a variável. Métodos A todo objeto podemos relacionar determinados comportamentos, ações e reações. As ações ou comportamento dos objetos são chamados na análise orientada a objeto de métodos (AOO), assim, um método é uma função, um serviço fornecido pelo objeto. Os comportamentos dos objetos são definidos na classe através dos métodos e servem para manipular e alterar os atributos do objeto (alteram o estado do objeto). Em Java, a definição de um método em uma classe é expressa dentro do corpo da classe como um bloco na forma: [modificador] tipo nome(argumentos) { corpo do método} onde o nome (um identificador válido) e o tipo dos argumentos constituem a assinatura do método. O tipo é um indicador do tipo de retorno do método, que pode ser um dos tipos primitivos da linguagem, um tipo de objeto (nome de classe ou interface), ou void se não houver nenhum valor de retorno. O modificador (opcional) é uma combinação de um especificador de visbilidade (public, protected ou private), de um especificador de redefinição (abstract ou final) e de um especificador de escopo (static). Métodos são essencialmente procedimentos que podem manipular atributos de objetos para os quais o método foi definido. Além dos atributos de objetos, métodos podem definir e manipular variáveis locais; também podem receber parâmetros por valor através da lista de argumentos. 18 Uma boa prática de programação é manter a funcionalidade de um método simples, desempenhando uma única tarefa. O nome do método deve refletir de modo adequado a tarefa realizada. Se a funcionalidade do método for simples, será fácil encontrar um nome adequado para o método. Como ocorre para a definição de atributos, a definição de métodos reflete de forma quase direta a informação que estaria presente em um diagrama de classes UML, a não ser por uma diferença vital: o corpo do método. Métodos de mesmo nome podem co-existir em uma mesma classe desde que a lista de argumentos seja distinta, usando o mecanismo de sobrecarga. Mensagens Um objeto tem determinados atributos (propriedades) e métodos (ações), e que o objeto reage ao meio que o envolve de acordo com as excitações que sofre. Em um programa orientado a objeto as excitações são representadas por mensagens que são enviadas a um objeto. Uma mensagem pode ser gerada pelo usuário, por exemplo, ao clicar o mouse. Objeto (ou Instância) A Análise Orientada a Objeto (AOO) tem uma série de conceitos que auxiliam as pessoas a delinear claramente o problema e a identificar os objetos e seus relacionamentos. Objetos são coisas do mundo real ou imaginário, que podemos de alguma forma identificar, como uma pedra, uma caneta, um copo, uma fada. Um objeto tem determinadas propriedades que o caracterizam, e que são armazenadas no próprio objeto. As propriedades de um objeto são chamadas ainda de atributos. O objeto interage com o meio e em função de excitações que sofre, realiza determinadas ações que alteram o seu estado (seus atributos). Os atributos de um objeto não são estáticos, eles sofrem alterações com o tempo. Para a POO, um objeto é uma entidade única que reúne atributos e métodos, ou seja, reúne as propriedades do objeto e as reações às excitações que sofre. Uma variável do tipo classe é chamada de objeto. A instânciade uma classe é chamada de objeto. Tipos Básicos Observe a tabela a seguir, sobre os tipos de dados. Esses tipos são conhecidos como Tipos de Dados Primitivos. Como podemos observar a linguagem Java oferece diversos tipos de dados com os quais podemos trabalhar. Há basicamente duas categorias em que se encaixam os tipos de dados: tipos primitivos e tipos de referências. Os tipos primitivos correspondem a dados mais simples ou escalares, enquanto os tipos de referências consistem em arrays, classes e interfaces. Estes serão vistos nos módulos subseqüentes. 19 Vamos a uma descrição curta sobre cada um dos tipos: Tipo Descrição boolean Pode ser contido em 1 bit, porém o seu tamanho não é precisamente definido. Assume os valores true ou false. char Caractere em notação Unicode de 16 bits. Serve para armazenar dados alfanuméricos. Também pode ser usado como um dado inteiro com valores na faixa entre 0 e 65535. byte Inteiro de 8 bits em notação de complemento de dois. Pode assumir valores entre -27=-128 e 27-1=127. short Inteiro de 16 bits em notação de complemento de dois. Os valores possíveis cobrem a faixa de -2-15=-32.768 a 215-1=32.767 int Inteiro de 32 bits em notação de complemento de dois. Pode assumir valores entre 231=2.147.483.648 e 231-1=2.147.483.647. long Inteiro de 64 bits em notação de complemento de dois. Pode assumir valores entre -263 e 263-1. float Representa números em notação de ponto flutuante normalizada em precisão simples de 32 bits em conformidade com a norma IEEE 754-1985. O menor valor positivo representável por esse tipo é 1.40239846e-46 e o maior é 3.40282347e+38. 4 bytes de tamanho e 23 dígitos binários deprecisão. double Representa números em notação de ponto flutuante normalizada em precisão dupla de 64 bits em conformidade com a norma IEEE 754-1985. O menor valor positivo representável é 4.94065645841246544e-324 e o maior é 1.7976931348623157e+308. 8 bytes de tamanho e 52 dígitos binários de precisão. O Tipo boolean O tipo de dados boolean representa dois valores lógicos representados pelos literais true ou false. Valores boolean são produzidos pelos operadores relacionais (<, <=, > e >=), condicionais (&& e ||), lógicos (& e |) e de igualdade (== e !=) e são usados para gerenciar o fluxo de controle durante a execução do programa. Veja um trecho de código exemplificando o uso deste tipo de dados: package Exemplos; public class Exemplo1Boolean { public static void main(String args[]){ boolean continuar = true; if(continuar == true){ System.out.println("Podemos continuar."); } 20 else{ System.out.println("Vamos parar."); } System.exit(0); } } Operador NOT ( ! ) Desta vez, temos o nosso operador NOT antes da variável do usuário. O operador NOT é um ponto de exclamação única (!). É o teste para a negação, o que significa que ele está testando para o oposto do que o valor realmente é. package Exemplos; public class Exemplo2Boolean { public static void main (String args []) { boolean b; b = false; System.out.println ("Conteudo de b é: " + b); b = true; System.out.println ("Conteudo de b é: " + b); if (b) System.out.println ("Executa se b verdadeiro"); b = false; if (!b) System.out.println ("Executa se b nao for verdadeiro"); } } run: Conteudo de b é: false Conteudo de b é: true Executa se b verdadeiro Executa se b nao for verdadeiro package Exemplos; public class Exemplo3Boolean { public static void main(String args[]){ boolean continuar = true; if(!continuar == true){ System.out.println("Podemos continuar."); } else{ System.out.println("Vamos parar."); } System.exit(0); } } 21 Controle de Fluxo – Estruturas de Seleção e Repetição Comando de Seleção em Java Introdução Um comando de seleção define uma condição em um programa, que permite que grupos de comandos sejam executados de maneira condicional, de acordo com o resultado da avaliação de um determinado teste (verdadeiro ou falso). Ou seja, programas utilizam comandos de seleção para escolher entre cursos alternativos de ações. A sintaxe do comando de seleção em Java é: A sintaxe do if no Java é a seguinte: if (condicaoBooleana) { codigo; } Uma condição booleana é qualquer expressão que retorne true ou false. Para isso, você pode usar os operadores <, >, <=, >= e outros. Um exemplo: int idade = 15; if (idade < 18) { System.out.println("Não pode entrar"); } Além disso, você pode usar a cláusula else para indicar o comportamento que deve ser executado no caso da expressão booleana ser falsa: int idade = 15; if (idade < 18) { System.out.println("Não pode entrar"); } else { System.out.println("Pode entrar"); } Você pode concatenar expressões booleanas através dos operadores lógicos “E” e “OU”. O “E” é representado pelo && e o “OU” é representado pelo ||. Um exemplo seria verificar se ele tem menos de 18 anos e se ele não é amigo do dono: int idade = 15; boolean amigoDoDono = true; if (idade < 18 && amigoDoDono == false) { System.out.println("Não pode entrar"); } else { System.out.println("Pode entrar"); } Esse código poderia ficar ainda mais legível, utilizando-se o operador de negação, o !. Esse operador transforma o resultado de uma expressão booleana de false para true e vice versa. 22 int idade = 15; boolean amigoDoDono = true; if (idade < 18 && !amigoDoDono) { System.out.println("Não pode entrar"); } else { System.out.println("Pode entrar"); } Repare na linha 3 que o trecho amigoDoDono == false virou !amigoDoDono. Eles têm o mesmo valor. Para comparar se uma variável tem o mesmo valor que outra variável ou valor, utilizamos o operador ==. Repare que utilizar o operador = dentro de um if vai retornar um erro de compilação, já que o operador = é o de atribuição. int mes = 1; if (mes == 1) { System.out.println("Você deveria estar de férias"); } Estruturas de Repetição While O while é um comando usado para fazer um laço (loop), isto é, repetir um trecho de código algumas vezes. A idéia é que esse trecho de código seja repetido enquanto uma determinada condição permanecer verdadeira. int idade = 15; while (idade < 18) { System.out.println(idade); idade = idade + 1; } O trecho dentro do bloco do while será executado até o momento em que a condição idade < 18 passe a ser falsa. E isso ocorrerá exatamente no momento em que idade == 18, o que não o fará imprimir 18. int i = 0; while (i < 10) { System.out.println(i); i = i + 1; } Já o while acima imprime de 0 a 9. 23 Do while O comando do while é uma estrutura de repetição, tal como o próprio while. A principal diferença entre os dois é que do while irá fazer a comparação apenas no final do bloco de código, sendo representado da seguinte forma: do{ código } while (comparação); Neste caso, devemos ter as mesmas precauções quanto while, no que diz respeito a looping infinito. Mas nãoé necessário inicializar a variável antes do bloco de código como acontece com while, pois a comparação só será feita após todo o código ter sido executado. For Outro comando de loop extremamente utilizado é o for. A idéia é a mesma do while: fazer um trecho de código ser repetido enquanto uma condição continuar verdadeira. Mas além disso, o for isola também um espaço para inicialização de variáveis e o modificador dessas variáveis. Isso faz com que fiquem mais legíveis, as variáveis que são relacionadas ao loop: for (inicializacao; condicao; incremento) { codigo; } Um exemplo é o a seguir: for (int i = 0; i < 10; i = i + 1) { System.out.println("olá!"); } Repare que esse for poderia ser trocado por: int i = 0; while (i < 10) { System.out.println("olá!"); i = i + 1; } Porém, o código do for indica claramente que a variável i serve, em especial, para controlar a quantidade de laços executados. Quando usar o for? Quando usar o while? Depende do gosto e da ocasião. Pós incremento ++ i = i + 1 pode realmente ser substituído por i++ quando isolado, porém, em alguns casos, temos essa instrução envolvida em, por exemplo, uma atribuição: int i = 5; int x = i++; Qual é o valor de x? O de i, após essa linha, é 6. O operador ++, quando vem após a variável, retorna o valor antigo, e incrementa (pós incremento), fazendo x valer 5. 24 Se você tivesse usado o ++ antes da variável (pré incremento), o resultado seria 6: int i = 5; int x = ++i; // aqui x valera 6 Entrada de Dados (Scanner) A leitura de dados de entrada em aplicativos através da janela de comando do sistema operacional era surpreendentemente complexa até a versão 1.4.2 do J2SE. Isto não era problema para aplicativos com recursos GUI - Graphical User Interface (Interface Gráfica com o Usuário), mas tornava-se desconfortável para estudantes interessados em escrever programas simples com o propósito de aprender Java. J2SE 5.0 introduz a classe java.util.Scanner para a entrada de dados, inclusive através da entrada padrão, System.in. O exemplo a seguir apresenta uma aplicação Java para a entrada de dois números pelo teclado e a saída da soma na janela de comando do sistema operacional. É necessário criar uma instância da classe Scanner, passando como argumento o objeto padrão de entrada, System.in, que irá capturar as entradas de dados via o teclado. O método nextInt(), da instância da classe Scanner, lê o valor digitado e o armazena em uma variável do tipo int. package programas; import java.util.Scanner; public class Teste { public static void main(String[] args) { String nome; int num1; float num2; double num3; Scanner entrada = new Scanner(System.in); System.out.print("Entre com um nome .........: "); nome = entrada.nextLine(); System.out.print("Entre com um inteiro número: "); num1 = entrada.nextInt(); System.out.print("Entre com o primeiro valor : "); num2 = entrada.nextFloat(); System.out.print("Entre com o segundo valor : "); num3 = entrada.nextDouble(); System.out.printf("Nome digitado .: " + nome); System.out.printf("\nNumero digitado: " + num1); System.out.printf("\nValor digitado : " + num2); System.out.printf("\nValor digitado : " + num3); System.out.printf("\n"); } } 25 A classe Scanner possui diversos métodos que podem ser utilizados para realizar este serviço. Os principais métodos que podemos utilizar, neste caso, são: Método Finalidade next() Aguarda uma entrada em formato String nextInt() Aguarda uma entrada em formato Inteiro nextByte() Aguarda uma entrada em formato Inteiro nextLong() Aguarda uma entrada em formato Inteiro Longo nextFloat() Aguarda uma entrada em formato Número Fracionário nextDouble() Aguarda uma entrada em formato Número Fracionário Tabela 1: Métodos da Classe Scanner para obter dados Encapsulamento Poderiamos dizer que encapsular significa, na orientação à objetos, separar um programa em partes isolando-as o máximo possível, protegendo o acesso direto aos atributos de uma classe com o objetivo de deixar o programa mais flexível e facilitar o trabalho no código. Para isso se faz necessário o uso de modificadores de acesso mais restritivos nos atributos da classe. Esses atributos são manipulados indiretamente com o uso de métodos específicos. O padrão usado para a manipulação desses atributos são os métodos set (que define o valor do atributo) e get (que retorna o valor do atributo). Encapsulamento vem de encapsular, que em programação orientada a objetos significa separar o programa em partes, o mais isoladas possível. A idéia é tornar o software mais flexível, fácil de modificar e de criar novas implementações. Para exemplificar, podemos pensar em uma dona de casa (usuário) utilizando um liquidificador (sistema). O usuário não necessita conhecer detalhes do funcionamento interno do sistema para poder utilizá-lo, precisa apenas conhecer a interface, no caso, os botões que controlam o liquidificador. Outro exemplo clássico de encapsulamento é o padrão de projeto chamado Mediator. Uma grande vantagem do encapsulamento é que toda parte encapsulada pode ser modificada sem que os usuários da classe em questão sejam afetados. No exemplo do liquidificador, um técnico poderia substituir o motor do equipamento por um outro totalmente diferente, sem que a dona de casa seja afetada - afinal, ela continuará somente tendo que pressionar o botão. O encapsulamento protege o acesso direto (referência) aos atributos de uma instância fora da classe onde estes foram declarados. Esta proteção consiste em se usar modificadores de acesso mais restritivos sobre os atributos definidos na classe. Depois devem ser criados métodos para manipular de forma indireta os atributos da classe. Encapsular atributos também auxilia a garantir que o estado e o comportamento de um objeto se mantenha coeso. Por exemplo, no caso da classe Semaforo poderiamos ter um método de acesso chamado lerCor(), e um modificador chamado proximaCor(). O estado é mantido pois os usuários da classe não podem alterar as cores de um semáforo ao seu bel prazer e, por exemplo, fazer a seguinte troca de cores: vermelho-amarelo-vermelho. É comum usar o padrão get<nomeDoAtributo> para o método que retorna o valor atual do atributo e 26 set<nomeDoAtributo> para o método que modifica o valor de um atributo do objeto, como no exemplo abaixo: setComProtecao e getComProtecao. Exemplo sem encapsulamento class NaoEncapsulado { int semProtecao; // implicitamente public } public class TesteNaoEncapsulado { public static void main(String[] args) { NaoEncapsulado ne = new NaoEncapsulado(); ne.semProtecao = 10; // acesso direto ao atributo System.out.println("Valor sem proteção: " + ne.semProtecao); } } Com encapsulamento class Encapsulado { private int comProtecao; public void setComProtecao(int valor) { comProtecao = valor; } public int getComProtecao() { return comProtecao; } } public class TesteEncapsulado { public static void main(String[] args) { Encapsulado e = new Encapsulado(); e.setComProtecao(10); System.out.println("Valor com proteção: " + e.getComProtecao()); } } Vejamos como ficaria a classe pessoa com encapsulamento. Pessoa.javapublic class Pessoa{ private String nome; private String sobrenome; private String dataNasc; private String rg; private String[] telefones; public Pessoa(){ } public String getNome(){ return nome; } public void setNome(String n){ 27 nome = n; } public String getSobrenome(){ return sobrenome; } public void setSobrenome(String s){ sobrenome = s; } public String getDataNasc(){ return dataNasc; } public void setDataNasc(String d){ dataNasc = d; } public String getRg(){ return rg; } public void setRg(String r){ r = rg; } public String getTelefones(){ return telefones; } public void setTelefones(String[] telefones){ telefones[] = telefones; } } Métodos Get e Set Como visto anteriormente, o encapsulamento "protege" os atributos ou métodos dentro de uma classe, portanto devemos prover meios para acessar tais membros quando eles são particulares, ou seja, quando possuem o modificador private. O que torna isso possível é a criação de métodos. Em programação orientada a objetos, esses métodos são chamados de métodos acessores ou getters e setters, pois eles provêm acesso aos atributos da classe, e geralmente, se iniciam com get ou set, daí a origem de seu nome. Na verdade, não há nada de diferente entre os métodos comuns e os métodos acessores. A única importância está no fato da orientação a objeto. Pois, sempre que formos acessar um membro em Java usaremos get ou set. Set Nomeamos um método acessor com set toda vez que este método for modificar algum campo ou atributo de uma classe, ou seja, se não criarmos um método acessor set para algum atributo, isso quer dizer que este atributo não deve ser modificado. Portanto, como o valor de um atributo da classe será modificado, não é necessário que este método retorne nenhum valor, por isso, os métodos setters são void. Porém, obrigatoriamente, eles tem que receber um argumento que será o novo valor do campo. 28 Get Nomeamos um método acessor com get toda vez que este método for verificar algum campo ou atributo de uma classe. Como este método irá verificar um valor, ele sempre terá um retorno como String, int, float, etc. Mas não terá nenhum argumento. Sobrecarga de Métodos Neste capítulo vamos apresentar a sobrecarga de métodos, o uso de métodos com o mesmo nome, mas parâmetros diferentes. O que é a sobrecarga de métodos? Sobrecarga de métodos se refere ao uso de métodos com mesmo nome, mas com tipos de parâmetros ou número de parâmetros diferentes. Isto é, o nome do método é o mesmo, mas os tipos de parâmetros são diferentes. De um modo geral como os métodos sobrecarregados têm o mesmo nome, eles realizam basicamente a mesma tarefa, a diferença é o número de parâmetros e ou o tipo dos parâmetros que são recebidos. Exemplos de sobrecarga O exemplo a seguir declara métodos com o mesmo nome, métodos sobrecarregados. Exemplo: public void metodoA(int x, int y); // 1-int,int public void metodoA(float x, float y); // 2-float,float public void metodoA(int x, float y); // 3-int,float O compilador reconhece qual método você quer acessar verificando o tipo dos parâmetros e o número de parâmetros. Mudar o nome dos parâmetros não é uma sobrecarga, o compilador diferencia o tipo e a quantidade de parâmetros não o nome e sim pela sua assinatura. Exemplo de Sobrecarga package programas; import entity.Numeros; public class ExemploSobreCarga { public static void main(String[] args) { Numeros exemplo = new Numeros(); System.out.print("===== Exemplo de Sobrecarga de Metodo ====="); System.out.print("\n"); System.out.print("Primeiro Metodo: 2 parametro "); exemplo.imprime(1,2); System.out.print("\nSegundo Metodo : 3 parametro "); exemplo.imprime(1,2,3); System.out.print("\nTerceiro Metodo: 4 parametro "); exemplo.imprime(1,2,3,4); } } 29 package entity; public class Numeros { public int num1; public int num2; public int num3; public int num4; public Numeros() {} public void imprime(int a, int b){ num1 = a; num2 = b; System.out.print (num1 + " " + num2 ); } public void imprime(int x, int f, int s){ num1 = x; num2 = f; num3 = s; System.out.print (num1 + " " + num2 + " " + num3 ); } public void imprime(int m, int n, int o, int p){ num1 = m; num2 = n; num3 = o; num4 = p; System.out.print (num1 + " " + num2 + " " + num3 + " " + num4 ); } } Interfaces Interface é um recurso da orientação a objeto utilizado em Java que define ações que devem ser obrigatoriamente executadas, mas que cada classe pode executar de forma diferente. Interfaces contém valores constantes ou assinaturas de métodos que devem ser implementados dentro de uma classe. E por que isso? Isso se deve ao fato que muitos objetos (classes) podem possuir a mesma ação (método), porém, podem executá-la de maneira diferente. Usando um exemplo bem drástico, podemos ter uma interface chamada aéreo que possui a assinatura do método voar(). Ou seja, toda classe que implementar aéreo deve dizer como voar(). Portanto, se eu tenho uma classe chamada pássaro e outra chamada avião, ambas implementando a interface aéreo, então, nestas duas classes devemos codificar a forma como cada um irá voar(). Uma interface é criada da mesma forma que uma classe, mas utilizando a palavra- chave interface no lugar declass. interface nomeDaInterface { métodoAbstrato (argumentos); } 30 Usando uma Interface em uma Classe Como vimos anteriormente, uma classe pode extender suas funcionalidades obtendo as características de outra classe num processo que chamamos de herança. Uma interface não é herdada, mas sim, implementada. Porque todo o código dos métodos da interface deve ser escrito dentro da classe que o chama. Dessa forma, obtemos as assinaturas dos métodos da interface em uma classe usando a palavra-chave implements. A vantagem principal das interfaces é que não há limites de quantas interfaces uma classe pode implementar. O que ajuda no caso de heranças múltiplas que não é possível ser feito em Java, pois uma classe apenas pode herdar as características de uma outra classe. Resumindo Uma interface em Java é uma espécie de classe, com as seguintes propriedades: Não pode ser instanciável (não podemos criar objetos com new); Só pode possuir assinaturas de métodos de instância, públicos e abstratos (sem corpo). Não pode possuir métodos concretos (com corpo), nem métodos estáticos. Os prefixos abstract e public podem ser usados, mas são em geral omitidos; Não pode conter variáveis de instância ou de classe (static); Pode conter declarações de constantes (com prefixo final e inicializadas para um valor) – nesse caso essa variável funcionará como uma constante de classe. O prefixo static possa ser usado, mas é em geral omitido; Pode ser criada como subinterface de outra interface já existente, usando extends, como as classes. Para criar interfaces usamos uma sintaxe parecida com a das classes, substituindo a palavraclass por interface, por exemplo: Exemplo1: package Exemplos; import entity.InterfaceQualquer; import javax.swing.JOptionPane; public class ExemploInterface implements InterfaceQualquer{ public void calculaArea(double medida) { JOptionPane.showMessageDialog(null,"Area de um Quadrado: " + medida * medida); } public void calculaPerimetro(double medida) { JOptionPane.showMessageDialog(null,"Perímetro de um Quadrado: " + medida * 4); } public static void main(String[] args) { ExemploInterface ex = new ExemploInterface(); double medida; medida = (Double.parseDouble(JOptionPane.showInputDialog(null, "Cálculo com figura geométrica" + "\nDigite a medida: "))); ex.calculaArea(medida); ex.calculaPerimetro(medida); } } 31 Exemplo2: package entity; public interface InterfaceQualquer { public final double PI = 3.1416; public void calculaArea(double n1); public void calculaPerimetro(double n2); } public interface InterfaceExemplo{ public final String PALAVRA = "UFRJ"; public void metodo1(int x); public String metodo2 (String s); } public interface InterfaceExemplo2 extends InterfaceExemplo { public void metodo3(); } Nos exemplos acima, são criadas duas interfaces. A segunda é uma subinterface da primeira, ou uma extensão dela. A interface InterfaceExemplo2 contém todos os três métodos, e mais a constante PALAVRA. Ou seja, ela "herda" as definições da sua superinterface Exemplo (bem como de todas as superinterfaces acima na hierarquia que existirem). Ao contrário das classes, não existe uma interface "raiz" de todas as interfaces, como ocorre com a classe Object. A interface InterfaceExemplo, vista acima, não herda de nenhuma outra. Note que a mesma convenção para nome de classe se aplica aos nomes das interfaces: iniciar com letra maiúscula, seguida de letras minúsculas. A constante PALAVRA do exemplo acima segue a convenção de nome de constantes em Java, que é ter todas as letras maiúsculas. O arquivo fonte de uma interface, da mesma forma que no caso de classes, também tem o nome da interface com a terminação .java. E o compilador gera da mesma forma um arquivo .class de mesmo nome. Usando interfaces Uma Interface funciona de forma análoga a uma classe abstrata. Ou seja, ela não pode ser instanciada, mas pode ser como que "herdada" por uma classe. A forma sintática para uma classe herdar de uma interface utiliza a palavra chave implements, como no exemplo fictício abaixo: 32 public class ClasseTeste implements InterfaceExemplo { public void metodo1(int x) { System.out.println(x); } public String metodo2(String s) { return s + " da " + PALAVRA; } // outros métodos e atributos desta classe } O sentido de uma classe "herdar" de uma interface é similar ao de herdar métodos abstratos de uma superclasse abstrata. A classe fica obrigada a implementar concretamente todos os métodos declarados na interface, e nas suas super-interfaces, ou a classe não compilará. Note que a classe pode usar diretamente a constante definida na interface. Classes podem implementar mais de uma interface Uma diferença essencial entre classes e interfaces é que uma classe pode implementar diversas interfaces, embora possa ser subclasse de apenas uma superclasse. Nesse caso, após a palavra chave implements, escrevemos a lista das interfaces que a classe implementa, separadas por vírgulas. Por exemplo, sejam as interfaces InterfaceExemplo1, InterfaceExemplo2, InterfaceY e uma classe ExemploInterface que implementa as duas últimas interfaces: package entity; public interface InterfaceExemplo1{ public final String PALAVRA= "UFRJ"; public void metodo1(); } package entity; public interface InterfaceExemplo2 extends InterfaceExemplo1 { public void metodo2(); } package entity; public interface InterfaceY { public void f1(); public void f2(); } package entity; import javax.swing.JOptionPane; public class ExemploInterface implements InterfaceExemplo2, InterfaceY { public void metodoDaClasse(){ //Método da classe JOptionPane.showMessageDialog(null, "Executou o método da classe"); } public void metodo1(){ //Método da interface1 33 JOptionPane.showMessageDialog(null, "Executou o método da Interface1"); } public void metodo2(){ //Método da interface2 JOptionPane.showMessageDialog(null, "Executou o método da Interface2"); } public void f1(){ //Método1 da InterfaceY JOptionPane.showMessageDialog(null, "Executou o método1 da InterfaceY"); } public void f2(){ //Método2 da InterfaceY JOptionPane.showMessageDialog(null, "Executou o método2 da InterfaceY"); } } package programas; import entity.ExemploInterface; public class MainInterface { public static void main(String[] args) { ExemploInterface exemplo = new ExemploInterface(); exemplo.metodoDaClasse(); exemplo.metodo2(); exemplo.f1(); exemplo.f2(); } } try-catch-finally Tratamento de Exceções e Erros Umas das utilidades proporcionadas pela orientação a objetos de Java é a facilidade em tratar possíveis erros de execução chamados de exceções. Sempre que um método de alguma classe é passível de causar algum erro, então, podemos usar o método de tentativa - o try. Tudo que estiver dentro do bloco try será executado até que alguma exceção seja lançada, ou seja, até que algo dê errado. Quando uma exceção é lançada, ela sempre deve ser capturada. O trabalho de captura da exceção é executado pelo bloco catch. Um bloco try pode possuir vários blocos de catch, dependendo do número de exceções que podem ser lançadas por uma classe ou método. O bloco catch obtém o erro criando uma instância da exceção. Portanto, a sintaxe do bloco try catch é: try { // código a ser executado } catch (ClasseDeExceção instânciaDaExceção) { // tratamento da exceção } 34 Exceções As exceções são, na verdade, instâncias de classes. E como qualquer classe ou objeto, podemos facilmente manipular. Existem métodos comuns entre todas as classes de Exceções, dentre as quais podemos citar: toString() O Java usa o método toString() toda vez que for necessário converter um objeto em String, ou seja, para obter ume representação textual do objeto. Por exemplo para imprimir um objeto qualquer usando System.out.println ou para mostrar os itens de um JComboBox. Esse método toString() é definido na classe Object, portanto é herdado por todos os objetos. Todos os objetos são capazes de gerar uma representação textual. Mas o método do Object não conhece as classes derivadas, não sabe como o objeto deve ser representado. Por isso usa um padrão: o nome da classe seguido por um '@' e pelo hashCode em hexadecimal da instância em questão. No Java cada classe deve fornecer um hashCode(), método que recebe os dados armazenados em uma instância da classe em um único valor hash 1 . Retorna uma “representação em texto” do objeto. Converte os dados da exceção em String para visualização. printStackTrace()
Compartilhar