Ex1 Jonas Freitas [email protected] Ex1 1) Assinale V ou F para cada uma das afirmativas: ( ) Objetos do mundo real tem duas características em comum: estado e cidade ( ) Classe é o estereótipo de um objeto ( ) Atributo = Comportamento ( ) Comportamento = Ação ( ) Mensagem é a forma como os objetos se comunicam ( ) Encapsulamento é o mecanismo utilizado para disponibilizar métodos que operam sobre os dados e que protegem o acesso direto indevido aos atributos de uma instância fora da classe onde estes foram declarados Ex1 2) Assinale V ou F para cada uma das afirmativas: ( ) O modificador “private” na frente de um método, significa que o método só é visível para a própria classe ( ) O modificador “protected” significa que o método é visível para qualquer classe ( ) O modificador “private” na frente de um atributo, significa que o atributo é visível somente para os métodos que contém o modificador public. ( ) O modificador “protected” na frente de um atributo, significa que o atributo é visível somente para os métodos que contém o modificador protected. ( ) O ponto de ínicio da execução de um programa acontece no método main ( ) A palavra reservada void na frente de um método, significa que o método não retorna nenhum valor Ex1 3) Implemente um programa Java que calcule a área de um triangulo retângulo (possui um ângulo de 90 graus) e de um retângulo. Área do triângulo Area = base * altura / 2 Área do retângulo Área = base * altura Ex1 Genéricos Jonas Freitas [email protected] Genéricos public class Pessoa { private String nome; public String getNome() { return nome; } public void setNome(String nome) { this.nome = nome; } } Genéricos public class TesteColecaoSemGenericos { public static void main(String[] args) { Pessoa p1 = new Pessoa(); p1.setNome("Marco"); Pessoa p2 = new Pessoa(); p2.setNome("Diego"); Pessoa p3 = new Pessoa(); p3.setNome("Marcelo"); Pessoa p4 = new Pessoa(); p4.setNome("Wilson"); Pessoa p5 = new Pessoa(); p5.setNome("Paulo"); Collection lista = new ArrayList(); lista.add(p1); lista.add(p2); lista.add(p3); lista.add(p4); lista.add(p5); Iterator ite = lista.iterator(); while (ite.hasNext()) { Pessoa pessoa = (Pessoa) ite.next(); } } } Genéricos • Apesar de nossa coleção ter apenas um tipo de classe, para recuperarmos os objetos precisamos fazer um cast. • Funciona perfeitamente, mas ainda pode ser melhorado. Genéricos public class TesteColecaoSemGenericos { public static void main(String[] args) { Pessoa p1 = new Pessoa(); p1.setNome("Marco"); Pessoa p2 = new Pessoa(); p2.setNome("Diego"); Pessoa p3 = new Pessoa(); p3.setNome("Marcelo"); Pessoa p4 = new Pessoa(); p4.setNome("Wilson"); Pessoa p5 = new Pessoa(); p5.setNome("Paulo"); Collection lista = new ArrayList(); lista.add(p1); lista.add(p2); lista.add(p3); lista.add(p4); lista.add(p5); Iterator ite = lista.iterator(); while (ite.hasNext()) { Pessoa pessoa = (Pessoa) ite.next(); } } } public class TesteColecaoValoresAleatorios { public static void main(String[] args) { Collection lista = new ArrayList(); lista.add("Valor String"); lista.add(new Pessoa()); lista.add(10); lista.add(new Double(100.9)); Iterator ite = lista.iterator(); while (ite.hasNext()) { Pessoa pessoa = (Pessoa) ite.next(); } } } Genéricos • Um dos recursos mais comentados da versão 5. • Restringe os tipos de dados aceitos por referência. • Permite a verificação do tipo em tempo de compilação. Genéricos • Antigamente as coleções permitiam que adicionássemos qualquer tipo de objeto entre seus elementos. • Obviamente um programador mais descuidado poderia adicionar um objeto de tipo errado entre os elementos dessa coleção. Genéricos • No nosso exemplo temos uma coleção com quatro tipos diferentes de classe. • Durante a recuperação desses objetos provavelmente ocorreria algum tipo de erro. • A questão essencial é que esse problema só seria detectado em tempo de execução. • Mas aí já será tarde! Genéricos • Com essa sintaxe, não precisamos mais fazer cast. – Collection<Pessoa> lista = new ArrayList<Pessoa>(); • Uma consequência direta da aplicação de genéricos na nossa coleção é que restringimos a adição de objetos somente do tipo Pessoa. Genéricos package com.javabasico.genericos; import java.util.*; public class TesteColecaoComGenericos { public static void main(String[] args) { Pessoa p1 = new Pessoa(); p1.setNome("Marco"); Pessoa p2 = new Pessoa(); p2.setNome("Diego"); 1. Collection<Pessoa> lista = new ArrayList<Pessoa>(); lista.add(p1); lista.add(p2); 2. Iterator<Pessoa> ite = lista.iterator(); 3. while (ite.hasNext()) { 4. Pessoa pessoa = ite.next(); } } } Genéricos package com.javabasico.genericos; import java.util.*; public class TesteColecaoComGenericos { public static void main(String[] args) { Pessoa p1 = new Pessoa(); p1.setNome("Marco"); Pessoa p2 = new Pessoa(); p2.setNome("Diego"); 1. Collection<Pessoa> lista = new ArrayList<Pessoa>(); lista.add(p1); lista.add(p2); lista.add(new Double(100.9)); 2. Iterator<Pessoa> ite = lista.iterator(); 3. while (ite.hasNext()) { 4. Pessoa pessoa = ite.next(); } } } Genéricos • Então que dizer que a metodologia antiga de preenchimento de listas foi excluído? • Por que? Genéricos • Então que dizer que a metodologia antiga de preenchimento de listas foi excluído? • Não. • Por que? • Para manter a compatibilidade com os códigos antigos. Genéricos • Raw types • Quando um tipo genérico (como uma coleção) é usado sem o parâmetro, chamamos de raw types. • A utilização de raw types não é recomendada, mas é essencial para manter compatibilidade com código legado. • Em função disso aparece ao lado da coleção um warning indicando que você não está utilizando o parâmetro de tipo. • Para evitar esse warning, utilize a sintaxe logo abaixo. @SuppressWarnings("unchecked") public class TesteColecaoSemGenericos { {código da classe} } Genéricos • Exercico1 public class TesteColecaoSemGenericos { public static void main(String[] args) { Pessoa p1 = new Pessoa(); p1.setNome("Marco"); Pessoa p2 = new Pessoa(); p2.setNome("Diego"); Pessoa p3 = new Pessoa(); p3.setNome("Marcelo"); Pessoa p4 = new Pessoa(); p4.setNome("Wilson"); Pessoa p5 = new Pessoa(); p5.setNome("Paulo"); Collection lista = new ArrayList(); lista.add(p1); lista.add(p2); lista.add(p3); lista.add(p4); lista.add(p5); Iterator ite = lista.iterator(); while (ite.hasNext()) { Pessoa pessoa = (Pessoa) ite.next(); } } } Genéricos • Tipos parametrizados • Vamos dar uma olhada em um exemplo de classe que utiliza Object, ou seja, não utiliza tipos parametrizados. Genéricos package com.javabasico.genericos; public class CaixaDeObjeto { private Object objeto; public void adiciona(Object objetoAdicionado) { objeto = objetoAdicionado; } public Object recuperaObjeto() { return objeto; } } Genéricos • Conversão obrigatória • Sem a utilização de genéricos precisamos sempre fazer conversões. – Integer valorRecuperado = (Integer) caixa.recuperaObjeto(); • Não existe validação nenhuma em tempo de compilação já que a conversão é forçada. Genéricos public class TesteCaixaDeObjeto { public static void main(String[] args) { CaixaDeObjeto caixa = new CaixaDeObjeto(); caixa.adiciona(new Integer(10)); Integer valorRecuperado = (Integer) caixa.recuperaObjeto(); System.out.println("Valor integer: " + valorRecuperado); } } Genéricos • Erro de conversão • Nada impede o programador de converter para um tipo errado. • Infelizmente esse problema só será descoberto em tempo de execução. Genéricos package com.javabasico.genericos; public class TesteCaixaDeObjeto { public static void main(String[] args) { CaixaDeObjeto caixa = new CaixaDeObjeto(); caixa.adiciona(new Integer(10)); String valorRecuperado = (String) caixa.recuperaObjeto(); System.out.println("Valor integer: " + valorRecuperado); } } Genéricos • A exceção lançada quando a conversão não pode ser feita é essa a seguir. Exception in thread "main" java.lang.ClassCastException: java.lang.Integer cannot be cast to java.lang.String at com.javabasico.genericos.TesteCaixaDeObjeto.main(TesteCaixaDeObjeto.java:7) Genéricos • Tipos parametrizados • Vamos atualizar nossa caixa de objetos com um tipo parametrizado. • Esse tipo (T) será informado quando criarmos um objeto do tipo CaixaDeObjeto, como uma variável. • A mesma técnica pode ser aplicada a interfaces ou métodos. Genéricos package com.javabasico.genericos; 1. public class CaixaDeObjeto<T> { 2. private T objeto; 3. public void adiciona(T objetoAdicionado) { objeto = objetoAdicionado; } 4. public T recuperaObjeto() { return objeto; } } Genéricos 1. Declaração do tipo parametrizado. 2. A variável objeto agora é do tipo parametrizado. Esse tipo será indicado mais adiante. 3. O método adiciona só permite que você utilize o tipo T. 4. Recupera o objeto convertido para o tipo T Genéricos • Quando criamos um objeto do tipo CaixaDeObjeto devemos informar o tipo, conforme a sintaxe. • A partir desse momento, não será mais necessário fazer cast. Genéricos package com.javabasico.genericos; public class TesteCaixaDeObjeto { public static void main(String[] args) { 1. CaixaDeObjeto<Integer> caixa = new CaixaDeObjeto<Integer>(); caixa.adiciona(new Integer(10)); System.out.println("Valor integer: " + caixa.recuperaObjeto()); } } Genéricos 1. Agora parametrizamos a caixa de objetos. Essa caixa de objetos só aceitará objetos do tipo Integer. • Qualquer outro tipo de dado será considerado como erro pelo compilador. Genéricos package com.javabasico.genericos; public class TesteCaixaDeObjeto { public static void main(String[] args) { CaixaDeObjeto<Integer> caixa = new CaixaDeObjeto<Integer>(); caixa.adiciona(new Integer(10)); System.out.println("Valor integer: " + caixa.recuperaObjeto()); CaixaDeObjeto<Pessoa> caixaPessoa = new CaixaDeObjeto<Pessoa>(); Pessoa pessoa = new Pessoa(); pessoa.setNome("Marco"); caixaPessoa.adiciona(pessoa); System.out.println("Nome: " + caixaPessoa.recuperaObjeto().getNome()); } } Genéricos • Com o próximo exemplo você pode ver que métodos também aceitam tipos parametrizados. Genéricos package com.javabasico.genericos; public class CaixaDeObjeto<T> { private T objeto; public void adiciona(T objetoAdicionado) { objeto = objetoAdicionado; } public T recuperaObjeto() { return objeto; } public <U> void verifica(U u) { System.out.println("T: " + objeto.getClass().getName()); System.out.println("U: " + u.getClass().getName()); } } Genéricos package com.javabasico.genericos; public class TesteCaixaDeObjetoInspecao { public static void main(String[] args) { CaixaDeObjeto<Integer> caixa = new CaixaDeObjeto<Integer>(); caixa.adiciona(new Integer(10)); caixa.verifica(new Pessoa()); caixa.verifica(new String("Alguma frase")); } } Genéricos • Exercicio 2. package com.javabasico.genericos; public class CaixaDeObjeto { private Object objeto; public void adiciona(Object objetoAdicionado) { objeto = objetoAdicionado; } public class TesteCaixaDeObjeto { public static void main(String[] args) { public Object recuperaObjeto() { CaixaDeObjeto caixa = new CaixaDeObjeto(); return objeto; } caixa.adiciona(new Integer(10)); } Integer valorRecuperado = (Integer) caixa.recuperaObjeto(); System.out.println("Valor integer: " + valorRecuperado); } } Multithreading Jonas Freitas [email protected] Multithreading – EX: – Carregamento de uma aplicação desktop que busca dados em um servidor. Multithreading – EX: – Carregamento de uma aplicação desktop que busca dados em um servidor. Multithreading • Lista de tarefas a serem realizadas no carregamento do programa. • • • • • Carregamento de imagens Carregamento de configurações iniciais Sincronização de contatos (bloqueante) Carregamento do idioma Carregamento dos textos utilizados pela aplicação. Multithreading • 5 minutos para ordenar as atividades. Multithreading • Ordem correta. 1. 2. 3. 4. 5. Sincronização de contatos (bloqueante) Carregamento do idioma Carregamento de imagens Carregamento de configurações iniciais Carregamento dos textos utilizados pela aplicação. Multithreading • Thread = linha de execução • Multiplas linhas: ampliam a idéia de multitarefa • Programas individuais parecem realizar várias tarefas ao mesmo tempo Multithreading Portabilidade Diferenças entre Solaris e Win32 (Windows95, NT, etc.) • No Solaris Uma thread executa até completar ou até uma thread de prioridade mais alta ficar pronta Ocorre preempção (o processador é dado para a thread de prioridade mais alta) • No Win32 Threads são “timesliced” É dada uma fatia de tempo para a Thread executar O processador então troca para quaisquer threads de igual prioridade Multithreading • Dois modos de criar uma nova thread em Java: Declarar uma classe como sendo sub-classe de Thread Esta sub-classe deve sobrescrever o método run da classe Thread Declarar uma classe implementando a interface Runnable essa classe então implementa o método run Multithreading • Usando herança, nossa classe deve sobrescrever o método public void run(): class Tarefa1 extends Thread { public void run() { for(int i=0; i<1000; i++) System.out.println(“Usando herança”); } } Multithreading • A interface Runnable nos obriga a implementar o método public void run(): class Tarefa2 implements Runnable { public void run() { for(int i=0; i<1000; i++) System.out.println(“Usando Runnable”); } } Multithreading • Para usar as classes Tarefa1 e Tarefa2 devemos fazer: Thread threadComHeranca = new Tarefa1(); Thread threadComRunnable =new Thread(new Tarefa2()); threadComHeranca.start(); threadComRunnable.start() Multithreading • A saída de nosso exemplo é mais ou menos essa: Usando Runnable Usando Herança Usando Herança Usando Runnable Usando Herança Usando Runnable (...) Multithreading • Quando uma JVM inicializa, há em geral uma única thread • Que tipicamente chama o método main de alguma classe • JVM continua a executar threads até que: 1. o método exit da classe Runtime tenha sido chamado 2. todas as threads não daemon tenham morrido 3. Ou retornando da chamada de run ou levantando uma exceção Multithreading • public class Thread extends Object implements Runnable Construtores Thread( nome_da_thread ) Thread() Cria uma Thread auto-numerada de formato Thread-1, Thread-2... run() “faz o trabalho" da thread Pode ser sobrescrito em uma sub-classe de Thread ou em um objeto Runnable start() Lança a thread, então retorna ao chamador Chama run Erro se chamar start 2 vezes para a mesma thread Multithreading • Métodos da classe Thread • Método estático sleep( milliseconds ) A Thread “dorme” (não disputa pelo processador) por um número de milisegundos Pode dar a threads de menor prioridade uma chance de executar • interrupt() Interrompe uma thread Multithreading • Métodos da classe Thread (cont.) • isInterrupted() Determina se uma thread está interrompida • isAlive() Retorna true se start foi chamado e a função run não foi completada Multithreading • • • Métodos da classe Thread (cont.) setName( nome_da_thread ) getName Multithreading • Todas as applets e os aplicativos Java são multithreaded • Threads têm prioridades de 1 a 10 • Thread.MIN_PRIORITY - 1 • Thread.NORM_PRIORITY - 5 (default) • Thread.MAX_PRIORITY - 10 • Threads novas herdam a prioridade da thread que as criou Multithreading • Timeslicing • A cada thread é atribuída uma fatia de tempo do processador para executar – chamado um quantum • Quando tempo acaba, processador é dado para a próxima thread de igual prioridade (se disponível) • A thread de maior prioridade é mantida executando • Sem timeslicing, cada thread executa até completar Multithreading • Escalonador Java Mantém a thread de maior prioridade executando • Se houver timeslicing, garante que threads de igual prioridade executem de modo round-robin • Novas threads de alta prioridade podem adiar a execução de threads de menor prioridade • Espera indefinida (starvation) • Métodos setPriority( int priorityNumber ) getPriority Multithreading • • Problemas Uma prioridade de thread Java pode ser mapeada de forma diferente para as prioridades de threads do SO subjacente • Solaris tem 2 (32–1) níveis de prioridades; • Windows NT tem apenas 7 níveis de prioridades Multithreading • Programa exemplo 1. 2. 3. 4. 5. 6. Demonstra técnicas básicas de threading Cria uma classe derivada de Thread Usa o método sleep Visão geral Cria 4 threads, que dormem por uma quantidade aleatória de tempo Depois que acabam de dormir, escrevem seu nome Multithreading O Programa tem duas classes • PrintThread 1. Derivada de Thread 2. Variável de instância sleepTime • ThreadTester 1. Cria 4 objetos PrintThread Multithreading • • • • • • • • • • • • • • • • • • • • • • • • • • • • • 1 // ThreadTester.java 2// Mostra múltiplas threads escrevendo em diferentes intervalos. 3 4 public class ThreadTester { 5 public static void main( String args[] ) 6{ 7 PrintThread thread1, thread2, thread3, thread4; 8 9 thread1 = new PrintThread( "thread1" ); 10 thread2 = new PrintThread( "thread2" ); 11 thread3 = new PrintThread( "thread3" ); 12 thread4 = new PrintThread( "thread4" ); 13 14 System.err.println( "\nStarting threads" ); 15 thread1.start(); 17 thread2.start(); 18 thread3.start(); 19 thread4.start(); 20 21 System.err.println( "Threads started\n" ); 22 } 23 } 24 25 class PrintThread extends Thread { 26 private int sleepTime; 27 28 // construtor PrintThread atribui nome a thread chamando 29 // construtor Thread • • • • • • • • • Classe ThreadTester 1. main 1.1 Inicializa objetos 1.2 start --------------Classe PrintThread 1. extends Thread 1.1 variáveis de instância Multithreading • • • • • • • • • • • • • • • • • • • • • • • • • • • 30 public PrintThread( String name ) 31 { super( name ); 33 34 // dorme entre 0 e 5 segundos 35 sleepTime = (int) ( Math.random() * 5000 ); 36 37 System.err.println( "Name: " + getName() + 38 "; sleep: " + sleepTime ); 39 } 40 41 // executa a thread 42 public void run() 43 { 44 // coloca thread para dormir por um intervalo aleatório try { 46 System.err.println( getName() + " going to sleep" ); 47 Thread.sleep( sleepTime ); 48 } 49 catch ( InterruptedException exception ) { 50 System.err.println( exception.toString() ); 51 } 52 53 // escreve nome da thread 54 System.err.println( getName() + " done sleeping" ); 55 } 56 } Chama o construtor da superclass para atribuir nome a thread. sleep pode lançar uma exceção, logo ele deve ficar em um bloco try Multithreading • • • • • • • • • • • • • • Name: thread1; sleep: 1653 Name: thread2; sleep: 2910 Name: thread3; sleep: 4436 Name: thread4; sleep: 201 Starting threads Threads started thread1 going to sleep thread2 going to sleep thread3 going to sleep thread4 going to sleep thread4 done sleeping thread1 done sleeping thread2 done sleeping thread3 done sleeping • • • • • • • • • • • • • • Name: thread1; sleep: 3876 Name: thread2; sleep: 64 Name: thread3; sleep: 1752 Name: thread4; sleep: 3120 Starting threads Threads started thread2 going to sleep thread4 going to sleep thread1 going to sleep thread3 going to sleep thread2 done sleeping thread3 done sleeping thread4 done sleeping thread1 done sleeping • • • • • • • • • Classe ThreadTester 1. main 1.1 Inicializa objetos 1.2 start --------------Classe PrintThread 1. extends Thread 1.1 variáveis de instância Multithreading Estados da Thread – Ciclo de Vida de uma Thread • Estados de uma Thread – Nova (Born) • A Thread acabou de ser criada com new (ainda não está em execução) • Quando start é chamado, entra no estado pronta – Pronta (Ready - passível de execução) • Fica a cargo do SO permitir a execução • A thread pronta de mais alta prioridade entra no estado “em execução” Multithreading Estados da Thread – Ciclo de Vida de uma Thread • Estados de uma Thread (cont.) – Em execução (Running) • O SO entrega o processador a thread (thread começa a executar) • Quando o método run completa ou termina, entra no estado “morta” – Morta (Dead) • Thread marcada para ser removida do sistema Multithreading Estados da Thread – Ciclo de Vida de uma Thread • Outros estados (cont.) – Espera • Entra quando wait é chamado em um objet que a thread está acessando • Uma thread em espera torna-se pronta quando o objeto chama notify • notifyAll – todas as threads em espera tornam-se prontas Multithreading • Estados da Thread – Ciclo de Vida • de uma Thread Multithreading • Exercício 1 1 class PrintThread extends Thread { 2 private int sleepTime; 3 4 // construtor PrintThread atribui nome a thread chamando 5 // construtor Thread 6 public PrintThread( String name ) 7{ super( name ); 8 9 // dorme entre 0 e 5 segundos 10 sleepTime = (int) ( Math.random() * 5000 ); 11 12 System.err.println( "Name: " + getName() + 13 "; sleep: " + sleepTime ); 14 } 15 16 // executa a thread 17 public void run() 18 { 19 // coloca thread para dormir por um intervalo aleatório 20 try { 21 System.err.println( getName() + " going to sleep" ); 22 Thread.sleep( sleepTime ); 23 } 24 catch ( InterruptedException exception ) { 25 System.err.println( exception.toString() ); 26 } 27 28 // escreve nome da thread 29 System.err.println( getName() + " done sleeping" ); 30 } 31 } Multithreading • Exercício 1 1 class PrintThread extends Thread { 2 private int sleepTime = 1000; 3 4 // construtor PrintThread atribui nome a thread chamando 5 // construtor Thread 6 public PrintThread( String name ) { 7 super( name ); 8} 9 10// executa a thread 11 public void run(){ 12 13 Int finalTime = 0; 14 While( finalTime <= 60000 ){ 15 // coloca thread para dormir por um intervalo de 1 segundo 16 try { 17 Thread.sleep( sleepTime ); 18 } 19 catch ( InterruptedException exception ) { 20 System.err.println( exception.toString() ); 21 } 22 23// escreve o segundo corrente 24 finalTime += 1000; 25 System.out.println(“tempo = “ + finalTime/1000 ); } } } Multithreading • Exercícios • • • • • Crie um programa que cria 10 threads cada uma escreve uma mensagem na tela contendo seu número. Escreva um programa que realize o cálculo das somas dos valores das linhas de uma matriz qualquer de números inteiros e imprima o resultado na tela. Faça com que o cálculo do somatório de cada linha seja realizado em paralelo por uma thread. Defina a classe Contador como uma implementação da interface Runnable, que imprime números de 0 a 1000. Crie a classe TesteContador que deve definir o método main que cria e inicia a execução do thread Contador. Teste o resultado executando a classe TesteContador. Agora altere o método main da classe TesteContador para criar dois ou mais threads Contador e inicialize a execução dos mesmos. Crie uma classe T1 do tipo Thread com um método construtor que receba um número de identificação da Thread e um método run que fique em loop eterno imprimindo na tela a frase "Thread x executando", onde x é o número de identificação da Thread. Faça um programa que crie uma matriz de 5 Threads T1 e, com um laço FOR, inicialize todas as Threads. Crie duas threads onde uma fica enviando notícias a cada 5 segundos (textos quaisquer, no total de 10), enquanto a outra fica enviando a hora a cada 10 segundos. A hora deverá ser informada umas 5 vezes para que o programa se encerre. Collections • • • • • Introdução Interfaces Implementações Algoritmos Customizando Implementações Interfaces • • • • • • • • • • • • • • • • • • • • • • • • • public class Funcionario { private String nome; private String endereco; private double salario; public String getNome() { return nome; } public String getEndereco() { return endereco; } public double getSalario() { return salario; } private void calculaSalario() { // Busca valores do banco etc. } private void atualizaDados() { // Busca valores do Banco etc. } } Interfaces • public interface Funcionario { • public String getNome(); • public String getEndereco(); • public double getSalario(); • } Interfaces • public interface Funcionario { • public static final int FUNCIONARIO_GERENTE = 0; • public static final int FUNCIONARIO_VENDEDOR = 1; • // etc. • } Interfaces • • • • • • • • • • • • • • • • • public class Pessoa implements Funcionario { private String nome; private String endereco; private double salario; public String getNome() { return nome; } public String getEndereco() { return endereco; } public double getSalario() { return salario; } } • Funcionario f = new Pessoa(); Interfaces • • • • • • • • • • public interface Relogio { public String getHoras(); } public interface Radio() { public void liga(); public void desliga(); public void trocaEstacao(int frequencia); } Interfaces • • • • • • • • • • • • • • • • • • • • • • • • public class RadioRelogio implements Radio, Relogio { private String horarioAtual; public RadioRelogio { // Inicializa objeto } public String getHoras() { return horarioAtual; } public void liga() { // Implementacao } public void desliga() { // Implementacao } public void trocaEstacao(int frequencia) { // Implementacao } } Interfaces • Exemplo de utilização de interfaces • Sistema Hospitalar x Veterinário Interfaces • Uma empresa de desenvolvimento de softwares possui um sistema utilizando em controle de clínicas médicas de pequeno porte. O sistema é relativamente simples, utilizado apenas para cadastro e controle de pacientes da clínica, mantendo um histórico do cliente, bem como informações médicas importantes. Interfaces • Em uma ocasião, a mesma empresa fechou um contrato para o desenvolvimento de um novo software para uma clínica recém aberta. A única diferença é que esta clínica era veterinária, lidava com animais e não com pessoas. Interfaces • A clínica veterinária também deseja manter histórico dos animais atendidos, bem como suas informações médicas (controle de vacinas etc.). Em suma, pode-se utilizar o sistema originalmente desenvolvido para clínicas gerais em clínicas veterinárias com algumas poucas adaptações. Interfaces • public class Animal { • // Informações da Classe • } Interfaces • public class Relatorios { • // ... • public void imprimeRelatorio(Pessoa p) { • // ... • } • // ... • } Interfaces • public interface Paciente { • public String getNome(); • public Historico getHistoricoMedico(); • public Ficha getInformacoesCadastrais(); • // etc. • } Interfaces • • • • • • • public class Pessoa implements Paciente { ... } public class Animal implements Paciente { ... } Interfaces • Paciente p = new Pessoa(); • Paciente a = new Animal(); Interfaces • public class Relatorios { • // ... • public void imprimeRelatorio(Paciente p) { • // ... • } • // ... • } Collections Introdução • O que é uma coleção? – Um objeto que agrupa múltiplos elementos em uma única unidade • Usadas para armazenar, recuperar e manipular elementos que formam um grupo natural. • Ex.: Vector, Hashtable, array (JDK 1.1) Problemática? Collections Collections Framework • Conjunto de interfaces, implementações e algoritmos • Vantagens – – – – – – Reduz esforço de programação Aumenta velocidade e qualidade na programação Permite interoperabilidade entre API´s Reduz esforço para aprender uma nova API Reduz esforço para criar uma nova API Promove reuso Collections Interfaces Collections Interfaces • São utilizadas sempre que possível – Parâmetros de métodos – Retorno dos métodos • Permite polimorfismo Collections Collection • Raiz da hierarquia • Grupo mais genérico de elementos • Não garante nas implementações – Duplicatas – Ordenação • Não possui nenhuma implementação direta • Iterator, extrutura de navegação – next, hasNext, remove(optional) Collections public interface Collection { // Basic Operations int size(); boolean isEmpty(); boolean contains(Object element); boolean add(Object element); // Optional boolean remove(Object element); // Optional Iterator iterator(); // Bulk Operations boolean containsAll(Collection c); boolean addAll(Collection c); // Optional boolean removeAll(Collection c); // Optional void clear(); // Optional // Array Operations Object[] toArray(); Object[] toArray(Object a[]); } Collection Collections SET • • • • • • Extends Collection Não contém duplicatas Não garante ordem entre os elementos Não acrescenta métodos Caracterização de tipo Operações – – – – Subconjunto (containsAll) União (addAll) Intercessão (reatinaAll) Diferença (removeAll) Collections LIST • • • • • • Extends Collection Coleção ordenada (Sequência) Pode ter duplicatas Controle na posição de inserção ou remoção Acesso aos elementos pelo índice ListIterator – hasPrevious,previous, nextIndex, previousIndex Collections public interface List extends Collection { // Positional Access Object get(int index); Object set(int index, Object element); void add(int index, Object element); Object remove(int index); abstract boolean addAll(int index, Collection c); // Search int indexOf(Object o); int lastIndexOf(Object o); // Iteration ListIterator listIterator(); ListIterator listIterator(int index); // Range-view List subList(int from, int to); } List // // // // Optional Optional Optional Optional Collections MAP • • • • Mapeamento de chaves em valores Não possui chaves duplicadas Cada chave leva a somente um elemento Para uma busca efetiva, o objeto da chave deve reimplementar os métodos: – hashCode – equals Collections public interface Map { // Basic Operations Object put(Object key, Object value); Object get(Object key); Object remove(Object key); boolean containsKey(Object key); boolean containsValue(Object value); int size(); boolean isEmpty(); // Bulk Operations void putAll(Map t); void clear(); // Collection Views public Set keySet(); public Collection values(); public Set entrySet(); // Interface for entrySet elements public interface Entry { Object getKey(); Object getValue(); Object setValue(Object value); } } MAP Collections Ordenação de Objetos • java.util.Comparator – Provê multiplas formas de ordenação – compare(object,object) • Retornos – Inteiro negativo = menor que – Zero = iguais – Inteiro positivo = maior que • Não são elementos do framework, apenas estruturas complementares Collections Sorted Set • Extends Set • Elementos ordenados de forma ascendente • Algumas operações a mais para aproveitar a vantagem da ordenação public interface SortedSet extends Set { // Range-view SortedSet subSet(Object fromElement, Object toElement); SortedSet headSet(Object toElement); //inferior SortedSet tailSet(Object fromElement); //superior // Endpoints Object first(); Object last(); // Comparator access Comparator comparator(); } Collections Sorted Map • Extends Map • Mapeamento onde as chaves são ordenadas de forma ascendente. public interface SortedMap extends Map { Comparator comparator(); SortedMap subMap(Object fromKey, Object toKey); SortedMap headMap(Object toKey); SortedMap tailMap(Object fromKey); Object firstKey(); Object lastKey(); } Collections Implementações Implementations JAVA Hash Table Resizable Array Balanced Tree Linked List Set Interfaces HashSet List Map TreeSet ArrayList, Vector HashMap, Hashtable LinkedList TreeMap Collections Usando List Collections Usando Set Collections Usando Map Collections • Exercícios • • • • Qual a vantagem que collection trás para sua aplicação em programas em java? Em que casos devemos utilizar List, Map e Set? As implementações estão prontas? Como devemos proceder para utilizarmos uma collection? Collections Criar uma classe ListaDePessoa que possua: – Uma lista de Strings para armazenar nomes – Um método para adicionar nomes – Um método para informar o tamanho da lista – Um método para listar todas as pessoas da lista • No programa principal: – Crie um menu de opções onde: 1. Adicione um novo nome a lista 2. Exiba todos os nomes da lista 3. Sair do programa – Após exibir o menu, mostre quantas pessoas tem na lista Collections Collections Collections Implemente uma ArrayList que possa conter Círculos. – Teste a coleção adicionando, removendo, buscando e imprimindo os objetos da lista – Crie um método que retorne a lista como um array. Collections Collections RMI • Sistemas distribuídos requerem que aplicações executando em diferentes espaços de endereçamento, potencialmente em máquinas diferentes, sejam capazes de trocar dados; • Java RMI é o mecanismo que permite um objeto invocar um método de outro objeto que existe em outro espaço de endereçamento; • A invocação de método remoto permite que um objeto executando sobre uma determinada JVM invoque métodos sobre um objeto executando sobre outra JVM. RMI • A definição do comportamento e a implementação do comportamento são conceitos separados: a definição do serviço remoto é codificado usando uma interface (interface) Java, e a implementação do serviço remoto é codificado usando uma classe (class); • A arquitetura RMI torna o uso de objetos Java distribuídos similar ao uso de objetos Java locais =⇒ transparência de acesso. RMI Implementação Java RMI • Camada Stub e Skeleton: intercepta as chamadas de métodos feitas pelo cliente para que a variável de referência da interface redirecione essas chamadas para o serviço RMI remoto; • Camada Remote Reference Layer: gerencia referências feitas dos clientes para os objetos do serviço remoto. A conexão do cliente ao servidor é Unicast (um-para-um); • Camada de transporte: é baseada nas conexões TCP/IP entre as maquinas em uma rede. RMI Argumentos e Valores de Retorno • Podem ser passados de ou para um método remoto qualquer entidade que seja uma instância de um tipo primitivo, objeto remoto ou objeto serializável (que implementa a interface java.io.Serializable; • Alguns objetos não atendem a estes critérios, normalmente por encapsular informação que faz sentido somente em um único espaço de endereçamento, como threads e descritores de arquivos; • Muitas classes core Java, incluindo as constantes dos pacotes java.lang e java.util implementam a interface Serializable. RMI Localizando o Serviço Remoto RMI • Pode-se utilizar diferentes tipos de serviços de diretório, incluindo o JNDI (Java Naming and Directory Interface); • O próprio RMI inclue um simples serviço, chamado de RMI Registry; • Ele executa em cada maquina que hospeda o serviço remoto, por definição na porta 1099; RMI Localizando o Serviço Remoto RMI • O servidor: o Cria um serviço remoto, instanciando o objeto que implemente aquele serviço; o Exporta aquele objeto para o RMI. Quando o objeto é exportado o RMI cria um serviço que aguarda as conexões do cliente; o Registra o objeto no RMI Registry, com um nome público. • O Cliente: o O RMI Registry é acessado através da classe estática Naming; o Ela provém o método lookup(), que aceita a URL que especifica o nome do servidor e o nome do serviço desejado e retorna uma referência remota para o objeto do serviço; o A URL é formada como seguinte: rmi://<host_name>[:port_number]/<service_name> RMI Passos para o Desenvolvimento do Servidor • Criar a interface do servidor, que deve estender a classe Remote. Todo método deve lançar a exceção RemoteException; • Implementar a interface criada; • Escrever o código que instancia a implementação do servidor, exporta o objeto para o RMI e o registra junto ao serviço de nomes da tecnologia Java (RMI registry). RMI Serviço de Nomes RMI Registry • Métodos da interface Registry: o void bind(String name, Remote obj): associa a referência remota ao nome especificado; o String[] list(): retorna um array dos nomes registrados; o Remote lookup(String name): retorna a referência remota correspondente ao nome especificado; o void rebind(String name, Remote obj): substitui a amarração para o nome espeficado, associando-o à referência remota especificada; o void unbind(String name): remove a amarração para o nome especificado. Mensageiro m = new MensageiroImpl(); Naming.rebind("rmi://localhost:1099/MensageiroService", m); RMI import java.rmi.Remote; import java.rmi.RemoteException; public interface Mensageiro extends Remote { public void enviarMensagem( String msg ) throws RemoteException; public String lerMensagem() throws RemoteException; } Compilar Interface RMI import java.rmi.RemoteException; import java.rmi.server.UnicastRemoteObject; public class MensageiroImpl extends UnicastRemoteObject implements Mensageiro { public MensageiroImpl() throws RemoteException { super(); } public void enviarMensagem( String msg ) throws RemoteException { System.out.println( msg ); } public String lerMensagem() throws RemoteException { return "This is not a Hello World! message"; } } Compilar Implementação Gerar Stub RMI import java.rmi.Naming; public class MensageiroServer { public MensageiroServer() { try { Mensageiro m = new MensageiroImpl(); Naming.rebind("rmi://localhost:1099/MensageiroService", m); } catch( Exception e ) { System.out.println( "Trouble: " + e ); } } public static void main(String[] args) { new MensageiroServer(); } } Compilar Servidor RMI import java.rmi.Naming; import java.rmi.RemoteException; import java.rmi.NotBoundException; import java.net.MalformedURLException; public class MensageiroClient { public static void main( String args[] ) { try { Mensageiro m = (Mensageiro) Naming.lookup( "rmi://localhost/MensageiroService" ); System.out.println( m.lerMensagem() ); m.enviarMensagem( "Hello World!" ); } catch( MalformedURLException e ) { Compilar System.out.println(); System.out.println( "MalformedURLException: " + e.toString() ); } catch( RemoteException e ) { System.out.println(); System.out.println( "RemoteException: " + e.toString() ); } Cliente RMI • Rodando o sistema RMI • Abrir três diferentes consoles do MS-DOS no seu Windows, ou outro, caso utilize um diferente sistema operacional. Em um dos consoles vai rodar o programa servidor, no outro o cliente e no terceiro o RMI Registry. Inicie com o RMI Registry. Você deve estar no mesmo diretório em que estão gravados seus arquivos para rodar o aplicativo. Execute a seguinte linha de comando: • Console A - rmiregistry • Console B - java MensageiroServer • Console C - java MensageiroClient RMI Console B - Hellow World! Console C - This is not a Hello World! message