Your SlideShare is downloading. ×
Apostila de Fundamentos Java
Upcoming SlideShare
Loading in...5
×

Thanks for flagging this SlideShare!

Oops! An error has occurred.

×

Introducing the official SlideShare app

Stunning, full-screen experience for iPhone and Android

Text the download link to your phone

Standard text messaging rates apply

Apostila de Fundamentos Java

15,999
views

Published on

Apostila do treinamento de fundamentos do Java.

Apostila do treinamento de fundamentos do Java.


3 Comments
43 Likes
Statistics
Notes
  • Faço das palavras de RafaCarmenez, as minhas, estudo e procuro aprender as coisas sozinho, por isso q pessoa q disponibilize para download essas apostilas por favor, Grato.
       Reply 
    Are you sure you want to  Yes  No
    Your message goes here
  • Muito bom!
       Reply 
    Are you sure you want to  Yes  No
    Your message goes here
  • Boa tarde Marcio, sou iniciante no estudo do JAVA, estou buscando fontes por conta... não faço curso, aprendo sozinho em horas vagas.
    Será que poderia disponibilizar esta apostila?
    Fico muito grato, Abraço.
       Reply 
    Are you sure you want to  Yes  No
    Your message goes here
No Downloads
Views
Total Views
15,999
On Slideshare
0
From Embeds
0
Number of Embeds
1
Actions
Shares
0
Downloads
0
Comments
3
Likes
43
Embeds 0
No embeds

Report content
Flagged as inappropriate Flag as inappropriate
Flag as inappropriate

Select your reason for flagging this presentation as inappropriate.

Cancel
No notes for slide

Transcript

  • 1. Fundamentos Java
  • 2. Sobre nossa empresa
    • A Jet Software é uma empresa jovem, dinâmica,
    • que atua no mercado de TI, em consultoria
    • e treinamento. Nossa empresa é
    • especializada em Java, .NET, SOA, EAI e metodologias
    • ágeis.
    • Nossos profissionais são experientes, certificados e
    • possuem vários anos de experiência de mercado,
    • agregando assim alto valor nas soluções apresentadas a
    • nossos clientes, quer sejam elas sobre consultoria ou
    • treinamentos.
  • 3. Sobre esta apostila
    • Esta apostila tem a finalidade de levar ao aluno os
    • fundamentos da linguagem Java. Ou seja, nosso objetivo é
    • mostrar os conceitos que regem a linguagem, seu
    • funcionamento, comportamento, configuração, setup de
    • ambiente e toda informação básica que darão ao aluno o
    • conhecimento técnico suficiente para a preparação para a
    • certificação e cobrir os pré-requisitos para os próximos
    • módulos de desenvolvimento Java para web, componentes
    • distribuídos ( EJB ) e demais módulos.
  • 4. Sobre este curso
    • Nosso foco é trazer a nossos alunos um curso
    • dinâmico, abordando o conteúdo da linguagem e da
    • plataforma, e também as melhores práticas e bibliotecas
    • Utilizadas pelo mercado. E foi pensando nisso que a
    • Jet Software elaborou sua grade de cursos, afim de
    • que ao término de cada módulo o aluno esteja dominando
    • a tecnologia / plataforma, e também conhecendo tudo
    • aquilo que o mercado utiliza, estando assim melhor
    • preparado para as futuras oportunidades.
  • 5. O que o aluno deve aprender sobre Java ?
    • Esta é uma pergunta que muitas pessoas fazem e provavelmente
    • continuarão a fazer. Existe um certo mito de que para ser um bom
    • programador Java o indivíduo deve saber somente “tudo” sobre a
    • linguagem. Fique calmo, pois isto não é verdade!
    • A linguagem e a plataforma Java possui inúmeras features e APIs, e
    • seria impossível descarregar todo este conteúdo sobre o aluno em um
    • só curso ou em um só livro, o que existe sim é um conjunto de
    • regras e conceitos básicos que o aluno necessita saber para iniciar
    • sua vida como programador Java, e após a absorção destes conceitos
    • é muito fácil adicionar mais conhecimento a sua base.
  • 6. O que o aluno deve aprender sobre Java ?
    • Todos os próximos módulos usarão os conceitos, APIs e
    • demais conhecimentos adquiridos neste curso de fundamentos.
    • Recomendamos aqueles alunos que desejam tirar a certificação que
    • ao término de nosso curso invistam entre 2 ou 4 semanas se
    • preparando para a prova, pois não basta somente absorver o conteúdo
    • em sala de aula como será passado, mas também treinar o que foi aprendido,
    • e ainda preparar-se para as famosas “pegadinhas” da prova.
    • Recomendamos o seguinte livro para a preparação, que contém uma gama
    • imensa de exercícios e dicas :
  • 7. Preparação para a certificação
    • SCJP Sun Certified Programmer for Java 6 Exam 310-065 [ILLUSTRATED] (Hardcover)
    • by Katherine Sierra (Author), Bert Bates (Author)
  • 8. Agenda do Curso
    • Introdução ao Java
    • Conceitos Básicos
    • Introdução a Orientação a Objetos
    • Declaração de variáveis
    • Construção de classes
    • Tipos
    • Herança e Polimorfismo
    • Interfaces
    • Enumerações ( Enum )
    • Controle de Fluxo
    • Tratamento de Exceções
    • O Framework de coleções ( Collection framework )
    • Generics
    • Threads
    • JDBC
  • 9. Introdução ao Java Capítulo 1
  • 10. Simples, orientada a objetos e familiar
    • A linguagem de programação Java foi pensada
    • para “atacar” as dificuldades do desenvolvimento
    • de aplicações, no contexto de heterogeneidade,
    • ambientes de rede distribuídos.
    • E além de todos estes desafios, a execução segura de
    • aplicações que consomem o mínimo de recursos de um
    • sistema, pode ser executada em qualquer hardware e
    • plataforma de software, e além de tudo pode ser estendida
    • dinamicamente.
  • 11. Simples, orientada a objetos e familiar
    • A linguagem de programação Java foi originada
    • como parte de um projeto de pesquisa para
    • desenvolver uma espécie de software avançado
    • para uma grande variedade de dispositivos de
    • rede ( móveis ). O objetivo era desenvolver uma
    • plataforma operacional que fosse pequena,
    • confiável, portável distribuída, tempo-real.
  • 12. Simples, orientada a objetos e familiar
    • Quando o projeto iniciou-se o C++ foi a linguagem escolhida. Mas conforme o
    • tempo foi passando as dificuldades encontradas com o C++ cresceram ao
    • ponto de que os problemas poderiam ser melhor resolvidos criando-se uma
    • nova plataforma de linguagem.
    • Decisões de design e arquitetura vieram de uma grande variedade de
    • linguagens, tais como Eiffel, SmallTalk, Objective C e Cedar/Mesa. O resultado
    • foi uma nova linguagem/plataforma que provou ser ideal para o
    • desenvolvimento de aplicações seguras, distribuídas, network-based,
    • aplicações de usuário final em diversos ambientes que vão desde sistemas
    • embarcados ( embedded ) até a Web e desktops.
  • 13. Robusta e segura
    • A linguagem de programação Java foi arquitetada
    • para ser um software altamente confiável.
    • Ela provê uma extensiva checagem em tempo de
    • compilação, seguida por um segundo nível de
    • checagem em tempo de execução. As features da
    • linguagem guiam os programadores no caminho
    • dos hábitos confiáveis de programação.
  • 14. Robusta e segura
    • O modelo de gerenciamento de memória é extremamente
    • simples, pois os objetos são criados com o operador new .
    • Não existe nenhum tipo de ponteiro definido pelo programador, não
    • existe aritimética de ponteiros , e temos ainda um garbage collector
    • automático. Este modelo simples de gerenciamento elimina uma gama
    • incrível de erros de programação que programadores C e C++ tem que
    • lidar no seu dia-a-dia. Podemos desenvolver código Java com a
    • confiança que o sistema/plataforma irá encontrar muitos erros
    • rapidamente e que os maiores problemas não ficarão escondidos até
    • nosso software estar em produção.
  • 15. Robusta e segura
    • A tecnologia Java foi desenvolvida para operar em ambientes distribuídos, o
    • que significa que a segurança é um item de extrema importância. Com as
    • propriedades de segurança que foram desenvolvidas dentro da linguagem e
    • no sistema de run-time, a tecnologia Java nos permite construir aplicações que
    • não podem ser invadidas por meios externos.
    • Em um ambiente de rede, as aplicações escritas na linguagem Java estão
    • seguras de qualquer intrusão por código não autorizado, ou ainda por vírus ou
    • arquivos inválidos.
  • 16. Arquitetura neutra e portável
    • A tecnologia Java é também responsável por suportar aplicações que serão instaladas
    • ( deployed ) em ambientes de redes heterogêneos. Nestes ambientes as aplicações
    • precisam ser capazes de executar em uma grande variedade de arquitetura de
    • hardware. Dentro desta variedade de plataformas de hardware, as aplicações devem
    • executar em cima de uma variedade de sistemas operacionais, e inter-operar com
    • Múltiplas interfaces de linguagem de programação.
    • Para acomodar esta diversidade de sistemas operacionais, o compilador Java produz o bytecode ,
    • que é um formato arquitetural intermediário e neutro, que é designado a trasportar o código
    • eficientemente para múltiplas plataformas de hardware e software. A natureza interpretada da
    • tecnologia Java resolve ambos problemas de distribuição binária e versionamento; pois o mesmo
    • byte code será executado em qualquer plataforma.
  • 17. Arquitetura neutra e portável
    • A arquitetura neutra e portável da plataforma da linguagem Java é conhecida como Java
    • Virtual Machine . Ela é uma especificação de uma abstração de uma máquina, na qual
    • os compiladores da linguagem Java podem gerar código. Implementações específicas
    • Da Java Virtual Machine para plataformas específicas de hardware e software criam a
    • concreta materialização da virtual machine.
    • A Java Virtual Machine é baseada primeiramente na especificação de interface POSIX,
    • um padrão da industria para a definição de interfaces de sistemas portáveis.
    • Implementar a Java Virtual Machine em novas arquitetura é uma tarefa relativamente
    • simples, necessitando apenas que a plataforma de destino cumpra com os requisitos
    • básicos, tal como o suporte a multi-threading.
  • 18. Alta Performance
    • Performance é sempre alvo de grandes considerações. A plataforma
    • Java possui uma performance superior adotando um esquema onde o
    • interpretador pode ser executado em velocidade máxima sem a
    • necessidade do ambiente de checagem de run-time. O garbage
    • collector automático é executado como uma thread de baixa
    • prioridade em background, proporcionando assim uma alta
    • probabilidade que a memória estará disponível quando requisitada,
    • causando assim uma melhor performance.
  • 19. Alta Performance
    • Aplicações que necessitam de uma grande
    • quantidade de poder de processamento podem
    • ser designadas tal como seções de computação
    • intensivas podem ser re-escritas em código nativo
    • de máquina como necessitar e interfacear com a
    • plataforma Java. Em geral, usuários percebem
    • que aplicações interativas respondem rápido,
    • mesmo que elas sejam interpretadas.
  • 20. Interpretada, threaded, dinâmica
    • O interpretador Java pode executar bytecodes Java
    • diretamente em qualquer máquina na qual o sistema de
    • interpretador e run-time tenha sido portada. Em uma
    • plataforma interpretada como o Java, a fase de link de um
    • programa é simples, incremental e leve. Os benefícios são
    • grandes, tais como ciclos de desenvolvimentos mais
    • rápidos, prototipação, experimentação, e o
    • desenvolvimento rápido de casos normais, ao contrário do
    • tradicional compilador “peso-pesado” : compilar, linkar e ciclos de testes.
  • 21. Interpretada, threaded, dinâmica
    • Aplicações modernas baseadas em rede, tal como o
    • HotJava Browser para a web, tipicamente necessida de muitas coisas
    • ao mesmo tempo. Um usuário trabalhando com o HotJava browser
    • pode executar muitas animações concorrentemente enquanto faz o
    • download de uma imagem e usa o scroll de uma página. A capacidade
    • de multi-thread da tecnologia Java provê os meios para a construção
    • de aplicações com atividades concorrentes de threads. Multithreading
    • resulta em um alto nível de interatividade para o usuário final.
  • 22. Interpretada, threaded, dinâmica
    • A plataforma Java suporta multi-threading no nível
    • de linguagem com a sofisticação adicional de
    • sincronização de primitivos: a biblioteca de linguagem
    • provê a classe Thread , e o sistema de run-time provê o
    • monitor e as condições de lock primitivas. No nível de
    • biblioteca, novamente, as bibliotecas de sistema de alto
    • nível, tem sido escritas para serem thread safe :
    • a funcionalidade provida pelas bibliotecas está disponível
    • sem o conflito para a execução de múltiplas threads.
  • 23. Interpretada, threaded, dinâmica
    • Enquanto o compilador Java é restrito no seu “compile-time static
    • checking”, o sistema de run-time da linguagem é dinâmico nos seus
    • estágios de linking.
    • As classes são “linkadas” somente quando necessário. Novos módulos de
    • código podem ser linkados sob demanda de uma grande variedade de fontes,
    • mesmo de fontes através da rede. No caso do HotJava Browser e aplicações
    • similares, código executável interativo pode ser carregado de qualquer lugar, o
    • que possibilita o update transparente de aplicações. O resultado é um serviço
    • constante on-line que sempre é incrementado; ele pode permaneter inovador e
    • recente, ser oferecido para mais clientes, e suportar o crescimento do
    • comércio eletrônico na internet.
  • 24. Multi-plataforma
  • 25. A plataforma Java, um novo jeito de fazer computação distribuída
    • Se pegarmos individualmente, estas
    • características discutidas acima podem ser
    • encontradas em uma grande variedade de
    • plataformas de software.
    • Mas o que é completamente novo é a maneira que a
    • tecnologia Java e o seu ambiente de runtime tem
    • combinado eles para produzir um poderoso e flexível
    • sistema de programação.
  • 26. A plataforma Java, um novo jeito de fazer computação distribuída
    • Desenvolver nossas aplicações usando a linguagem de programação Java resulta em
    • um software que é portável através de múltiplas arquiteturas de máquinas, sistemas
    • operacionais, e interfaces de usuário gráficas, seguro e de alta performance.
    • Com a tecnologia Java, nosso trabalho como desenvolvedores é muito fácil, pois o foco
    • de nossa atenção é somente no objetivo final de entregarmos um produto inovador no
    • prazo, baseado nos sólidos fundamentos da plataforma Java.
    • A melhor forma de desenvolver software é aqui, agora, trazido pela plataforma Java.
  • 27. A plataforma Java http://java.sun.com/javase/technologies/index.jsp
  • 28. Resumo
        • Simples
        • Orientada a Objetos
        • Distribuída
        • Multithreaded
        • Dinâmica
        • Arquiteturalmente Neutra
        • Portável
        • Alta Performance
        • Robusta
        • Segura
  • 29. Instalando o ambiente de desenvolvimento do Java
  • 30. O ambiente de desenvolvimento
    • Para podermos desenvolver programas em Java precisaremos :
    • Java Development Kit ( JDK ), que por sua vez é um
    • conjunto de programas e APIs que nos possibilita
    • escrevermos e compilar programas em Java.
    • Notepad ++
    • Netbeans, que é uma das mais famosas IDEs para
    • desenvolvimento Java.
  • 31. Passos para a instalação do ambiente
    • Download the Notepad++
    • http://notepad-plus.sourceforge.net/uk/site.htm
    • Execute o instalador do Notepad++
    • Download the JDK : http://java.sun.com/javase/downloads
    • Ou vá para a página principal : www.java.sun.com e navegue no link JavaSE, afim de baixar a versão correta ( 6.x )
    • Execute o instalador do JDK
    • Crie a variável JAVA_HOME no seu painel de controle, apontando para o diretório de instalação de seu JDK, ex : C:Arquivos de programasJavajdk1.6.0_05
    • Configure o seu path no painel de controle para conter o caminho do JDK, exemplo : %JAVA_HOME%;%JAVA_HOMEin%;%JAVA_HOMElib%;
  • 32. Passos para a instalação do ambiente
  • 33. Verificando a instalação
    • Abra uma janela de comandos do windows e digite o
    • seguinte comando : java –version
    • Você deverá ver o seguinte resultado ( ou a versão que
    • você instalou ):
    • java version 1.6.0_05 
    • Java(TM) SE Runtime Environment (build 1.6.0_05-b13)
    • Java HotSpot(TM) Client VM (build 10.0-b19, mixed mode, sharing)
  • 34. Estrutura de diretório
  • 35. Estrutura de diretório
    • Bin  Compilador e command line tools
    • Db  Banco de dados
    • Demo  Demos
    • Include  Arquivos para métodos native
    • Jre  Arquivos Java Runtime Env.
    • Lib  Arquivos de bibliotecas
    • Src  Código fonte das bibliotecas
  • 36. Conceitos Básicos Capítulo 2
  • 37. Tópicos
    • Compilando um programa em Java
    • • String
    • • Blocos e expressões
    • • Operadores
    • • Controle de execução
    • • Arrays
  • 38. Compilando um programa Java
    • Crie um diretório chamado c:projetosWelcome
    • Abra o Notepad++ e digite o seguinte código :
    • public class Welcome {
    • public static void main(String[] args) {
    • System.out.println(“Bem vindo ao mundo do Java”);
    • }
    • }
  • 39. Compilando um programa Java
    • Salve este arquivo como Welcome.java
    • dentro do diretório Welcome. Abra uma
    • janela do DOS e vamos compilar e
    • rodar nosso novo programa :
    • javac Welcome.java
    • java Welcome
    • Resultado : Bem vindo ao mundo do Java
  • 40. Programando em Java
    • Neste momento já possuímos um bom
    • conhecimento sobre a linguagem e a
    • plataforma Java, e já temos o JDK
    • instalado, compilando e executando programas
    • Java. Nesta parte veremos mais a fundo os
    • conceitos básicos de programação, tal como tipos
    • de dados, fluxo e loops.
  • 41. Programando em Java
    • Um programa Java simples.
    • É o que exibimos no trecho código abaixo, e podemos até dizer que
    • este programa tem o mínimo de código necessário para que o mesmo
    • seja executado como um “executável”, como veremos mais a frente na
    • anatomia de um programa Java :
    • public class PrimeiroExemplo {
    • public static void main(String[] args) {
    • System.out.println("Nosso primeiro exemplo !!!");
    • }
    • }
  • 42. Anatomia de um programa Java
    • Traçaremos a antomia deste programa Java para
    • tornarmos mais confortáveis com o framework provido pelo
    • JDK. A primeira propriedade que devemos notar é que o
    • Java é “case sensitive”, ou seja, o Java pode interpretar
    • maiúsculo/minúsculo como erro se digitarmos MAIN ao invés de main,
    • e o programa não poderá ser executado gerando um erro :
    • C:projetosWelcome>javac PrimeiroExemplo.java
    • C:projetosWelcome>java PrimeiroExemplo
    • Exception in thread "main" java.lang.NoSuchMethodError: main
  • 43. Anatomia de um programa Java
    • Este erro é ocasionado por que a JVM espera que a classe
    • possua um método chamado main com a seguinte
    • assinatura :
    • public static void main (String[] args) {
    • }
    • Ao invés de :
    • public static void MAIN (String[] args) {
    • }
  • 44. Anatomia de um programa Java
    • public  é um modificador de acesso, que rege como a classe pode
    • ser acessada. Veremos modificadores a fundo mais a frente.
    • class  é um identificador, um marcador que diz que o bloco inteiro é
    • uma classe, e vale a pena apontar mais uma vez que tudo no Java é
    • um tipo de classe específica. Em linhas muito gerais uma classe é um
    • container de código que define o comportamento de uma aplicação,
    • um bloco de código no qual todo programa é montado sobre, e tudo
    • em um programa Java deve estar dentro de uma class.
  • 45. Anatomia de um programa Java
    • O padrão de nomeclatura de classes Java é o famoso “camel case”, onde
    • usamos uma letra maiúscula sempre que passamos para uma nova parte de
    • identificação da classe, para ficar mais claro podemos dar como exemplo duas
    • classes, uma para registrar pagamentos e outra para listar balanço :
    • public class RegistrarPagamento {
    • ..
    • }
    • Public class ListarBalanco {
    • ..
    • }
  • 46. Anatomia de um programa Java
    • Outra coisa a ser notada são os colchetes { }, que
    • delimitam o início e fim de um determinado bloco, e se
    • abrimos um novo bloco, o mesmo deve ser fechado em
    • algum momento abaixo. Caso não façamos isso
    • receberemos um erro do compilador.
    • public class NomeDaClasse {
    • public static void main(String[] args) {
    • //invocação de métodos, apis, e etc…
    • }
    • }
  • 47. Anatomia de um programa Java
    • Não precisamos nos preocupar com a
    • palavra chave “static” neste momento, pois
    • veremos estes e outros conceitos mais de
    • perto nos próximos capítulos. O ponto a ser
    • lembrado é que toda classe Java que desejamos
    • que seja “executável” por meio de linha de
    • comando deve ter a sintaxe acima declarada.
  • 48. Comentários
    • //
    • /* e */
    • /** e */
  • 49. Comentários
    • /**
    • * Este é nosso primeiro JavaDoc
    • * @version 1.00 08/02/2009
    • * @author Márcio Alves Marinho
    • */
    • public class SegundoExemplo {
    • /*
    • Este é nosso primeiro comentário longo
    • Blah blah blah blah blah blah blah blah
    • Blah blah blah blah blah blah blah blah
    • Blah blah blah blah blah blah blah blah
    • Blah blah blah blah blah blah blah blah
    • Blah blah blah blah blah blah blah blah
    • */
    • public static void main(String[] args) {
    • //Um comentário simples de uma linha só
    • System.out.println("Nosso segundo exemplo !");
    • }
    • }
  • 50. Tipos de Dados Tipo Bits Bytes Mínimo Máximo byte 8 1 -2 7 2 7 -1 short 16 2 -2 15 2 15 -1 int 32 4 -2 31 2 31 -1 long 64 8 -2 63 2 63 -1 float 32 4 n/a n/a double 64 8 n/a n/a boolean Verdadeiro / falso True / false - - char caractere 1 String caracteres n/a n/a n/a
  • 51. String
    • • O tipo String é um dos mais utilizados em qualquer linguagem
    • de programação
    • • Em Java, o tipo String é uma classe e não um tipo primitivo
    • • No entanto, assim como os tipos primitivos, as strings podem
    • ser criadas a partir de constantes, que, no caso, são seqüências
    • de caracteres delimitados por aspas duplas. Ex:
    • String s = “abc”;
    • • Embora seja um objeto, não há a necessidade de utilização do
    • operador new , como acontece com TODAS as outras classes.
  • 52. String
    • • As instâncias de String são objetos imutáveis, ou seja, uma vez criada o seu
    • valor não pode ser nunca alterado.
    • • Isto acontece porque cada instância de String é criada apenas uma vez, e essa
    • lista de strings é mantida pelo sistema. Se uma nova String for criada e o seu
    • valor já estiver nesta lista, não há a necessidade de criar uma nova instância.
    • Ex.:
    • String s1, s2, s3; abc
    • s1 = “abc”;
    • s2 = “abc”;
    • s3 = s1.toUpperCase();
  • 53. Variáveis
    • Em Java toda variável necessita ter um tipo, isto porque o Java é uma
    • linguagem fortemente tipada, como vimos anteriormente :
    • double salary;
    • int vacationDays;
    • long earthPopulation;
    • boolean done;
    • int i, j; // ambas inteiras
    • Lembrando sempre que devemos inicializar uma variável antes de podermos
    • utilizar a mesma para qualquer função :
    • int vacationDays;
    • // ERRO !--variable not initialized
    • System.out.println(vacationDays);
  • 54. Variáveis
    • Constantes são variáveis “imutáveis”, pois uma vez atribuido um valor a mesma,
    • nunca mais poderemos mudá-lo :
    • public class Constants {
    • public static void main(String[] args) {
    • final double CM_PER_INCH = 2.54;
    • double paperWidth = 8.5;
    • double paperHeight = 11;
    • System.out.println("Paper size in centimeters: "
    • + paperWidth * CM_PER_INCH + " by " + paperHeight *
    • CM_PER_INCH);
    • }
    • }
    • A palavra chave final é quem torna a variável imutável ( constante ) !
  • 55. Operadores e atribuição
  • 56. Operadores e atribuição
    • Operadores são utilizados para operações aritiméticas, ou seja,
    • adição, subtração, multiplicação e divisão. Atribuição é a ação de
    • determinar um valor a uma variável.
    • O trabalho de atribuir um valor a uma variável parece ser algo muito
    • simples, pois a única coisa que devemos fazer é colocar um valor no
    • lado direito do sinal de igual “=” e a variável a esquerda do mesmo.
    • Veremos capítulo de Orientação a Objetos que isto não é tão fácil
    • quanto parece, mas neste momentos nos ateremos aos exemplos
    • mais simples :
  • 57. Atribuição
    • int x = 4;
    • int a = 12;
    • long l = 44444444444444;
    • double d = 355.44;
  • 58. Operadores
    • Como exmeplo de operações podemos utilizar :
    • x += 4;
    • Que é o equivalente a :
    • x = x + 4;
    • Geralmente quando queremos fazer este tipo de operação direta utilizamos o símbolo antes do sinal
    • de =, como *= ou %=). Exemplos de Incrementanto e decremento :
    • int myVar = 15 ;
    • myVar++ ;
    • O valor de myVar será de 16, pois adicionamos mais um número ao mesmo. Outros exemplos :
    • int m = 7;
    • int n = 7;
    • int a = 2 * ++m; // vale 16, e “m” vale 8
    • int b = 2 * n++; // vale 14, e “n” vale 8
  • 59. Operadores relacionais
    • Operadores relacionais são aqueles que estão ligados a comparações, e o seu resultado
    • é sempre true ou false, a caracterização dos mesmos é pelo sinal “==”, um duplo sinal
    • de igual, como veremos a seguir :
    • 3 == 7 ( false )
    • 3 != 7 ( true )
    • Nota :
    • == ( igual )
    • != ou <> ( diferente )
    • Temos também os outros operadores, < menor que, > maior que, <= menor ou igual
    • que, e >= maior ou igual que. O Java segue o C++ e usa os operadores && e || que são
    • avaliados em “short circuit” . Ou seja, o segundo argumento não é avaliado se o
    • primeiro já determinar o valor. A sintaxe é muito simples :
  • 60. Operadores relacionais
    • expressão1 && expressão2
    • int x = 5;
    • x != 0 && 1 / x > x + y;
    • A segunda parte de nossa expressão nunca será avaliada, pois a
    • primeira parte dela já satisfaz a condição que queremos. E da mesma forma
    • poderemos utilizar o ou lógico ||.
    • expressão1 || expressão2
    • Outro operador lógico utilizado pelo Java é o operador ternário, que tem sua sintaxe :
    • condição1 ? expressão1 : expressão2
  • 61. Operadores relacionais
    • Este operador avalia a condição1, e se a mesma for verdadeira (true), então o Java atribui a primeira
    • expressão como resultado, senão a segunda :
    • int x = 7;
    • int y = 9;
    • String resultado = x > y ? “X é Maior que Y” : “Não, X não é maior que Y”
    • System.out.println(resultado);
    • Operadores de bitwise
    • Este tipo de operador funciona com qualquer tipo inteiro, e eles operam diretamente com os bits que
    • compõem os inteiros. Isto significa que podemos utilizar um tipo de máscara para pegar os bits
    • individuais de um número. Estes operadores são :
    • & (“and”) | (“or”) ^ (“xor”) ~ (“not”)
  • 62. Operadores relacionais
    • Como exemplo temos :
    • int fourthBitFromRight = (n & 8) / 8;
    • Estes operadores tem uma particularidade, pois eles não são
    • executados em short circuit, ou seja, a segunda expressão será
    • avaliada de qualquer forma após a primeira.
    • Por último temos os operadores de shift, que servem para mover os bits para a
    • esquerda ou direita, eles são >> , << e >>> .
    • int n = 6;
    • int quartoBitDaDireita = (n & (1 << 3)) >> 3;
  • 63. Conversão entre tipos numéricos
  • 64. Conversão entre tipos numéricos
    • Quando convertemos nossos valores para uma variável de capacidade
    • superior, não temos problema algum com o conteúdo, mas quando
    • tentamos fazer o inverso, devemos utilizar um cast , e lidar com a
    • perda de dados :
    • int n = 123456789;
    • float f = n;
    • System.out.println(&quot;n == &quot; + n);
    • System.out.println(&quot;f == &quot; + f);
    • n == 123456789
    • f == 1.23456792E8
  • 65. Conversão entre tipos numéricos
    • O exemplo acima nos mostra um cast automático entre um
    • int e um float, nesse caso, a magnitude do número será
    • mantida, mas haverá uma conversão automática para o
    • tipo float e perderemos alguma precisão. Podemos ver na
    • figura anterior que as setas cheias indicam uma conversão
    • sem perda de precisão, e as setas pontilhadas conversão com possível
    • perda de precisão.
    • Quando dois valores usam um operador binário ( por exemplo n + f
    • onde um operando é um integer e o outro um float), ambos operandos são
    • convertidos para um tipo comum antes da operação ser executada.
  • 66. Conversão entre tipos numéricos
    • Se um dos operandos é do tipo double , o outro
    • será convertido pra double .
    • Se um dos operandos é do tipo float , o outro será convertido para float .
    • Se um dos operandos é long , então o outro será convertido pra long .
    • Em qualquer outro caso serão convertidos para int
  • 67. Conversão entre tipos numéricos ( cast )
    • Nos exemplos anteriores vimos que as conversões são automáticas,
    • pois estamos tentando colocar ó conteúdo de uma variável de menor
    • grandeza em uma outra de maior grandeza. Esta conversão
    • automática não acontece quando tentamos fazer o contrário,
    • colocarmos o conteúdo de uma variável double dentro de um int , por
    • exemplo :
    • double x = 9.997;
    • int nx = (int) x;
  • 68. Operadores e hierarquia de parênteses
    • Devemos prestar atenção na precedência de
    • operadores no momento em que montamos uma
    • expressão, pois dependendo da disposição das
    • expressões ou dos operadores podemos ter uma
    • precedência diferente da esperada. Se nenhum
    • parêntese for usado, então a precedência natural
    • será. Como exemplo, o operador && tem uma
    • precedência mais altar q || :
  • 69. Operadores e hierarquia de parênteses
    • a && b || c
    • é o mesmo que :
    • (a && b) || c
    • Por que o sinal += associa da direita para a esquerda,
    • a expressão a += b += c significa a += (b += c)
    • Ou seja, o valor de b += c (que é o valor de b depois da adição) é adicionado a.
  • 70. Operadores e hierarquia de parênteses Operadores Associatividade [] . () (invocação de método) Esquerda para a direita ! ~ ++ -- + (unary) – (unary) () (cast) new Direita para a esquerda * / % Esquerda para a direita + - Esquerda para a direita << >> >>> Esquerda para a direita < <= > >= instanceof Esquerda para a direita == != Esquerda para a direita & Esquerda para a direita ^ Esquerda para a direita | Esquerda para a direita && Esquerda para a direita || Esquerda para a direita ?: Esquerda para a direita = += -= *= /= %= &= |= ^= <<= >>= >>>= Esquerda para a direita
  • 71. Enumerations
    • As vezes precisamos representar um conjunto
    • distintos de valores para um cálculo, ou
    • precisamos de um conjunto restritivo. O Java, apartir de
    • sua versão 5 disponibiliza um valioso recurso chamado
    • enumeration ( enum ), que é um tipo especial para
    • armazenar um conjunto de dados :
    • enum Size { SMALL, MEDIUM, LARGE, EXTRA_LARGE };
    • Size s = Size.MEDIUM;
  • 72. Strings
    • O tipo String é um dos mais utilizados em qualquer
    • linguagem de programação. Em Java, o tipo String é uma
    • classe e não um tipo primitivo, no entanto, assim como os
    • tipos primitivos, as strings podem ser criadas a partir de
    • constantes, que, no caso, são seqüências de caracteres
    • delimitados por aspas duplas :
    • String s = “abc”;
  • 73. Strings
    • Embora seja um objeto, não há a necessidade de
    • utilização do operador new, como acontece com TODAS
    • as outras classes.
    • As instâncias de String são objetos imutáveis, ou seja, uma
    • vez criada o seu valor não pode ser nunca alterado. Isto
    • acontece porque cada instância de String é criada apenas
    • uma vez, e essa lista de strings é mantida pelo sistema. Se
    • uma nova String for criada e o seu valor já estiver nesta
    • lista, não há a necessidade de criar uma nova instância.
  • 74. Strings
    • String s1, s2, s3;
    • s1 = “abc”;
    • s2 = “abc”;
    • s3 = s1.toUpperCase();
  • 75. String ( alguns métodos ) Assinatura Descrição Exemplo char charAt(int posicao) Retorna o caractere em determinada posição na String String s = “Teste”; char c = s.charAt( //Resultado: ‘s’ int indexOf(String s2) Retorna a posição da primeira ocorrência de s2 na String String s = “Teste”; int pos = s.indexOf(“st”); //Resultado: 2 int lastIndexOf(String s2) Retorna a posição da última ocorrência de s2 na String String s = “Teste”; int pos = s.lastIndexOf(“e”); //Resultado: 4 int length() Retorna o tamanho da String String s = “Teste”; int tam = s.length(); //Resultado: 5 String substring(int pos1, int pos2) Retorna um pedaço da string que vai de pos1 a pos2 String s = “Teste”; String s2 = s.substring(1, 4); //Resultado: “est” String toUpperCase() Converte para maiúsculo String s = “Teste”; String s2 = s.toUpperCase(); //Resultado: ‘TESTE’ String toLowerCase() Converte para minúsculo String s = “Teste”; String s2 = s.toLowerCase(); //Resultado: ‘teste’ String trim() Limpa os espaços no início e no final da String String s = “ Teste da a ”; String s2 = s.trim(); //Resultado: “Teste da a”
  • 76. String ( comparações )
    • Comparação de Strings :
    • Ao comparar duas Strings utilize sempre o método equals() em vez do operador ==.
    • Isto é necessário porque o == compara as referências, enquanto que o equals() compara
    • os valores das referências:
    • String s1 = “a”;
    • String s2 = “a”;
    • if(s1 == s2){
    • //De vez em quando funciona 
    • }
    • if(s1.equals(s2)){
    • //Forma correta de comparar
    • }
    • “ Hello&quot;.equalsIgnoreCase(&quot;hello&quot;)
  • 77. String ( Métodos )
    • String greeting = &quot;Hello&quot;;
    • int n = greeting.length(); // 5.
    • char first = greeting.charAt(0); // first is 'H'
    • char last = greeting.charAt(4); // last is 'o'
    • int cp = greeting.codePointAt(index);
    • Documentação completa on-line de String :
    • http://java.sun.com/javase/6/docs/api/java/lang/String.html
  • 78. Orientação a Objetos Capítulo 3
  • 79. Orientação a Objetos
    • O paradigma de orientação a objetos ( OO ) é o assunto
    • mais quente na forma de desenvolver software na
    • “ atualidade”. O mesmo substituiu a famosa forma
    • estruturada de desenvolver sistemas, e podemos citar por
    • exemplo a linguagem C ou Clipper. Java é uma linguagem
    • totalmente orientada a objetos.
    • Um programa orientado a objetos é composto de objetos, e cada
    • objeto tem uma funcionalidade específica que é exposta para os
    • usuários, ou ainda temos outras funcionalidades que são
    • comportamentos escondidos.
  • 80. Classes
    • Uma classe é um template, ou ainda podemos considerá-la
    • uma forma na qual objetos são “cozinhados como bolos”,
    • ou seja todo objeto terá o formato da forma que foi produzido.
    • Como vimos anteriormente, qualquer código escrito em
    • Java é SEMPRE escrito dentro de uma classe.
    • As bibliotecas standard do Java possuem uma gama
    • imensa de classes para tratamento de interface de usuário,
    • datas, programação em rede e muito mais.
  • 81. Classes
  • 82. Classes
    • Quando construímos um objeto apartir de uma classe,
    • podemos dizer que o objeto é uma instância daquela
    • classe.
    • import java.util.Date;
    • public class Contrato {
    • Date dataRegistro;
    • Date dataVencimento;
    • double valor;
    • void adicionarVencimento (int valor) {
    • //implementação aqui
    • }
    • double calcularValor (int valor) {
    • //implementação aqui
    • return 0;
    • }
    • }
  • 83. Classes ( propriedades )
    • Uma classe possui algumas propriedades
    • básicas, que podemos classificar da
    • seguinte forma :
    • Encapsulamento – Também conhecido como “esconder a informação”, que nada mais é do que a combinação de estado e comportamento, empacotados para esconder os detalhes da implementação do usuário.
    • Campos de instância – Os dados vivem aqui dentro, que são variáveis declaradas dentro das classes.
    • Métodos – São os procedimentos de acesso aos dados contidos nos campos de instância.
    • Para termos estas propriedades acima NUNCA devemos invocar um campo de instância diretamente, pelo contrário, devemos sempre invocar um método que realizará o trabalho necessário para retornar-nos o valor desejado.
  • 84. Objetos
    • Objetos são a materialização de uma classe, ou seja, como dissemos anteriormente uma classe é como uma forma para criarmos novos objetos que farão parte do nosso programa.
    • Objetos possuem as seguintes propriedades:
    • Comportamento – Simplesmente aquilo que o objeto é capaz de realizar.
    • O estado do objeto – Como o objeto reage quando invocamos seus métodos.
    • Identidade do objeto – Como o objeto de distingue dos outros objetos que podem ter o mesmo estado e comportamento;
  • 85. Identificando classes
    • Em programas procedurais nós iniciamos o programa com algum processo no topo, tipo “principal”, mas em programação OO não existe este tipo de mecanismo. Na programação OO precisamos criar classes e colocar métodos neles.
    • Uma regra para encontrarmos classes é olhando para os substantivos de nossos use-cases ou estórias, e os métodos serão os verbos.
  • 86. Identificando classes
    • Ordem de Pagamento
    • Item
    • Endereço de envio
    • Pagamento
    • Pedido
    • Conta
  • 87. Relacionamento entre classes
    • Dependência ( Usa uma classe )
    • Agregação ( Tem uma classe )
    • Herança ( É um tipo de classe )
  • 88. Relacionamento entre classes (125)
  • 89. Criando e usando objetos
    • Para podermos usar objetos precisamos antes criá-los apartir de sua classe :
    • java.util.Date data = new java.util.Date();
    • System.out.println(data);
    • String s1 = new java.util.Date().toString();
    • System.out.println(s1);
  • 90. Atributos
    • Atributos são as variáveis de instância que existem dentro das classes para compor seu estado, ou seja, são as propriedades que uma classe carrega para compor sua informação.
  • 91. Atributos
    • public class Pessoa {
    • long id;
    • String nome;
    • Date dataNascimento;
    • }
  • 92. Métodos
    • Como vimos rapidamente anteriormente, os métodos são funções utilizadas para acessar um determinado comportamento da classe.
  • 93. Métodos
    • import java.util.Date;
    • /**
    • * @author Marcio
    • */
    • public class Pessoa {
    • private long id;
    • private String nome;
    • private Date dataNascimento;
    • public long getId() {
    • return id;
    • }
    • public void setId(long id) {
    • this.id = id;
    • }
  • 94. Métodos
    • public String getNome() {
    • return nome;
    • }
    • public void setNome(String nome) {
    • this.nome = nome;
    • }
    • public Date getDataNascimento() {
    • return dataNascimento;
    • }
    • public void setDataNascimento(Date dataNascimento) {
    • this.dataNascimento = dataNascimento;
    • }
    • }
  • 95. Construtores
    • Construtores são métodos especiais para criar novas instâncias de objetos. Estes métodos possuem o mesmo nome da classe, mas sem retorno. Podemos ainda usar os construtores para atribuirmos um estado inicial ao objeto, se assim o desejarmos.
  • 96. Construtores
    • import java.util.Date;
    • public class Pessoa {
    • private long id;
    • private String nome;
    • private Date dataNascimento;
    • //Construtor defaul para a classe pessoa
    • public Pessoa() {
    • }
    • public Pessoa(long id, String nome, Date dataNascimento) {
    • this.id = id;
    • this.nome = nome;
    • this.dataNascimento = dataNascimento;
    • }
  • 97. Exemplo
    • public class Pessoa {
    • ...
    • public static void main(String[] args) {
    • Pessoa p1 = new Pessoa();
    • Pessoa p2 = new Pessoa(1, &quot;Marcio Alves Marinho&quot;,
    • new Date(&quot;14/12/1974&quot;));
    • System.out.println(p1.getId() + &quot; # &quot; + p1.getNome() + &quot; # &quot; +
    • p1.getDataNascimento());
    • System.out.println(p2.getId() + &quot; # &quot; + p2.getNome() + &quot; # &quot; +
    • p2.getDataNascimento());
    • }
    • ...
    • }
    • Resultado :
    • 0 # null # null
    • 1 # Marcio Alves Marinho # Sat Dec 14 00:00:00 BRT 1974
  • 98. Pacotes
    • Pacotes são uma forma de organizar nosso código, no fundo pacotes nada mais são do que uma estrutura hierárquica de diretórios que o Java usa para uma melhor organização do código fonte.
    • Podemos então organizar nosso código por camadas, nível de importância, ou qualquer outra forma que for mais conveniente.
  • 99. Pacotes
  • 100. Pacotes
  • 101. Pacotes
    • Um pacote genérico seguindo a convenção proposta pela Sun, diz que o prefixo de um pacote único deve estar escrito em minúsculo, primeiramente com o domínio, e os componentes subsequentes sendo o nome da organização, divisão, departamento, projeto, máquina ou login name.
    • com.sun.eng
    • com.apple.quicktime.v2
    • edu.cmu.cs.bovik.cheese
    • br.com.jetsoftware.domain
  • 102. Especificando e Importando Pacotes
    • O Comando Package serve para especificar a que pacote uma determinada classe ou inteface pertence.
    • O Comando Import torna disponível para o pacote corrente, as classes dos pacotes mencionados após a cláusula import.
  • 103. Resolvendo Nomes e Colisões
    • Quando dois ou mais pacotes são importados para um
    • determinado programa e eles contém classes de mesmo nome isso
    • não representa problemas de colisão caso tais classes não sejam
    • utilizadas
    • No caso de ser necessário fazer referência a uma das classes
    • citadas acima, isso deve ser feito de modo explícito para que não
    • haja problemas de colisão. Caso isso não seja feito, o compilador
    • enviará uma mensagem de erro, forçando que essa chamada seja
    • explicitada.
    • java.util.Date / java.sql.Date
  • 104. Modificadores de acesso
    • class MinhaClass { }
    • Apesar desta declaração funcionar a mesma não é ideal, pois como já vimos necessitamos organizar o nosso código na forma de pacotes, e precisamos ainda organizar o acesso as nossas classes. Ou seja, precisamos definir quem poderá acessar nossas classes e de onde.
  • 105. Modificadores
    • De acesso : public, protected, private.
    • Não relacionados a acesso : strictfp, final, e abstract.
  • 106. Modificadores ( em miúdos )
    • Podemos exemplificar o acesso a classes, se dissermos por exemplo que a class A tem acesso a outra classe B, e isto significa que a classe A pode fazer uma destas 3 coisas :
    • Criar uma instância de B
    • Extender B ( ser uma sub-classe de B )
    • Acessar certos métodos e variáveis dentro de B, dependendo do controle de acesso destes métodos e variáveis.
  • 107. Modificadores ( em miúdos )
    • Na verdade acesso significa visibilidade . Se a classe A não puder ver a classe B, então o nível de acesso dos métodos e variáveis dentro de B não farão a menor diferença, pois a classe A não terá como acessá-los de forma alguma.
  • 108. Acesso Default
    • Default – Uma classe com acesso default não possui declaração de modificadores, e este é o acesso default quando não especificamos nenhum. Default também é conhecido como “package level access”, por que as classes com acesso default podem somente ser vista por classes dentro do mesmo pacote.
  • 109. Default, exemplo
    • Arquivo Beverage.java
    • package cert;
    • class Beverage { }
    • Arquivo Tea.java
    • package exam.stuff;
    • import cert.Beverage;
    • class Tea extends Beverage { }
    • Se tentarmos compilar....
    • Can't access class cert.Beverage. Class or interface must be
    • public, in same package, or an accessible member class.
    • import cert.Beverage;
  • 110. Acesso Public
    • Public – Uma classe que é declarada com a palavra chave public dá acesso a todas classes de todos pacotes. Todas as classes do universo ( e outros universos paralelos) tem acesso a classes “public” .
  • 111. Public, exemplo
    • package cert;
    • public class Beverage { }
    • Agora a compilação funcionará !
  • 112. Private
    • Como o próprio nome já diz, “private” é um modificador para acesso privado, ou seja, ninguém externamente a classe tem acesso ao que for definido com esse modificador de acesso.
  • 113. Final
    • Classes definidas como “final” não podem ter sub-classes !
    • Em outras palavras, outras classes não poderão extendê-las, e qualquer tentativa receberemos um erro do compilador.
  • 114. Final, exemplo
    • package cert;
    • public final class Beverage {
    • public void importantMethod() { }
    • }
    • package exam.stuff;
    • import cert.Beverage;
    • class Tea extends Beverage { }
    • Se tentarmos compilar de novo...
    • Can't subclass final classes: class
    • cert.Beverage class Tea extends Beverage{
    • 1 error
  • 115. Abstract
    • Classes declaradas como “abstract” não podem ser instanciadas, isto acontece porque as mesmas são usadas como template para outras classes, ou seja, elas já nasceram para conterem algum comportamento base e serem extendidas e terem um refinamento nas sub-classes.
  • 116. Abstract, exemplo
    • abstract class Carro {
    • private double price;
    • private String model;
    • private String year;
    • public abstract void goFast();
    • public abstract void goUpHill();
    • public abstract void impressNeighbors();
    • // Mais métodos...
    • }
    • Se tentarmos a façanha de instanciá-la :
    • Carro.java:7: class Car is an abstract
    • class. It can't be instantiated.
    • Car x = new Car();
    • 1 error
  • 117. Abstract, exemplo
    • package comida;
    • public abstract class Fruta{
    • /* any code you want */
    • }
    • import comida;
    • class Banana extends Fruta{
    • /* any code you want */
    • }
  • 118. Herança
    • Extends é a palavra chave usada para podermos definir herança entre classes no Java. Toda sub-classe possui todas as características da classe base que foi herdada, isso funciona quase que exatamente como se fosse herança genética, onde o herdeiro tem as características de seus pais, cor dos olhos, cabelo, feições e etc.
    • Simplesmente usamos a seguinte notação :
    • ClasseB extends ClasseA
  • 119. Herança
    • Com herança podemos modificar todo o comportamento de uma cadeia de classes alterando somente o código da classe base. Por isso devemos ter muito cuidado quando fazemos o design da mesma, pois um bug ou código mal-feito se extenderá por toda hierarquia de classes.
  • 120. Interfaces
    • Interfaces são uma alternativa a herança, qualquer classe pode “assinar” ou seja, implementar os métodos definidos na mesma, sem dizer como o farão.
    • Elas são também vistas como contratos, pois qualquer classe que implementar a interface serão obrigadas a implementar seus métodos.
    • Interfaces podem ser implementadas por qualquer classe, de qualquer lugar ou hierarquia. Isso nos permite mudar radicalmente a característica de diferentes classes dando a elas a mesma característica.
  • 121. Interfaces
  • 122. Interfaces, exemplo
    • package br.com.jetsoftware.domain;
    • import java.util.Date;
    • public interface IContratoFinanceiro {
    • double calcularBalanco();
    • double calcularHistorico(Date dataInicial, Date dataFinal);
    • double saldoMensal(int mes, int ano);
    • }
  • 123. Interfaces, exemplo
    • package br.com.jetsoftware.domain;
    • import java.util.Date;
    • public class Caixa implements IContratoFinanceiro {
    • public double calcularBalanco() {
    • //seus cálculos
    • return 2;
    • }
    • public double calcularHistorico(Date dataInicial, Date dataFinal) {
    • //seus cálculos
    • if (dataFinal.getTime() < dataInicial.getTime()) {
    • return 0;
    • }
    • return 55.3;
    • }
    • public double saldoMensal(int mes, int ano) {
    • //seus cálculos
    • return 30;
    • }
    • }
  • 124. Interfaces, exemplo
    • package br.com.jetsoftware.domain;
    • import java.util.Date;
    • public class ContratoFinanceiro implements IContratoFinanceiro {
    • public double calcularBalanco() {
    • //seus cálculos
    • return 7;
    • }
    • public double calcularHistorico(Date dataInicial, Date dataFinal) {
    • //seus cálculos
    • return 99.4;
    • }
    • public double saldoMensal(int mes, int ano) {
    • //seus cálculos
    • return 652.478;
    • }
    • }
  • 125. Interfaces
    • Interfaces podem ser vistas como classes 100% abstratas. Nós dissemos 100% abstratas pois enquanto classes abstratas podem definir métodos abstratos e não abstratos, interfaces por sua vez podem somente definir métodos abstratos.
    • Outra diferença que existe entre interfaces e classes é que interfaces possuem pouca flexibilidade no tocante como métodos e variáveis são definidas.
    • Todos os métodos de uma interface são implicitamente públicos e abstratos. Ou seja, não precisamos digitar as palavras chave public ou abstract, pois os mesmos serão sempre public e abstract.
    • Todas as variáveis dentro de uma interface devem ser public, static, e final, ou seja, interfaces podem declarar somente constantes.
  • 126. Interfaces
    • Métodos de Interfaces não podem ser static.
    • Já que métodos de interfaces são abstratos, eles não podem ser marcados como final, strictfp, or native.
    • Uma interface pode estender ( extends ) uma ou mais interfaces.
    • Uma interface não pode extender nada além de outra interface.
    • Uma interface não pode implementar outra interface ou classe.
    • Uma interface deve ser declarada com a palavra chave interface.
    • Interfaces podem ser usadas de forma polimórfica.
  • 127. Modificadores de acesso para atributos
    • Métodos e variáveis permitem o acesso quase que da mesma forma.
    • Existem 4 tipos de acesso distintos para atributos :
    • Public
    • Protected
    • Default
    • private
  • 128. Modificadores de acesso para atributos
    • Como vimos anteriormente, a proteção default é aquela que recebemos quando não digitamos nenhum modificador de acesso na declaração do membro. Os modificadores default e protected tem quase que o mesmo comportamento, exceto por uma diferença que será mencionada mais a frente.
  • 129. Modificadores de acesso para atributos
    • Public – Todos podem acessar.
    • Private – Só pode ser acessado pela mesma classe na qual o o atributo foi definido.
    • Default – Pode ser acessado se a classe que está tentando acessá-lo estiver dentro do mesmo pacote.
    • Protected – Pode ser acessado por qualquer sub-classe mesmo que estejam em pacotes diferentes.
    • Variáveis locais a um método não podem ter modificadores de acesso. Isto por que elas já são privadas ao método.
  • 130. Encapsulamento
    • Muito importante: conseguimos usar objetos da classe ContaCorrente sem saber nada sobre como a mesma foi implementada!
    • • Isso se chama Ocultação de Informação e é muito importante na
    • programação
    • • É a forma básica de lidar com a complexidade dos programas
    • • É comum usarmos &quot;private&quot; como especificador de controle de acesso para atributos de uma classe
  • 131. Encapsulamento
    • Também podemos dizer que a classe ContaCorrente
    • encapsula dados e comportamento em cima desses dados
    • Os dados são os atributos escondidos de nós (saldo, histórico de transações, dados do titular, etc)
    • • O comportamento são os métodos que podemos chamar para manipular o objeto
    • • Só podemos “alterar&quot; o estado do objeto através de seus métodos.
  • 132. Overloading e Redefinição
    • Em Java, o que identifica unicamente o método é o nome e a lista
    • de argumentos.
    • A técnica de definir métodos de mesmo nome, com listas de
    • argumentos diferentes é chamado de &quot; method overloading &quot; .
    • Quando uma classe B define um método usando o mesmo nome,
    • tipo de retorno e argumentos de um método de uma classe
    • ancestral A , este método redefine o método da classe ancestral.
  • 133. Overloading e Redefinição
    • public class ContaCorrente {
    • public ContaCorrente ( String t, String c, int n ) {
    • numero = n;
    • titular = new Titular ( t, c );
    • }
    • public ContaCorrente ( Titular t, int n ) {
    • numero = n;
    • titular = t;
    • }
    • }
  • 134. Overloading e Redefinição
    • public class Animal {
    • public void comer() {
    • System.out.println(&quot;Eu como de forma genérica !&quot;);
    • }
    • public void respirar() {
    • System.out.println(&quot;Eu respiro de forma genérica !&quot;);
    • }
    • }
  • 135. Overloading e Redefinição
    • class Cao extends Animal {
    • public void comer() {
    • System.out.println(&quot;Eu com o foçinho enfiado na minha tijela.&quot;);
    • }
    • public void respirar() {
    • System.out.println(&quot;Eu respiro pelos pulmoões e somente fora da agua.&quot;);
    • }
    • }
  • 136. Overloading e Redefinição
    • class SerHumano extends Animal {
    • public void comer() {
    • System.out.println(&quot;Eu como sentado na mesa, com garfo e faca.&quot;);
    • }
    • public void respirar() {
    • System.out.println(&quot;Eu respiro pelos pulmoões e somente fora da agua.&quot;);
    • }
    • }
  • 137. Visibilidade de membros Visibilidade Public Protected Default Private De dentro da mesma classe Sim Sim Sim Sim De qualquer classe dentro do mesmo pacote Sim Sim Sim Não De uma sub-classe dentro do mesmo pacote Sim Sim Sim Não De uma sub-classe fora do pacote Sim Sim, por herança Não Não De qualquer não sub-classe fora do pacote Sim Não Não Não
  • 138. Polimorfismo
    • A palavra &quot;polimorfismo&quot; significa &quot;Que apresenta várias formas“
    • Numa linguagem de programação, o polimorfismo permite tratar objetos de classes diferentes do mesmo jeito (com as mesmas chamadas a métodos), porque elas têm o mesmo comportamento
    • As classes fazem a mesma operação (método), mas de forma
    • diferente
    • – &quot;O quê&quot; é igual
    • – &quot;Como&quot; é diferente
  • 139. Polimorfismo
    • public static void main(String[] args) {
    • Animal a1 = new Cao();
    • Animal b1 = new SerHumano();
    • a1.comer();
    • b1.comer();
    • }
    • Eu com o foçinho enfiado na minha tijela.
    • Eu como sentado na mesa, com garfo e faca.
  • 140. Exercícios
  • 141. Exercícios
    • Pense sobre a implementação do seguinte programa,
    • dado em pseudo-código
    • Programa de Controle Bancácio
    • 1. Abra uma conta de número 1 para João com CPF
    • 309140605-06. Nesta conta, deposite R$1000,00.
    • 2. Abra uma conta de número 2 para Ana com CPF
    • 123456789-01. Transfira R$400,00 da conta de João para a conta de
    • Ana.
    • 3. Imprima o saldo da conta de João.
    • 4. Imprima o saldo da conta de Ana.
  • 142. Exercícios
    • Quais as classes que podemos identificar neste
    • exemplo?
    • • Quais são os atributos relevantes para o nosso modelo
    • do mundo real?
    • • Quais os comportamentos devem ser modelados?
  • 143. Controle de Fluxo Capítulo 4
  • 144. Controle de fluxo
    • É impossível imaginarmos algum programa que não precise executar nenhum código condicional !
    • O controle de fluxo é uma parte chave que qualquer linguagem tem, e o Java por sua vez oferece várias formas de fazer isto.
    • Temos declarações de “if”, “for” para loops e muito mais.
  • 145. Controle de fluxo
    • As declarações “if” e “switch” são tipo de controles condição/decisão que permite aos nossos programas se comportarem diferentemente em uma “encruzilhada”, dependendo do resultado do teste lógico.
    • O Java também provê três declarações de loop diferentes ( for, while e do ).
    • As exceptions por sua vez não dão uma forma elegante de tratarmos error de run-time.
    • Temos ainda as assertions, que foram adicionados na versão 1.4 do Java, que nos permite debugarmos e checarmos condições durante nossos testes.
  • 146. IF
    • A forma mais básica de “IF” é :
    • if (booleanExpression) {
    • System.out.println(&quot;Inside if statement&quot;);
    • }
    • Onde a expressão deve ser verdadeira para que o código entre as chaves seja executado.
  • 147. IF / ELSE
    • if (x > 3) {
    • System.out.println(&quot;x é maior que 3&quot;);
    • } else {
    • System.out.println(&quot;x não é maior que 3&quot;);
    • }
  • 148. Else opcional
    • if (x > 3) {
    • y = 2;
    • }
    • z += 8;
    • a = y + x;
  • 149. Prática ruim
    • if (x > 3) // horroroso !
    • y = 2;
    • z += 8;
    • a = y + x;
  • 150. Aninhando IF/ELSE
    • if (price < 300) {
    • buyProduct();
    • } else {
    • if (price < 400) {
    • getApproval();
    • } else {
    • dontBuyProduct();
    • }
    • }
  • 151. Aninhando IF/ELSE (re-escrevendo)
    • if (price < 300) {
    • buyProduct();
    • } else if (price < 400) {
    • getApproval();
    • } else {
    • dontBuyProduct();
    • }
  • 152. Switch
    • Um switch é uma forma de simular vários
    • “ ifs” de uma só vez.
  • 153. Switch, exemplo
    • int x = 3;
    • if(x == 1) {
    • System.out.println(&quot;x equals 1&quot;);
    • } else if(x == 2) {
    • System.out.println(&quot;x equals 2&quot;);
    • } else if(x == 3) {
    • System.out.println(&quot;x equals 3&quot;);
    • } else {
    • System.out.println(&quot;No idea what x is&quot;);
    • }
  • 154. Switch, exemplo ( código mais limpo )
    • int x = 3;
    • switch (x) {
    • case 1:
    • System.out.println(&quot;x is equal to 1&quot;);
    • break;
    • case 2:
    • System.out.println(&quot;x is equal to 2&quot;);
    • break;
    • case 3:
    • System.out.println(&quot;x is equal to 3&quot;);
    • break;
    • default:
    • System.out.println(&quot;Still no idea what x is&quot;);
    • }
  • 155. Expressão legal para switch/case
    • switch (expression) {
    • case constant1: code block
    • case constant2: code block
    • default: code block
    • }
  • 156. Switch/case, break
    • O break não é obrigatório na construção do switch, mas se não utilizarmos um break e a expressão for avaliada pare true, então o Java continuará avaliando as próximas expressões.
  • 157. Switch/case, break
    • int a = 10;
    • switch (a) {
    • case 10: System.out.println(&quot;O valor é 10 !&quot;);
    • case 20: System.out.println(&quot;O valor é 20 !&quot;);
    • case 30: System.out.println(&quot;O valor é 30 !&quot;);
    • default: System.out.println(&quot;Nada feito,
    • é default mesmo !&quot;);
    • }
    • Resultado trágico :
    • ==============
    • O valor é 10 !
    • O valor é 20 !
    • O valor é 30 !
    • Nada feito, é default mesmo !
  • 158. Loops ( while )
    • O loop “while” é utilizado em cenários onde não sabemos quantas vezes a declaração
    • será repetida, então continuaremos no loop enquanto a condição for verdadeira. A expressão utilizada
    • deverá sempre ser uma expressão lógica, ou seja, retornar true ou false !
    • while (expression) {
    • // do stuff
    • }
    • Ou ainda :
    • int x = 2;
    • while(x == 2) {
    • System.out.println(x);
    • ++x;
    • }
  • 159. Loops (do ... While)
    • do {
    • System.out.println(&quot;Inside loop&quot;);
    • }
    • A declaração do/while é diferente de while, pois a expressão interna será executada antes da checagem.
  • 160. Loops ( for )
    • A declaração for nos permite declarar uma ou mais variáveis do mesmo tipo dentro dos parênteses depois da declaração for, se declarmos mais de uma variável, então necessitamos delimitá-las por vírgula :
    • for (int x = 10, y = 3; y > 3; y++) { }
  • 161. I/O Capítulo 5
  • 162. Introdução
    • I/O fornece comunicação com dispositivos
    • – arquivos, console, networks, etc.
    • • Onde o acesso aos dados podem ser:
    • – sequenciais, aleatório, binário, caracteres, linhas,
    • blocos, objetos, etc.
  • 163. I/O Streams
    • I/O Stream representam uma fonte de input e um destino de output. Uma stream pode representar diferentes tipos de fontes e destinos, incluindo arquivos no disco, dispositivos, outros programas e arrays em memória.
    • Streams suportam diferentes tipos de dados, incluindo simples bytes, tipos primitivos, caracteres de localização, e objetos. Algumas streams simplesmente passam dados, outras manipulam e transformam os dados de maneira útil.
    • Não importa muito como elas trabalham internamente, todas streams representam o mesmo modelo simples de programação : Uma stream é uma sequencia de dados.
    • Um programa usa uma input stream para ler dados de uma origem para um destino, um item por vez.
  • 164. I/O Streams
    • Lendo a informação para um programa :
  • 165. I/O Streams
    • Um programa usa uma output stream para escrever dados para um destino, um item por vez :
  • 166.
    • I/O Streams
    I/O Streams
  • 167. Byte Streams
    • Os programas usam byte streams para input e output de bytes de 8 bits. Todas as classes de byte stream são descendentes de InputStream e OutputStream.
    • Existem muitas classes byte stream, e para demonstrarmos como os byte stream trabalham, iremos utilizar o file I/O byte stream ; FileInputStream e FileOutputStream.
  • 168. Usando um Byte Stream
    • import java.io.FileInputStream;
    • import java.io.FileOutputStream;
    • import java.io.IOException;
    • public class CopyBytes {
    • public static void main(String[] args) throws IOException {
    • FileInputStream in = null;
    • FileOutputStream out = null;
    • try {
    • in = new FileInputStream(&quot;xanadu.txt&quot;);
    • out = new FileOutputStream(&quot;outagain.txt&quot;);
    • int c;
    • while ((c = in.read()) != -1) {
    • out.write(c);
    • }
    • } finally {
    • if (in != null) {
    • in.close();
    • }
    • if (out != null) {
    • out.close();
    • }
    • }
    • }
    • }
  • 169. Usando um Byte Stream
    • O programa CopyBytes lê o conteúdo do arquivo dentro de um loop e escreve para uma output stream, um byte de cada vez.
  • 170. Usando um Byte Stream
    • O método read retorna um int, isto para nos permitir usar o resultado -1 para sabermos que o programa atingiu o fim da stream.
    • Sempre fecha streams, isto é muito importante, pois esta prática garante que não ficaremos com recursos presos sem necessidade.
    • Byte Streams devem ser utilizadas somente para I/O primitivos.
  • 171. Character Streams
    • O Java armazena caracteres usando convenção Unicode. Stream de caracteres para I/O são traduzidas automáticamente de e para o conjunto de caracteres locais.
    • Para a maioria das aplicações, I/O com caracteres é tão simples quanto com byte streams. O input e output é feito com classes de stream que fazem a tradução automética de conjuntos de caracteres.
    • Um programa que usa streams de caracteres no lugar de byte streams adapta-se automáticamente aos caracteres locais e está pronta para internacionalização ( sem trabalho extra).
  • 172. Usando Character Streams
    • Todas as streams de caractere são descendentes de Reader e Writer. Como acontece com byte streams, existem character streams que são especializadas para fazer I/O:
    • FileReader e FileWriter
  • 173. Usando Character Streams
    • import java.io.FileReader;
    • import java.io.FileWriter;
    • import java.io.IOException;
    • public class CopyCharacters {
    • public static void main(String[] args) throws IOException {
    • FileReader inputStream = null;
    • FileWriter outputStream = null;
    • try {
    • inputStream = new FileReader(&quot;xanadu.txt&quot;);
    • outputStream = new FileWriter(&quot;characteroutput.txt&quot;);
    • int c;
    • while ((c = inputStream.read()) != -1) {
    • outputStream.write(c);
    • }
    • } finally {
    • if (inputStream != null) {
    • inputStream.close();
    • }
    • if (outputStream != null) {
    • outputStream.close();
    • }
    • }
    • }
    • }
  • 174. Usando Character Streams
    • O programa CopyCharacters é muito semelhante ao CopyBytes. A grande diferença é que CopyCharacters usa FileReader e FileWriter para input e output no lugar de FileInputStream e FileOutputStream.
  • 175. Streams de caracteres que usam Byte Streams
    • Existe também a possibilidade de fazer “wrapper” para byte streams. A stream de caracteres usa uma byte stream para executar o I/O físico, enquanto a stream de caracteres trata a tradução entre os caracteres e bytes.
    • FileReader por exemplo usa FileInputStream, enquanto FileWriter usa FileOutputStream.
  • 176. I/O em linhas inteiras
    • I/O com caracteres geralmente é utilizado com conjuntos maiores do que com caracteres únicos. Um conjunto comum é uma linha, que são vários caracteres agrupados com um terminador de linha no final.
    • Um terminador de linha pode ser um carriage-return/line-feed (“ ”), carriage-return (“ ”), ou line-feed (“ ”).
  • 177. I/O em linhas inteiras
    • Modificaremos o nosso exemplo anterior, afim de torná-lo um I/O orientado a linhas. Usaremos também duas novas classes, BufferedReader e PrintWriter.
  • 178. I/O em linhas inteiras
    • import java.io.FileReader;
    • import java.io.FileWriter;
    • import java.io.BufferedReader;
    • import java.io.PrintWriter;
    • import java.io.IOException;
    • public class CopyLines {
    • public static void main(String[] args) throws IOException {
    • BufferedReader inputStream = null;
    • PrintWriter outputStream = null;
    • try {
    • inputStream = new BufferedReader(new FileReader(&quot;xanadu.txt&quot;));
    • outputStream = new PrintWriter(new FileWriter(&quot;characteroutput.txt&quot;));
  • 179. I/O em linhas inteiras
    • String l;
    • while ((l = inputStream.readLine()) != null) {
    • outputStream.println(l);
    • }
    • } finally {
    • if (inputStream != null) {
    • inputStream.close();
    • }
    • if (outputStream != null) {
    • outputStream.close();
    • }
    • }
    • }
    • }
  • 180. Buffered Streams
    • Os exemplos anteriores que utilizamos são do tipo unbuffered . Ou seja, toda leitura ou escrita é tratada diretamente pelo sistema operacional. Isto pode fazer com que o programa seja menos eficiente, visto que toda requisição desencadeia acesso ao disco, rede ou qualquer outra ação que seja cara.
    • Para reduzir este tipo de sobrecarga, a plataforma Java implementa o I/O buferizado. Input streams buferizadas lêem dados da memória de uma área conhecida como buffer, a API nativa é invocada somente quando o buffer estiver vazio. Da mesma forma output streams escrevem dados para um buffer, e a API nativa é invocada somente quando o buffer estiver cheio.
    • Um programa pode converter uma stream não buferizada para uma buferizada, usando wrappers, onde passamos o objeto não buferizado para o construtor de uma stream buferizada.
  • 181. Buffered Streams
    • inputStream = new BufferedReader(new FileReader(&quot;xanadu.txt&quot;));
    • outputStream = new BufferedWriter(new FileWriter(&quot;characteroutput.txt&quot;));
    • Existem quatro classes de stream buferizadas para fazermos wrapper de streams não buferizadas : BufferedInputStreame BufferedOutputStream criam bute streams buferizados, enquanto BufferedReader e BufferedWriter criam streams de caracteres buferizados.
  • 182. Descarregando Buffered Streams
    • Devemos escrever os dados do buffer de tempos em tempos, pois é exatamente isso que queremos, escrever os dados em um meio persistente. Esta ação é conhecida como flushing o buffer.
    • Algumas classes de output buferizadas suportam autoflush , especificado por um argumento opicional no construtor. Quando o autoflush está ligado, alguns eventos causam o descarregamento do buffer ( flush ).
    • Por exemplo, um autoflush em objetos PrintWriter acontecem em cada invocação do método println ou format.
    • Para realizar o flush na stream de forma manual, basta usar o método flush.
  • 183. Escaneando e formatando
    • Input e Output as vezes envolvem a tradução de formatos estranhos para formato humano. Para a realização desta tarefa o Java provê duas APIs.
    • A API scanner quebra o input em tokens individuais associados com bits de dados.
    • A API formatting monta os dados em formato bem formatado pronto para a leitura humana.
  • 184. Escaneando e formatando
    • import java.io.*;
    • import java.util.Scanner;
    • public class ScanXan {
    • public static void main(String[] args) throws IOException {
    • Scanner s = null;
    • try {
    • s = new Scanner(new BufferedReader(new FileReader(&quot;xanadu.txt&quot;)));
    • while (s.hasNext()) {
    • System.out.println(s.next());
    • }
    • } finally {
    • if (s != null) {
    • s.close();
    • }
    • }
    • }
    • }
  • 185. Escaneando e formatando
    • In
    • Xanadu
    • did
    • Kubla
    • Khan
    • A
    • stately
    • pleasure-dome
    • ...
    • Usando um token diferente :
    • s.useDelimiter(&quot;,*&quot;)
  • 186. Traduzindo tokens individuais
    • A classe Scanner suporta todos os tipos primitivos do Java ( com exceção de char ), e também BigInteger e BigDecimal. Também valores numéricos podem usar diferentes separadores.
  • 187. Traduzindo tokens individuais
    • import java.io.FileReader;
    • import java.io.BufferedReader;
    • import java.io.IOException;
    • import java.util.Scanner;
    • import java.util.Locale;
    • public class ScanSum {
    • public static void main(String[] args) throws IOException {
    • Scanner s = null;
    • double sum = 0;
    • try {
    • s = new Scanner(new BufferedReader(new FileReader(&quot;usnumbers.txt&quot;)));
    • s.useLocale(Locale.US);
    • while (s.hasNext()) {
    • if (s.hasNextDouble()) {
    • sum += s.nextDouble();
    • } else {
    • s.next();
    • }
    • }
    • } finally {
    • s.close();
    • }
    • System.out.println(sum);
    • }
    • }
  • 188. Traduzindo tokens individuais
    • Arquivo de exemplo :
    • numeros.txt
    • 8.2 32,767
    • 3.34159
    • 1,100,000.1
  • 189. Formatação
    • Stream de objetos que implementam formatação são instâncias de PrintWriter (stream de caracter), ou PrintStream (classe de byte stream).
    • Como todos os objetos de streams de bytes ou caracteres, instâncias de PrintStream e PrintWriter implementam o conjunto padrão de métodos write para output de byte ou caractere. Em adição, ambos PrintStream e PrintWriter implementam o mesmo conjunto de métodos para conversão de dados interno para output formatado. Onde dois níveis de formatação são providos :
    • print e println formatam valores individuais numa maneira padrão
    • format formata quase qualquer valor numérico baseado em uma string de formatação, com várias opções de formatação.
  • 190. Formatação
    • public class Root {
    • public static void main(String[] args) {
    • int i = 2;
    • double r = Math.sqrt(i);
    • System.out.print(“A raiz quadrada de &quot;);
    • System.out.print(i);
    • System.out.print(&quot; é &quot;);
    • System.out.print(r);
    • System.out.println(&quot;.&quot;);
    • i = 5;
    • r = Math.sqrt(i);
    • System.out.println(&quot; A raiz quadrada de &quot; + i + &quot; é &quot; + r + &quot;.&quot;);
    • }
    • }
    • A raiz quadrada de 2 é 1.4142135623730951.
    • A raiz quadrada de 5 é 2.23606797749979.
  • 191. O método format
    • O método format formata múltiplos argumentos baseado em uma string.
    • public class Root2 {
    • public static void main(String[] args) {
    • int i = 2; double r = Math.sqrt(i); System.out.format(&quot;The square root of %d is %f.%n&quot;,
    • i, r);
    • }
    • }
  • 192. O método format
    • Como usado no exemplo anterior, todos os formatadores começam com um % e terminam em 1 ou 2 caracteres que especificam o tipo de output formatado.
    • d – formata um valor inteiro como decimal
    • f - formata um valor ponto flutuante como decimal
    • n – gera um delimidador que é específico de uma plataforma
    • x – formata um inteiro como hexadecimal
    • s - formata qualquer valor como string
    • tB – formata um inteiro como um “local-specific” nome de mês
  • 193. O método format
    • public class Format {
    • public static void main(String[] args) {
    • System.out.format(&quot;%f, %1$+020.10f %n&quot;, Math.PI);
    • }
    • }
    • Resultado :
    • 3.141593, +00000003.1415926536
  • 194. O método format
    • Os elementos adicionais de nossa formatação são todos opcionais.
    • Precision – para pontos flutuantes é a precisão do valor formatado ( pode ser truncado).
    • Width – o tamanho mínimo do valor formatado.
    • Flags – especifica formatação adicional, neste caso o número será sempre exibido com o sinal +
    • Argument Index – nos permite explicitamente encontrarmos um determinado argumento.
  • 195. I/O na linha de comandos
    • Um programa também pode rodar na linha de comandos para interagir com o usuário final. O Java suporta este tipo de interação atráves do Console.
    • Uma alternativa avançada as streams é o Console. Este objeto possui a maior parte das features disponíveis pelas stream standard, e outros objetos. O console é bem interessante para entradas de senha. Este objeto também provê input e output de streams que são streams de caracteres, através de seus métodos reader e writer.
    • Antes de um programa poder usar o Console, o mesmo deve tentar recuperar este objeto invocando o método System.console(). Se o objeto Console estiver disponível este método o retornará, senão o mesmo retornará NULL, e então a interação com o console não será possível, pois o sistema operacional não suporta esta operação, ou o programa foi executado em um ambiente não interativo.
  • 196.
    • import java.io.Console;
    • import java.util.Arrays;
    • import java.io.IOException;
    • public class PegaSenha {
    • public static void main (String args[]) throws IOException {
    • Console c = System.console();
    • if (c == null) {
    • System.err.println(&quot;Sem console.&quot;);
    • System.exit(1);
    • }
    • String login = c.readLine(&quot;Digite seu login: &quot;);
    • char [] oldPassword = c.readPassword(&quot;Digite sua senha : &quot;);
  • 197.
    • if (verify(login, oldPassword)) {
    • boolean noMatch;
    • do {
    • char [] newPassword1 =
    • c.readPassword(&quot;Digite sua senha: &quot;);
    • char [] newPassword2 =
    • c.readPassword(&quot;Digite sua senha: &quot;);
    • noMatch = ! Arrays.equals(newPassword1, newPassword2);
    • if (noMatch) {
    • c.format(&quot;A senha não confere. Tente de novo.%n&quot;);
    • } else {
    • change(login, newPassword1);
    • c.format(&quot;Senha de %s modificada.%n&quot;, login);
    • }
    • Arrays.fill(newPassword1, ' ');
    • Arrays.fill(newPassword2, ' ');
    • } while (noMatch);
    • }
  • 198.
    • Arrays.fill(oldPassword, ' ');
    • }
    • //Método fictício
    • static boolean verify(String login, char[] password) {
    • return true;
    • }
    • //Método fictício
    • static void change(String login, char[] password) {}
    • }
  • 199. Data Streams
    • Data streams suportam I/O binário de tipos primitivos (boolean, char, byte, short, int, long, float, and double) e também Strings.
    • Todos os data stream implementam as interfaces DataInput ou DataOutput. Conheceremos também suas famosas implementações, DataInputStream e DataOutputStream.
  • 200. Data Streams ( output )
    • import java.io.BufferedOutputStream;
    • import java.io.DataOutputStream;
    • import java.io.FileNotFoundException;
    • import java.io.FileOutputStream;
    • import java.io.IOException;
    • public class UseOutputDataStream {
    • static final String dataFile = &quot;pedido&quot;;
    • static final double[] prices = { 19.99, 9.99, 15.99, 3.99, 4.99 };
    • static final int[] units = { 12, 8, 13, 29, 50 };
    • static final String[] descs = { &quot;Camisa do Java&quot;,
    • &quot;Chaveiro do Java&quot;,
    • &quot;Disquete&quot;,
    • &quot;Pen Drive&quot;,
    • &quot;Boné&quot; };
  • 201. Data Streams ( output )
    • public static void main(String[] args) throws FileNotFoundException, IOException {
    • DataOutputStream out = new DataOutputStream(new
    • BufferedOutputStream(new FileOutputStream(dataFile)));
    • //Escrevendo para a stream
    • for (int i = 0; i < prices.length; i ++) {
    • out.writeDouble(prices[i]);
    • out.writeInt(units[i]);
    • out.writeUTF(descs[i]);
    • }
    • }
    • }
  • 202. Data Streams ( input )
    • import java.io.BufferedInputStream;
    • import java.io.DataInputStream;
    • import java.io.EOFException;
    • import java.io.FileInputStream;
    • import java.io.FileNotFoundException;
    • import java.io.IOException;
    • public class UseInputDataStream {
    • static final String dataFile = &quot;pedido&quot;;
    • public static void main(String[] args) throws FileNotFoundException, IOException {
    • DataInputStream in = new DataInputStream(new
    • BufferedInputStream(new FileInputStream(dataFile)));
    • double price;
    • int unit;
    • String desc;
    • double total = 0.0;
  • 203. Data Streams ( output )
    • //Lendo do arquivo
    • try {
    • while (true) {
    • price = in.readDouble();
    • unit = in.readInt();
    • desc = in.readUTF();
    • System.out.format(&quot;You ordered %d units of %s at $%.2f%n&quot;,
    • unit, desc, price);
    • total += unit * price;
    • }
    • } catch (EOFException e) {
    • }
    • System.out.println(&quot;Total = &quot; + total);
    • }
    • }
    • Nota : DataStreams detectam o fim de arquivo capturando EOFException, ao invés de testarem um valor de retorno. E todas implementações de métodos de DataInput usam EOFException como retorno.
  • 204. Object Streams
    • Da mesma forma que streams suportam serialização de primitivos, elas também suportam I/O para objetos. Várias, mas nem todas as classes standard suportam serialização para seus objetos. Estas mesmas devem implementar a interface Serializable.
    • As classes de object stream são ObjectInputStream e ObjectOutputStream. Essas classes implementam ObjectInput e ObjectOutput, que são sub-interfaces de DataInput e DataOutput. Isso significa que todos os métodos de I/O para dados primitivos cobertos em Data Streams são também implementados em streams de objetos.
    • Se o método readObject() não retornar o tipo de objeto esperado, e ouver uma tentativa de cast para o tipo corredo, então a exception ClassNotFoundException poderá ser lançada.
  • 205. Output e Input de objetos complexos
    • Os métodos writeObject e readObject são muito simples de usar, mas eles contém uma lógica muito sofisticada de gerenciamento de objetos. Muitos objetos contém referências para outros objetos. Se readObject precisa reconstruir um objeto de uma stream, então o mesmo tem que reconstruir TODOS os objetos do grafo.
    • Estes objetos adicionais podem ter suas próprias referências, que também deverão ser resolvidas e etc.
    • Uma única invocação de writeObject pode causar que um grande número de objetos sejam escritos para a stream.
  • 206. Grafo de objetos
  • 207. Object Streams
    • Se dois objetos dentro da mesma stream contiverem referência para um mesmo objeto, então eles irão referenciar um único objeto quando eles forem reconstruídos.
    • Pois uma stream pode conter somente uma cópia de um objeto, apesar de poder conter um número infinito de referencias ao mesmo.
    • Se escrevermos um objeto para uma stream duas vezes, então nós realmente estaremos escrevendo somente a referência duas vezes.
  • 208. Object Streams
    • Object ob = new Object();
    • out.writeObject(ob);
    • out.writeObject(ob);
    • Mas, se um único objeto for escrito para duas streams diferentes, então o mesmo será efetivamente duplicado.
  • 209. Arquivos
    • Mantivemos o foco de nossa discussão nas streams, que nos dão um modelo simples de leitura e escrita de dados. Streams trabalham com uma grande variedade de fontes de dados e destinos, incluindo arquivos no disco. Mas, streams não suportam todas as operações que são comuns com arquivos em disco, e é onde veremos dois conceitos não-stream :
    • File
    • Random Access File
  • 210. File Objects
    • A classe File nos torna muito fácil escrever código independente de plataforma que examina e manipula arquivos.
    • O nome desta classe é um pouco confuso, pois instâncias de Files representam nomes de arquivos e não arquivos propriamente ditos, e o arquivo correspondente ao nome pode mesmo nem existir.
  • 211. Capturando as propriedades de um arquivo
    • import java.io.File;
    • import java.io.IOException;
    • import static java.lang.System.out;
    • public class FileStuff {
    • public static void main(String args[]) throws IOException {
    • out.print(&quot;File system roots: &quot;);
    • for (File root : File.listRoots()) {
    • out.format(&quot;%s &quot;, root);
    • }
    • out.println();
    • for (String fileName : args) {
    • out.format(&quot;%n------%nnew File(%s)%n&quot;, fileName);
    • File f = new File(fileName);
    • out.format(&quot;toString(): %s%n&quot;, f);
    • out.format(&quot;exists(): %b%n&quot;, f.exists());
    • out.format(&quot;lastModified(): %tc%n&quot;, f.lastModified());
  • 212. Capturando as propriedades de um arquivo
    • out.format(&quot;isFile(): %b%n&quot;, f.isFile());
    • out.format(&quot;isDirectory(): %b%n&quot;, f.isDirectory());
    • out.format(&quot;isHidden(): %b%n&quot;, f.isHidden());
    • out.format(&quot;canRead(): %b%n&quot;, f.canRead());
    • out.format(&quot;canWrite(): %b%n&quot;, f.canWrite());
    • out.format(&quot;canExecute(): %b%n&quot;, f.canExecute());
    • out.format(&quot;isAbsolute(): %b%n&quot;, f.isAbsolute());
    • out.format(&quot;length(): %d%n&quot;, f.length());
    • out.format(&quot;getName(): %s%n&quot;, f.getName());
    • out.format(&quot;getPath(): %s%n&quot;, f.getPath());
    • out.format(&quot;getAbsolutePath(): %s%n&quot;, f.getAbsolutePath());
    • out.format(&quot;getCanonicalPath(): %s%n&quot;, f.getCanonicalPath());
    • out.format(&quot;getParent(): %s%n&quot;, f.getParent());
    • out.format(&quot;toURI: %s%n&quot;, f.toURI());
    • }
    • }
    • }
  • 213. Random Access File
    • Random acess files permitem o acesso aleatório ao conteúdo de um arquivo.
    • new RandomAccessFile(&quot;xanadu.txt&quot;, &quot;r&quot;);
    • new RandomAccessFile(&quot;xanadu.txt&quot;, &quot;rw&quot;);
    • int skipBytes(int) — Move o ponteiro do arquivo para a frente com o número de bytes especificado.
    • void seek(long) — Posiciona o pointeiro antes do byte especificado.
    • long getFilePointer() — Retorna o a localização corrente do byte.
  • 214. Exceções Capítulo 6
  • 215. O que é uma exception ?
    • O termo exception vem da frase “exceptional event”.
    • Uma exception é um evento, que por sua vez ocorre durante a execução de um programa, que “bagunça” o fluxo normal do mesmo.
    • Quando um erro ocorre dentro de um método, o método cria um objeto e o entrega ao sistema de runtime. O objeto é chamado de objeto de exceção, e contém informações sobre o erro, incluindo o seu tipo e estado do programa quando o erro aconteceu. A criação de objetos de exceção e a entrega deles ao sistema de runtime é chamado de “ throwing an exception ”, ou lançamento de exceções.
    • Após um método lançar uma exceção, o sistema de runtime tenta encontrar alguém para tratar a mesma. O conjunto possível de candidatos a tratar a exceção é a lista ordenada de métodos que foram invocados até chegar ao método que lançou a exceção. Esta lista é denominada call stack .
  • 216. Call Stack
  • 217. Tratamento de exceção
    • O sistema de runtime procura o call stack por um método que contém um bloco de código que possa tratar a exceção. Este bloco de código é denominado exception handler . A busca inicia-se com no método onde o erro ocorreu e segue através da call stack em ordem reversa que os métodos foram invocados.
    • Quando um handler apropriado é encontrado, o sistema de runtime passa a exceção para o handler.
    • Um exception handler é considerado apropriado se o tipo de objeto de exceção lançado é do mesmo tipo tratado pelo handler.
    • O exception handler escolhido catch the exception , ou a caputra. Se o sistema de runtime procura em toda call stack e não consegue achar um handler, enão o sistema de runtime ( e o programa ) terminarão.
  • 218. Tratamento de exceção
  • 219. Capturando e tratando exceções
    • Um código Java válido para tratar exceções deve :
    • Usar uma declaração try para capturar a exceção, e o mesmo deve prover um tratador para esta exception.
    • Ou
    • O método deve especificar que o mesmo lança a exception, onde o método deve também declarar a cláusula throws .
  • 220. Três tipos de exceção
    • O primeiro tipo de exception as chamadas checked exeption . Estas exceptions são detectadas pelo compilador Java, e temos como exemplos :
      • java.io.FileNotFoundException
    • O segundo tipo de exception é o tipo error . Esta exception é ocasionada por algo externo a aplicação, e a aplicação geralmente não consegue antecipar-se a este tipo de exceção. Podemos usar como exemplo a abertura de um arquivo, pois podemos conseguir abrir o mesmo, mas na hora de gravarmos recebemos um erro por conta de uma falha de hardware que nos impediu de gravarmos o arquivo, exemplo :
      • java.io.IOErro
    • O terceiro tipo de exception são as runtime exceptions , que são internas a aplicação, mas a mesma não consegue se prevenir da mesma. Este tipo geralmente aponta para bugs, tais como error de lógica ou mal uso da API, exemplo :
      • NullPointerException
  • 221. Capturando e tratando exceções
    • public class Numeros {
    • public static void main(String []args) {
    • int[] a = new int[5];
    • a[0] = 5;
    • a[1] = 3;
    • a[2] = 6;
    • a[3] = 9;
    • a[4] = 88;
    • for (int i = 0; i < 6; i++) {
    • int j = a[i];
    • }
    • }
    • }
    • Exception in thread &quot;main&quot; java.lang.ArrayIndexOutOfBoundsException: 5
    • at Numeros.main(Numeros.java:13)
  • 222. O bloco try
    • A primeira coisa que devemos fazer para tratarmos um código de lança uma exceção é colocá-la em um bloco try :
    • try {
    • //codigo aqui
    • }
    • catch...
  • 223. O bloco try / catch
    • Nós criamos tratadores combinando blocos try e catch, onde cada catch será um tratador para uma excepção diferente :
    • import java.io.File;
    • import java.io.FileNotFoundException;
    • import java.io.IOException;
    • import java.io.PrintWriter;
    • public class OpenFile {
    • public static void main(String[] args) {
    • File f = new File(&quot;MeuArquivo.txt&quot;);
    • PrintWriter out = null;
    • try {
    • out = new PrintWriter(f);
    • } catch (FileNotFoundException ex) {
    • System.out.println(&quot;Não consegui abir o arquivo. &quot; + ex.getMessage());
    • } catch (IOException ex) {
    • System.out.println(&quot;Peguei uma IOException. &quot; + ex.getMessage());
    • }
    • }
    • }
  • 224. O bloco finally
    • O bloco finally sempre é executado quando um try existe. Isto garante que o bloco finally será executado mesmo quando uma exceção inesperada aconteça. Mas o finally é muito útil além de tratar exceções.
    • O finally permite ao programador ter qualquer código de limpeza sendo pulado acidentamente por algum return, continue ou break. Colocar código de limpeza dentro do finally é uma ótima prática.
    • }finally{
    • if (out != null ) {
    • System.out.println(&quot;Fechando o arquivo...&quot;);
    • out.close();
    • }else{
    • System.out.println(&quot;O arquivo não estava aberto !&quot;);
    • }
    • }
  • 225. Especificando exceptions lançadas por um método
    • Vimos anteriormente que podemos tratar as exceptions dentro de nossos próprios métodos, mas existe ainda a opção de deixarmos este tratamento para todo código “cliente” que invocar nosso método. Para isso precisamos adicionar a cláusula throws na assinatura de nosso método, seguido das possíveis exceções que nosso código lançará :
  • 226. Especificando exceptions lançadas por um método
    • import java.io.File;
    • import java.io.FileNotFoundException;
    • import java.io.PrintWriter;
    • class TrataArquivo {
    • public void abreArquivo() throws FileNotFoundException {
    • File f = new File(&quot;MeuArquivo.txt&quot;);
    • PrintWriter out = null;
    • out = new PrintWriter(f);
    • out.println(&quot;ABCDEFGH&quot;);
    • out.close();
    • }
    • }
  • 227. Especificando exceptions lançadas por um método
    • public class OpenFile {
    • public static void main(String[] args) {
    • TrataArquivo ta = new TrataArquivo();
    • try {
    • ta.abreArquivo();
    • } catch (FileNotFoundException ex) {
    • System.out.println(&quot;Não consegui abrir o arquivo...&quot;);
    • }
    • }
    • }
  • 228. Lançando exceções
    • É muito simples lançar exceções, tudo que necessitamos fazer é utilizarmos a cláusula throw dentro do método desejado :
    • throw umObjeto Throwable ;
  • 229. Lançando exceções
    • public class LancandoExceptions {
    • public double calculaPagamento(int mes) throws Exception {
    • if (mes < 1 || mes > 12) {
    • throw new Exception(&quot;Mês inválido !&quot;);
    • }
    • return 99.7;
    • }
    • }
  • 230. A classe Throwable
  • 231. Filhos de Throwable
    • Error – Quando acontece um erro na virtual machine ela lança uma exceção deste tipo. E os programas geralmente não capturam ou lançam este tipo de exceção.
    • Exception – Um objeto deste tipo indica que um problema ocorreu, mas isso não é um problema da VM e sim do programa, e geralmente os programas usam suas próprias exceptions para tratar condições de erro.
    • Podemos usar como exemplos de exceptions :
    • IllegalAccessException – Indica que um método não pode ser encontrado.
    • NegativeArraySizeException – Indica que o programa tentou criar um array com tamanho negativo.
    • A classe RuntimeException é reservada para exceptions que dizem respeito ao uso incorreto da API, e podemos citar como exemplo o NullPointerException, que é a tentativa de operação sobre um objeto nulo.
  • 232. Exceções em cadeia
    • Uma aplicação pode tratar uma exceção simplesmente lançando uma outra exceção. Esta técnica é muito útil, pois podemos capturar uma exceção genérica e transformá-la em outra mais específica :
    • try {
    • } catch (IOException e) {
    • throw new MyException(“Outro Erro&quot;, e) ;
    • }
  • 233. StackTrace
    • O objeto StackTrace é responsável por retornar um texto com a cadeia de métodos invocados até o lançamento da exceção :
    • public static void main(String[] args) {
    • Exception e = new Exception(&quot;Um erro foi gerado por mim !&quot;);
    • e.printStackTrace();
    • }
    • Resultado :
    • java.lang.Exception: Um erro foi gerado por mim !
    • at LancandoExceptions.main(LancandoExceptions.java:13)
  • 234. Criando uma exceção
    • public class MinhaExcecao extends Exception {
    • public MinhaExcecao() {
    • super();
    • }
    • public MinhaExcecao(String message) {
    • super(message);
    • }
    • }
  • 235. Nota sobre unchecked exceptions
    • Muitos programadores sentem-se tentados a escrever código que herdam e lançam somente unchecked exceptions, pois as mesmas não são checadas pelo compilador. Isto é uma péssima prática !
    • Uma exception que pode ser lançada por um método é parte de sua interface pública, e todos que invocam esses métodos devem saber sobre as exceções que o método pode lançar, e então os mesmos podem decidir como tratá-las.
    • Runtime Exceptions representam problemas que são resultado de programação, e o código cliente não é esperado que se recupera deste tipo de erro. Estes erros incluem exceções de aritimética, divisão por zero, null pointer exceptions, exception de índices dentre outros.
    • Regra básica : Se o cliente pode se recuperar da exception, então a exception deve ser checked, caso contrário, ela deve ser unchecked.
  • 236. Exceptions são
    • Uma forma organizada de tratar um evento excepcional que aconteceu durante o fluxo do seu programa.
    • As exceptions eliminam os códigos tipo espaguete ( bacalhau ) da forma tradicional de tratamento de erros.
  • 237. Threads Capítulo 7
  • 238. Concorrência
    • Nós usuários de computadores acreditamos e confiamos que nossos sistemas podem fazer mais de uma coisa ao mesmo tempo. Assumimos que podemos continuar trabalhando no work enquanto fazemos download de músicas, imprimimos algo, copiamos arquivos e etc.
    • Mesmo um simples aplicativo é esperado fazer mais de uma coisa de cada vez.
    • A plataforma Java foi re-estruturada do zero para suportar programação concorrente, com suporte concorrente básico na linguagem java e em suas bibliotecas. Desde a versão 5.0 que a plataforma Java incluiu também a biblioteca de concorrência.
  • 239. Processos e threads
    • Em programação concorrente, existem duas unidades básicas de execução : processos e threads . Em Java a programação concorrente está mais focada em threads. Mas de qualquer forma os processos também são importantes.
    • Um computador normalmente possui vários processos ativos e threads. E isto também é verdadeiro para sistemas que possuem uma única linha de execução, e possui somente uma thread sendo executada naquele momento. Tempo de processamento para um único core é compartilhado entre os processos e threads através de uma feature do SO chamada “time slicing”.
    • Hoje em dia é muito comum que os computadores tenham vários procesadores com vários cores, e isto aumenta em muito a capacidade de execução concorrente de processos e threads. Mas a concorrência também é possível em sistemas simples, onde não existam vários processadores ou cores de execução.
  • 240. Processos
    • Um processo é um ambiente de execução auto-contido. E um processo geralmente tem um conjunto privado e completo de recursos de runtime, e em particular cada processo possui sus própria área de memória.
    • Processos são geralmente vistos como sinônimos de programas ou aplicações, entretanto oque o usuário vê como uma simples aplicação pode ser na realidade um conjunto de processos cooperando. Para facilitar a comunicação entre processos, vários SOs suportam recursos de Inter Process Communication (IPC), tal como pipes ou sockets. IPC não é usado somente para a comunicação entre processos no mesmo sistema, mas processos em diferentes sistemas
    • A grande maioria das implementações da JVM rodam em um único processo. Uma aplicação Java pode criar processos adicionais usando um objeto ProcessBuilder.
  • 241. Processos
  • 242. Threads
    • Threads são também conhecidas como processos leves. Ambos processos e threads provêem um ambiente de execução, mas criar novas threads requer muito menos recursos do que criar novos processos.
    • Threads existem dentro de processos, e cada processo possui pelo menos uma. As threads compartilham os recursos do processo, incluindo memória e arquivos. Isso aumenta em muito a eficiência, mas pode acarretar em uma comunicação problemática.
    • Execução multi-thread é uma feature essencial da plataforma Java. Onde cada aplicação possui pelo menos uma thread, ou várias, se contarmos as threads do sistema que realizam trabalhos como gerenciamento de memória e tratamento de sinais. Mas da perspectiva do programador o programa é iniciado com uma única thread, chamada main thread .
  • 243. Objetos Thread
    • Cada thread é associada com uma instância da classe Thread . E existem duas formas de usarmos o objeto thread :
    • Para controlar a thread diretamente, simplesmente instanciamos uma Thread cada vez q a aplicação precisar realizar alguma tarefa assíncrona.
    • Para abstrair o gerenciamento da thread do resto da aplicação, passamos a tarefa a um executor.
  • 244. Definir e iniciar uma Thread
    • Criar um objeto Runnable. A interface Runnable define um método chamado run, que é esperado conter o código a ser executado em uma thread. O objeto runnable então é passado no construtor da thread para ser executado :
    • public class HelloRunnable implements Runnable {
    • public void run() {
    • System.out.println(&quot;Hello from a thread!&quot;);
    • }
    • public static void main(String args[]) {
    • (new Thread(new HelloRunnable())).start();
    • }
    • }
  • 245. Definir e iniciar uma Thread
    • Criar uma sublasse de Thread. Podemos fazer isso pois a classe Thread também implementa runnable diretamente. Podemos então criar uma subclasse e prover o código para o método run :
    • public class HelloThread extends Thread {
    • public void run() {
    • System.out.println(&quot;Hello from a thread!&quot;);
    • }
    • public static void main(String args[]) {
    • (new HelloThread()).start();
    • }
    • }
  • 246. Dando uma pausa na execução com sleep
    • O método Thread.sleep causa a suspensão da execução da thread corrente por um período específico de tempo. Isto é uma forma eficiente para termos tempo de processamento disponível para outras threads de uma aplicação, ou ainda para outras aplicações rodarem. O método sleep pode também ser usado para marcar o ritmo de execução, como por exemplo aguardar por outra thread.
    • public static native void sleep(long millis) throws InterruptedException;
    • public static void sleep(long millis, int nanos)
    • throws InterruptedException;
  • 247. Exemplo
    • public class SleepMessages {
    • public static void main(String args[]) throws InterruptedException {
    • String importantInfo[] = {
    • &quot;Mares eat oats&quot;,
    • &quot;Does eat oats&quot;,
    • &quot;Little lambs eat ivy&quot;,
    • &quot;A kid will eat ivy too&quot;
    • };
    • for (int i = 0; i < importantInfo.length; i++) {
    • //Pause for 4 seconds
    • Thread.sleep(4000);
    • //Print a message
    • System.out.println(importantInfo[i]);
    • }
    • }
    • }
  • 248. Nota
    • No exemplo anterior vimos que o método main declara uma InterruptedException, que é a exception que o método sleep lança quando outra thread interrompe a thread corrente enquanto o sleep está ativo.
  • 249. Interrupções
    • Uma interrupção é um indicativo que a thread deve de fazer aquilo que estiver fazendo, e fazer alguma outra coisa. É de inteira responsabilidade do programador dizer como a thread responde a uma interrupção, mas é muito comum a thread ser terminada nesses casos.
    • A thread envia uma interrupção invocando o método interrupt no objeto Thread para a thread que será interrompida. E para este mecanismo funcionar direito, a thread interrompida deve suportar sua própria operação.
  • 250. Suportando interrupções
    • A thread suporta interrupções através de vários métodos, podendo lançar a exceção InterruptedException, onde a execução será abortada.
    • for (int i = 0; i < 10; i++) {
    • //Pausa por 4 segundos
    • try {
    • Thread.sleep(4000);
    • } catch (InterruptedException e) {
    • //Exceção capturada, e nada mais a fazer.
    • return;
    • }
    • //Print a message
    • System.out.println(i);
    • }
  • 251. Suportando interrupções
    • Existem vários métodos que lançam InterruptedException, e os mesmos foram configurados para cancelar sua execução corrente e retornar imediatamente qiuando uma interrupção for recebida.
    • public static native void sleep(long millis) throws InterruptedException;
    • public static void sleep(long millis, int nanos) throws InterruptedException {}
    • public final synchronized void join(long millis) throws InterruptedException {}
    • public final synchronized void join(long millis, int nanos) throws InterruptedException {}
    • public final void join() throws InterruptedException {}
  • 252. Sabendo se uma interrupção foi recebida
    • As vezes as threads podem ficar um tempo muito longo sem invocar nenhum método que lança uma InterruptedException, então podemos invocar o método Thread.interrupted para sabermos se uma interrupção foi recebida.
    • if (Thread.interrupted()) {
    • //Interrupção recebida
    • return;
    • }
  • 253. Joins
    • O método join permite uma thread aguardar pelo término do trabalho de outra.
    • minhaThread.join();
    • Causa a interrupção da thread corrente até que minhaThread termine seu trabalho.
  • 254. Exemplo SimpleThreads
    • public class SimpleThreads {
    • }
  • 255. Sincronização
    • Threads comunicam-se primáriamente compartilhando o acesso a campos de objetos que elas referenciam. Esta forma de comunicação é muito eficiente, mas também é refém de dois erros : interferência de thread e erro de inconsistência de memória.
  • 256. Interferência
    • Interferências acontecem quando duas operações, rodando em diferentes threads, mas operando sobre o mesmo dado se intercalam.
    • public class Contador {
    • private int campo = 0;
    • public void incrementa() {
    • campo++;
    • }
    • public void subtrai() {
    • campo--;
    • }
    • public int valorAtual() {
    • return campo;
    • }
    • }
  • 257. Exemplo de interferência
    • Thread 1 pega o contador
    • Thread 2 pega o contador
    • Thread 1 recupera o valor e o incrementa (1)
    • Thread 2 recupera o valor e o decrementa (-1)
    • Thread 1 armazena o valor em c, que agora vale (1)
    • Thread 2 armazena o valor em c, que agora vale (-1)
  • 258. Métodos sincronizados
    • O Java provê duas formas básicas de sincronização : métodos sincronizados e declarações sincronizadas.
    • Para fazer um método se tornar sincronizado, somente precisamos adicionar a palavra chave synchronized em sua declaração.
  • 259. Métodos sincronizados
    • public class ContadorSincronizado {
    • private int c = 0;
    • public synchronized void increment() {
    • c++;
    • }
    • public synchronized void decrement() {
    • c--;
    • }
    • public synchronized int value() {
    • return c;
    • }
    • }
  • 260. Métodos sincronizados
    • Agora que temos um contador sincronizado, temos o seguinte resultado :
    • Não é mais possível termos mais de uma invocação em métodos sincronizados simultâneamente. Quando uma thread está executando um método sincronizado de um objeto, todas as outras thread que invocam este mesmo método estão suspensas, até que a primeira thread termine seu trabalho com o objeto.
    • Quando um método sincronizado existe, o mesmo garante a consistência com qualquer invocação futura de um método sincronizado do mesmo objeto. Isto garante que mudanças no estado do objeto sejam visíveis a todas as threads.
    • Obs : Construtores não podem receber a cláusula synchronized, pois somente uma thread consegue criar uma instância por vez, e isto também ocasionará em um erro de compilação.
  • 261. Locks implícitos e sincronização
    • A sincronização é feita atrvés de uma dispositivo interno chamado “monitor lock” . Locks implícitos comandam o acesso exclusivo ao estado do objeto.
    • Cada objeto tem um lock implícito associado a ele. Uma thread que precisa acesso exclusivo e consistente a um campo de um objeto precisa pegar um lock implícito antes de acessá-lo, e então liberá-lo quando terminar seu trabalho.
    • A thread é dona do lock entre o momento em quen o pega, até o momento da liberação. Enquanto uma thread tiver o lock sobre o objeto, nenhuma outra thread conseguirá pegar o mesmo lock, ou seja, as outras threads serão bloqueadas quando tentarem realizar o lock.
  • 262. Locks em métodos sincronizados
    • Quando uma thread invoca um método sincronizado, a mesma adquire automáticamente o lock para o método do objeto e o libera quando o método retornar.
  • 263. Declarações sincronizadas
    • Outra forma de criarmos código sincronizada é através das declarações sincronizadas . Ao contrário dos métodos sincronizados, as declarações devem especificar o objeto que provê o lock :
    • public void addName(String name) {
    • synchronized(this) {
    • lastName = name;
    • nameCount++;
    • }
    • nameList.add(name);
    • }
  • 264. DeadLock
    • O deadlock é uma situação onde duas ou mais threads ficam bloqueadas para sempre, esperando uma pela outra.
  • 265. Collections Capítulo 8
  • 266. Introdução
    • Uma coleção é um container, ou seja, um objeto que tem a capacidade de agrupar vários elementos em uma única unidade.
    • Coleções são utilizadas para guardar, recuperar, manipular e comunicar dados agregados. Geralmente elas representam algum agrupamento natural, como por exemplo lista de funcionários, grupo de emails, e etc.
  • 267. O framework de coleções
    • É a arquitetura unificada para representar e maniuplar coleções, onde todos os frameworks possuem :
    • Interfaces : Que são dados abstratos que representam as coleções. As interfaces permitem que as coleções sejam manipuladas independentemente dos detalhes de implementação.
    • Implementações : São as implementações concretas das interfaces, ou seja, elas são as estruturas “de fato”.
    • Algorítimos : São métodos que executam operações úteis, tal como pesquisa e ordenação em objetos que implementam interfaces de coleções. Os algorítimos são polimórficos, ou seja, o mesmo método pode ser usado em diferentes implementa~ções.
  • 268. Benefícios do framework de coleções
    • Reduz o trabalho com programação : Pois provê ótimas estruturas de dados e algorítimos, o framework de coleções nos libera para concentrarmos somente nas partes importantes do nosso programa, ao invés de ficarmos focados em problemas de “baixo-nível”.
    • Aumenta a velocidade de programação e a qualidade : Pois provê implementações de alta performance e alta qualidade em suas estruturas e algorítimos. As várias implementações são intercambiáveis, então os programas podem mudar de implementação fácilmente.
    • Reduz o tempo de aprendizado.
    • Reduz o tempo de escrita de novas APIs
    • Possibilita o reuso.
  • 269. Interfaces
    • As interfaces do core encapsulam diferentes tipos de coleções, que são mostradas na próxima figura.
    • Estas interfaces permitem que as coleções sejam manipuladas independente de sua representação. As coleções do core são a pedra fundamental do Java Collections Framework.
  • 270. Collection
    • A raiz da hierarquia de coleções. Uma collection representa um grupo de objetos denominados elementos.
    • A interface Collection é o denominador comum entre todas as coleções que a implementam e é usada para passar coleções a métodos e manipulá-las de forma genérica.
  • 271. Set
    • É uma coleção que não pode ter elementos duplicados. Esta interface modela a abstração matemática de “conjunto”.
  • 272. List
    • Uma coleção ordenada ( também conhecida como sequência). As listas podem conter elementos duplicados. O usuário geralmente tem o controle preciso de onde o elemento é inserido na mesma, e pode acessá-lo usando um índice de posição.
  • 273. Queue
    • Uma coleção usada para carregar múltiplos elementos antes de processá-los. Queues típicamente, mas não necessáriamente, ordenam elementos no modo FIFO (first-in, first-out).
    • Entre as exceções estão priority queues, que ordenam os elementos de acordo com um comparator fornecido.
  • 274. Map
    • Um objeto que mapeia chaves e valores. Um mapa não pode ter chaves duplicadas, e uma chave só pode mapear um único valor.
  • 275. Sorted
    • SortedSet - Um conujunto que mantém seus elementos em ordem ascendente.
    • SortedMap – Um mapa que mantém os seus mapeamentos em ordem ascendente de chave. Este mapa é análogo ao SortedSet.
  • 276. A iterface Collection
    • public interface Collection<E> extends Iterable<E> {
    • // Basic operations
    • int size();
    • boolean isEmpty();
    • boolean contains(Object element);
    • boolean add(E element); //optional
    • boolean remove(Object element); //optional
    • Iterator<E> iterator();
    • // Bulk operations
    • boolean containsAll(Collection<?> c);
    • boolean addAll(Collection<? extends E> c); //optional
    • boolean removeAll(Collection<?> c); //optional
    • boolean retainAll(Collection<?> c); //optional
    • void clear(); //optional
    • // Array operations
    • Object[] toArray();
    • <T> T[] toArray(T[] a);
    • }
  • 277. Atravessando coleções
    • Declaração for-each
    • for (Object o : collection) { System.out.println(o);
    • }
    • Iterators
    • public interface Iterator<E> {
    • boolean hasNext();
    • E next();
    • void remove(); //optional
    • }
    • static void filter(Collection<?> c) {
    • for (Iterator<?> it = c.iterator(); it.hasNext(); )
    • if (!cond(it.next())) it.remove();
    • }
  • 278. Operações em massa sobre Collections
    • Operações em massa são executadas em cima de uma coleção inteira.
    • containsAll – retorna true se a coleção destino possui todos os itens na coleção especificada.
    • addAll – adiciona todos os elementos da coleção especificada na coleção destino.
    • removeAll – remove da coleção destino todos os elementos que também estiverem contidos na coleção especificada.
    • retainAll – remove da coleção destino todos os elementos que não estiverem contidos na coleção especificada.
    • clear – remove todos os elementos da coleção.
    • c.removeAll(Collections.singleton(e));
    • c.removeAll(Collections.singleton(null));
  • 279. A interface Collection e Arrays
    • O método toArray é provido como uma ponte de ligação entre coleções e APIs antigas que esperam arrays como entrada. As operações com arrays permitem que o conteúdo de uma coleção seja traduzido para um array.
    • Object[] a = c.toArray();
  • 280. A interface Set
    • public interface Set<E> extends Collection<E> {
    • // Basic operations
    • int size();
    • boolean isEmpty();
    • boolean contains(Object element);
    • boolean add(E element); //optional
    • boolean remove(Object element); //optional
    • Iterator<E> iterator();
    • // Bulk operations
    • boolean containsAll(Collection<?> c);
    • boolean addAll(Collection<? extends E> c); //optional
    • boolean removeAll(Collection<?> c); //optional
    • boolean retainAll(Collection<?> c); //optional
    • void clear(); //optional
    • // Array Operations
    • Object[] toArray();
    • <T> T[] toArray(T[] a);
    • }
  • 281. Implementações de Set
    • O Java possui 3 implementações para a interface Set.
    • HashSet – Armazena os elementos em uma hash table, é a implementação de melhor performance, mas a mesma não garante order alguma no momento da iteração
    • TreeSet – Armazena os elementos em formato red-black tree, ordena os elementos baseado nos seus valores, e é substancialmente mais lenta que HashSet.
    • LinkedSet – Implementada como hash table com uma linked list, ordena os elementos baseada na order em que eles foram inseridos no conjunto.
    • Collection<Type> noDups = new HashSet<Type>(c);
    • Collection<Type> noDups = new LinkedHashSet<Type>(c);
  • 282. Operações em massa com Sets
    • Operações em massa são muito interessantes em Sets, pois elas são executadas de forma algébriga.
    • s1.containsAll(s2) — retorna true se s2 é um subconjunto de s1. (s2 é um subconjunto de s1 se s1 contém todos os elementos que estão em s2.)
    • s1.addAll(s2) — transforma s1 na união de s1 e s2. (A união de dois sets é o set contendo todos os elementos contidos em ambos sets.)
    • s1.retainAll(s2) — transforma s1 na interseção de s1 e s2. (A interseção de dois sets é um set contendo somente os elementos comuns em ambos sets.)
    • s1.removeAll(s2) — transforma s1 na diferença (assimétrica) de s1 e s2. (Por exemplo, a diferença entre s1 menos s2 é o set contendo todos os elementos encontrados em s1 mas não em s2.)
  • 283. Operações em massa com Sets
    • Para calcular a união, interseção ou a diferença entre sets de forma não destrutiva, então devemos copiar o set antes de invocarmos as operações em massa :
    • Set<Type> union = new HashSet<Type>(s1);
    • union.addAll(s2);
    • Set<Type> intersection = new HashSet<Type>(s1);
    • intersection.retainAll(s2);
    • Set<Type> difference = new HashSet<Type>(s1);
    • difference.removeAll(s2);
  • 284. A interface List
    • public interface List<E> extends Collection<E> {
    • // Positional access
    • E get(int index);
    • E set(int index, E element); //optional
    • boolean add(E element); //optional
    • void add(int index, E element); //optional
    • E remove(int index); //optional
    • boolean addAll(int index,
    • Collection<? extends E> c); //optional
    • // Search
    • int indexOf(Object o);
    • int lastIndexOf(Object o);
    • // Iteration
    • ListIterator<E> listIterator();
    • ListIterator<E> listIterator(int index);
    • // Range-view
    • List<E> subList(int from, int to);
    • }
  • 285. Implementações de List
    • O Java possui duas implementações para List.
    • ArrayList – Geralmente é a implementação de melhor performance.
    • LinkedList – Oferece melhor performance sob certas circunstâncias.
    • Vector “intruso” – Foi refatorado para implementar List.
  • 286. Operações sobre List
    • list1.addAll(list2);
    • //Forma não destrutiva
    • List<Type> list3 = new ArrayList<Type>(list1);
    • list3.addAll(list2);
    • //acesso posicional e pesquisa
    • public static <E> void swap(List<E> a, int i, int j) {
    • E tmp = a.get(i);
    • a.set(i, a.get(j));
    • a.set(j, tmp);
    • }
  • 287. Iterators
    • É retornado pelas operações de iterators da lista.
    • public interface ListIterator<E> extends Iterator<E> {
    • boolean hasNext();
    • E next();
    • boolean hasPrevious();
    • E previous();
    • int nextIndex();
    • int previousIndex();
    • void remove(); //optional
    • void set(E e); //optional
    • void add(E e); //optional
    • }
    • for (ListIterator<Type> it = list.listIterator(list.size()); it.hasPrevious(); ) {
    • Type t = it.previous();
    • ...
    • }
  • 288. Queue
    • public interface Queue<E> extends Collection<E> {
    • E element();
    • boolean offer(E e);
    • E peek();
    • E poll();
    • E remove();
    • }
    • static <E> List<E> heapSort(Collection<E> c) {
    • Queue<E> queue = new PriorityQueue<E>(c);
    • List<E> result = new ArrayList<E>();
    • while (!queue.isEmpty())
    • result.add(queue.remove());
    • return result;
    • }
  • 289. A interface Map
    • public interface Map<K,V> {
    • // Basic operations
    • V put(K key, V value);
    • V get(Object key);
    • V remove(Object key);
    • boolean containsKey(Object key);
    • boolean containsValue(Object value);
    • int size();
    • boolean isEmpty();
    • // Bulk operations
    • void putAll(Map<? extends K, ? extends V> m);
    • void clear();
  • 290. A interface Map
    • // Collection Views
    • public Set<K> keySet();
    • public Collection<V> values();
    • public Set<Map.Entry<K,V>> entrySet();
    • // Interface for entrySet elements
    • public interface Entry {
    • K getKey();
    • V getValue();
    • V setValue(V value);
    • }
    • }
    • Existem três implementações para a interface Map : HashMap, TreeMap e LinkedHashMap. Que por sua vez são análogas as implementações de Set.
  • 291. Operações com Map
    • import java.util.*;
    • public class Freq {
    • public static void main(String[] args) {
    • HashMap<String, Integer> m = new HashMap<String, Integer>();
    • // Initialize frequency table from command line
    • for (String a : args) {
    • Integer freq = m.get(a);
    • m.put(a, (freq == null) ? 1 : freq + 1);
    • }
    • System.out.println(m.size() + &quot; distinct words:&quot;);
    • System.out.println(m);
    • }
    • }
    • for (Map.Entry<KeyType, ValType> e : m.entrySet()) System.out.println(e.getKey() + &quot;: &quot; + e.getValue());
  • 292. Generics Capítulo 9
  • 293. Introdução Generics é a alteração mais significante da linguagem Java desde a sua versão 1.0. A adição das generics no java 5.0 foi o resultado de uma especificação ( JSR 14 ), que foi feita em 1999. Generics são muito úteis porque elas nos permitem escrever código que é seguro e fácil de ler, ao invés de código que trabalha com Objects e usa vários casts. As generics são muito úteis no trabalho com collections, tal como o ArrayList.
  • 294. Introdução Generics são muito parecidas com as famosas templates do C++. Programação com generics significa escrever código que pode ser reutilizado por objetos de diferente tipos.
  • 295. Usando coleções com cast List myIntList = new LinkedList(); // 1 myIntList.add(new Integer(0)); // 2 Integer x = (Integer) myIntList.iterator().next(); // 3 Famoso código “saco de gatos”
  • 296. Com Generics Uma interface ou classe pode ser declarada para receber um ou mais parâmetros, que são escritos entre os sinais de menor e maior < e >. List <Integer> myIntList = new LinkedList<Integer>(); // 1' myIntList.add(new Integer(0)); // 2' Integer x = myIntList.iterator().next(); // 3'
  • 297. Especificação de generics Definição da interface List : public interface List <E>{ void add(E x); Iterator<E> iterator(); } public interface Iterator<E>{ E next(); boolean hasNext(); }
  • 298. Programando com generics É muito fácil utilizarmos uma classe genérica como ArrayList. E a maioria de nós programadores mortais iremos simplesmente digitar ArrayList<String>, pois esta declaração já faz parte da linguagem, e é tão natural quanto se estivessemos declarando um array de strings : String[]. Infelizmente não é tão fácil implementar uma classe genérica, pois os programadores que utilizarão este código podem querer plugar todos os tipos de classes como parâmetro de tipo. E os mesmos esperam que tudo funcione sem restrição ou mensagem de erro.
  • 299. Wrappers Todo tipo em Java é um tipo referência ou primitivo. Um tipo referência é qualquer classe, instância ou array. Todos os tipos referência são subclasses de Object. Existem 8 tipos de primitivos, e cada um deles possui uma classe ( Wrapper ) correspondente.
  • 300. Wrappers Primitivo Referência byte Byte short Short int Integer long Long float Float double Double boolean Boolean char Character
  • 301. Boxing e Unboxing A conversão de primitivo para refência é chamado de boxing, e a conversão de referência para primitivo é chamado de unboxing. O Java com generics insere mecanismos de boxing e unboxing quando necessário, deixando o programador livre de criar um wrapper ou convertê-lo para um primitivo. List<Integer> list = new ArrayList<Integer>(); list.add(1); //Boxing int n = list.get(0); //Unboxing //É o mesmo que : List<Integer> list = new ArrayList<Integer>(); list.add(new Integer(1)); int n = list.get(0);
  • 302. Definição de classe genérica public class Pair<T> { public Pair() { first = null; second = null; } public Pair(T first, T second) { this.first = first; this.second = second; } public T getFirst() { return first; } public T getSecond() { return second; } public void setFirst(T newValue) { first = newValue; } public void setSecond(T newValue) { second = newValue; } private T first; private T second; }
  • 303. Definição de classe genérica Temos em nossa classe “Pair” uma variável de tipo T, que está entre < > depois do nome da classe. Vale a pena lembrar que uma classe genérica pode ter mais de um tipo de variável. Poderíamos ter definido a classe Pair usando dois parâmetros : public class Pair<T, U> { . . . }
  • 304. Padrões Os “type variables” são utilizados dentro da definição da classe para especificar o retorno do método, tipos de campos e variáveis locais : private T first; É uma prática comum usar letras em caixa alta para tipos, e mantê-los curtos. As bibliotecas do Java usam a variável E para tipo de elemento de coleção, K e V para chave e valor ( key/value ) de um mapa/tabela, e T ( e também U e S, se necessário), para qualquer outro tipo.
  • 305. Instanciando tipos genéricos Para tal tarefa necessitamos somente substituir as variáveis de tipo pelo tipo desejado : Pair<String>
  • 306. Método genérico e varargs Public static <T> void addAll(list<T>, T... arr) { For (T tipo : arr ) { list.add(tipo); } }
  • 307. Testando a classe genérica Pair public class PairTeste { public static void main(String[] args) { Pair<String> p = new Pair<String>(); p.setFirst(&quot;a&quot;); p.setSecond(&quot;b&quot;); } }
  • 308. foreach Existe uma forma mais rápida e inteligente de iterar em arrays e coleções : double[] ar = {1.2, 3.0, 0.8}; int sum = 0; for (double d : ar) { sum += d; }
  • 309. foreach List<String> names = new ArrayList<String>(); names.add(&quot;a&quot;); names.add(&quot;b&quot;); names.add(&quot;c&quot;); for (String name: names) { System.out.println(name.charAt(0)); }