0% acharam este documento útil (0 voto)
37 visualizações303 páginas

Java para Crianças: Aprenda Programação

O livro 'Programação Java para Crianças' de Yakov Fain ensina a linguagem de programação Java de forma acessível, visando crianças a partir de 12 anos. Ele abrange desde a instalação do Java até a criação de jogos e interfaces gráficas, utilizando ferramentas profissionais. O material é oferecido gratuitamente online e pode ser usado por adolescentes, pais e professores como um recurso educacional.

Enviado por

silviacarvalhos
Direitos autorais
© All Rights Reserved
Levamos muito a sério os direitos de conteúdo. Se você suspeita que este conteúdo é seu, reivindique-o aqui.
Formatos disponíveis
Baixe no formato PDF, TXT ou leia on-line no Scribd
0% acharam este documento útil (0 voto)
37 visualizações303 páginas

Java para Crianças: Aprenda Programação

O livro 'Programação Java para Crianças' de Yakov Fain ensina a linguagem de programação Java de forma acessível, visando crianças a partir de 12 anos. Ele abrange desde a instalação do Java até a criação de jogos e interfaces gráficas, utilizando ferramentas profissionais. O material é oferecido gratuitamente online e pode ser usado por adolescentes, pais e professores como um recurso educacional.

Enviado por

silviacarvalhos
Direitos autorais
© All Rights Reserved
Levamos muito a sério os direitos de conteúdo. Se você suspeita que este conteúdo é seu, reivindique-o aqui.
Formatos disponíveis
Baixe no formato PDF, TXT ou leia on-line no Scribd

22/03/2025, 18:48 Programação Java para crianças

Programação Java para crianças

[Link] 1/303
22/03/2025, 18:48 Programação Java para crianças

Índice
Prefácio
1. Escrevendo seu primeiro programa
1.1. Instalando Java no seu computador
1.1.1. Somente para usuários do Windows
1.2. Três etapas principais na programação Java
1.2.1. Janela de comando
1.2.2. Etapa 1 – Escreva o programa
1.2.3. Passo 2 – Compilar o Programa
1.2.4. Etapa 3 – Execute o programa
2. Ficando confortável no IDEA IDE
2.1. Instalando o IntelliJ IDEA
2.2. Criando seu primeiro projeto
2.3. Criando a classe HelloWorld no IDEA
2.3.1. Adicionando o método main
2.3.2. Executando HelloWorld no IDEA
2.4. Como HelloWorld funciona?
3. Conheça as classes - as principais construções da linguagem
3.1. Dissecando classes e objetos
3.1.1. Aulas
3.1.2. Objetos
3.2. Tipos de dados e variáveis ​Java
3.2.1. Primitivos
3.2.2. Classes como tipos de dados
3.2.3. Quanta memória é necessária
3.3. Criação de um animal de estimação
3.4. Herança – um peixe também pode ser um animal de estimação
3.5. Substituição de método
3.6. Desafie-se
4. Blocos de construção Java
4.1. Comentários do programa
4.2. Tomando decisões
4.2.1. A declaração if
4.2.2. Operadores Lógicos
4.2.3. Operador condicional
4.2.4. Usando else if
4.2.5. A switch Declaração
4.3. Quanto tempo uma variável viverá?
4.3.1. A palavra-chave static

[Link] 2/303
22/03/2025, 18:48 Programação Java para crianças

4.4. Métodos Especiais: Construtores


4.5. A palavra-chave this
4.6. Matrizes
4.7. Repetindo ações com loops
4.8. Desafie-se
5. Interfaces, Lambdas, Classes Abstratas e Anônimas
5.1. Interfaces Java
5.1.1. Métodos Padrão em Interfaces
5.1.2. Métodos estáticos em interfaces
5.1.3. Variáveis ​estáticas finais em interfaces
5.1.4. Interfaces Funcionais
5.2. Classes abstratas
5.2.1. Qual é a diferença entre classes abstratas e interfaces?
5.3. Classes anônimas
5.4. Expressões Lambda
5.4.1. Simplificando o código com Lambdas
5.5. Projeto: Interfaces Java e Expressões Lambda
6. Níveis de acesso, coleções, genéricos e multithreading
6.1. Níveis de acesso
6.2. Fundição
6.3. Coleções de dados selecionadas
6.3.1. A classe ArrayList
6.3.2. A classe Hashtable
6.4. Introdução aos Genéricos
6.5. Introdução leve ao multithreading
6.5.1. Como criar um tópico
6.6. Projeto: Usando ArrayList e Generics
7. Introdução à GUI com JavaFX
7.1. Introdução ao JavaFX
7.2. Breve Visão Geral dos Layouts JavaFX
7.3. Introdução ao Scene Builder
7.4. Layout do GridPane
7.4.1. Projetando uma janela de entrada no Scene Builder
7.4.2. Programação da janela de login em Java
7.5. Estilização com CSS
7.6. BorderPane e Combinando Layouts
7.7. Projeto: Criando uma GUI para Calculadora
8. Programação de interação do usuário em JavaFX
8.1. Eventos
8.1.1. Atribuindo manipuladores de eventos em FXML

[Link] 3/303
22/03/2025, 18:48 Programação Java para crianças

8.1.2. Adicionando controlador ao aplicativo Sign In


8.1.3. Troca de dados entre componentes GUI e controlador
8.1.4. Atribuindo manipuladores de eventos em Java
8.1.5. Leituras Adicionais sobre Manipulação de Eventos
8.2. Vinculação de dados e propriedades
8.3. O Thread de Aplicação em JavaFX
8.3.1. Demonstração da tela congelada
8.4. Implantando com o JavaFX Packager
8.5. O que estudar a seguir sobre JavaFX
8.6. Projeto: Adicionando Manipulação de Eventos para Calculadora
8.6.1. Desafie-se
9. Lidando com erros de tempo de execução
9.1. Lendo o Stack Trace
9.2. Árvore genealógica de exceções
9.3. Bloco Tentar/Pegar
9.4. A palavra-chave throws
9.5. A palavra-chave finally
9.6. A palavra-chave throw
9.7. Criando exceções personalizadas
9.8. Projeto: Criar uma loja de bicicletas JavaFX
10. Criando um jogo da velha
10.1. Desenvolvendo o jogo: passo a passo
10.1.1. Desenvolvendo a parte GUI no Scene Builder
10.1.2. Manipulando cliques de botão no controlador
10.1.3. Botões de estilo e a barra de menu
10.1.4. Implementando a estratégia do jogo
10.1.5. Destacando a combinação vencedora
10.1.6. Manipulando o jogo da velha no menu
10.2. Projeto: Jogando contra o computador
10.2.1. Desafie-se
11. Trabalhando com arquivos e serialização
11.1. Noções básicas de trabalho com fluxos
11.1.1. Fluxos de bytes
11.1.2. Fluxos Bufferizados
11.2. Fluxos de Personagens
11.3. Trabalhando com arquivos usando [Link]
11.3.1. Usando classes Path e Paths
11.3.2. Usando os arquivos de classe
11.3.3. Lendo um arquivo
11.3.4. Escrevendo em um arquivo

[Link] 4/303
22/03/2025, 18:48 Programação Java para crianças

11.4. Argumentos de linha de comando


11.5. Serialização: Transformando um objeto em bytes
11.6. Projeto: Salvando as pontuações do jogo
12. Rede: Baixando arquivos da Internet
12.1. Como os computadores se encontram na Web
12.2. Nomes de domínio e endereços IP
12.3. Baixando arquivos da Web
12.3.1. Baixando qualquer arquivo da Internet
12.4. Projeto: Baixando Música
13. Criando um jogo de pingue-pongue
13.1. A Estratégia
13.2. Etapa 1: Criando a tabela
13.3. Etapa 2: Manipulando eventos de teclado
13.3.1. Processando eventos de teclado no controlador
13.3.2. O tipo enum
13.3.3. Preparando para processar as chaves S, Q e N
13.4. Etapa 3: Movendo o remo
13.5. Passo 4. Movendo a bola
13.5.1. Movendo a bola para a raquete direita
13.5.2. Servindo a bola horizontalmente
13.5.3. Servindo a bola em direções aleatórias
13.6. Etapa 5: Movendo o Paddle do Computador
13.7. Etapa 6: quicando a bola
13.8. Projeto: Exibindo a pontuação do jogo
14. Git para crianças
14.1. Dois tipos de sistemas de controle de versão
14.2. Introdução ao Git
14.2.1. Apresentando-se ao Git
14.3. Criando um novo repositório Git
14.4. Comandos Git selecionados
14.4.1. O comando status
14.4.2. O comando add
14.4.3. O comando commit
14.4.4. O comando reset
14.4.5. Ramificação de código
14.4.6. Resolução de conflitos
14.5. Publicando seu código no GitHub
14.5.1. Criando um repositório GitHub
14.5.2. Enviando o repositório local para o GitHub
14.5.3. Puxando a versão mais recente do GitHub

[Link] 5/303
22/03/2025, 18:48 Programação Java para crianças

14.5.4. Clonagem
14.5.5. Bifurcação e solicitações de pull
14.5.6. Clonagem do IntelliJ IDEA
Epílogo

[Link] 6/303
22/03/2025, 18:48 Programação Java para crianças

[Link] 7/303
22/03/2025, 18:48 Programação Java para crianças

Prefácio
O livro "Java para Crianças" foi escrito por Yakov Fain, Java Champion ([Link] . O
objetivo é ajudar os alunos a aprender a programar na linguagem mais popular do mundo: Java. Este livro
começa com uma introdução ao Java e então explica como escrever programas que tenham Interface Gráfica de
Usuário escrevendo os jogos Tic-Tac-Toe e Ping-Pong.

O livro "Java para Crianças" pode ser usado de várias maneiras:

1. Os adolescentes podem usá-lo para aprenderem sozinhos

2. Os pais podem usar este livro para ensinar Java aos seus filhos

3. Professores escolares podem usá-lo como um livro-texto em aulas introdutórias sobre programação

4. Professores universitários podem usá-lo como um suplemento para suas aulas de "Ciência da Computação
101".

Embora este livro tenha sido escrito para crianças de 12+ anos, adultos que procuram uma introdução fácil ao
Java também podem achar este livro útil. No livro, você usará as mesmas ferramentas usadas por programadores
profissionais. Como bônus, o último capítulo lhe ensinará como publicar seu código na Web em um site super
popular chamado GitHub ([Link] . Milhões de programadores compartilham seus programas lá e você
também deveria.

Yuri Fain ([Link] produziu ilustrações para este livro. Se este material parece muito fácil para
você, compre a segunda edição do meu livro para adultos "Java 24-Hour Trainer"
([Link] ou um curso em vídeo "Introdução
ao Java e Java EE" ([Link] .

A versão online deste livro é oferecida gratuitamente sob a licença Creative Commons
([Link] , mas o autor apreciaria uma doação
([Link] se você achasse este
livro útil. Após fazer uma doação, você terá direito a receber a versão em PDF do livro, bem como nos formatos
MOBI (para Kindle) e EPUB (para iBook).

Participe do grupo na Internet ([Link] onde os leitores podem postar suas


perguntas e comentários sobre o conteúdo deste livro.

Se você encontrar um erro nos exemplos de código, envie seus comentários diretamente para mim em
yakovfain@[Link] ([Link] ou abra um problema no repositório de exemplos de código
([Link] no GitHub.

[Link] 8/303
22/03/2025, 18:48 Programação Java para crianças

Todos os direitos reservados. © Yakov Fain 2015.

[Link] 9/303
22/03/2025, 18:48 Programação Java para crianças

1. Escrevendo seu primeiro programa


As pessoas se comunicam entre si usando diferentes idiomas. Hoje em dia, as pessoas geralmente passam mais
tempo se comunicando com computadores, smartphones e tablets do que entre si. Nós casualmente dizemos uns
aos outros: "Eu instalei um aplicativo legal que pode fazer isso e aquilo". Em outras palavras, as pessoas usam
aplicativos para se comunicar com computadores. Então, alguém tem que escrever esses aplicativos. Aqueles
que escrevem aplicativos de computador são conhecidos como programadores ou desenvolvedores de software.

Programadores escrevem aplicativos como jogos, calculadoras e editores de texto usando diferentes linguagens
de programação. Sem aplicativos, computadores, smartphones e consoles de jogos teriam uso muito limitado
para a maioria das pessoas. Dispositivos de computação geralmente vêm com um Sistema Operacional (SO)
instalado, como Windows, Mac OS, iOS e Android, mas imagine um iPhone que não tem nenhum aplicativo ou
um laptop que só pode mostrar o logotipo do SO. Quem iria querer um dispositivo desses?

Os programadores criam aplicativos usando diferentes linguagens de programação, como Java, Python, C++,
JavaScript, C e muitas outras. Algumas das linguagens são boas para produzir pequenos programas que exigem
muito pouco espaço de memória e podem ser incorporados em chips de computador. Algumas linguagens de
programação são ótimas para programar aplicativos da Web que rodam dentro dos navegadores da Web.
Algumas linguagens de programação são ótimas para rodar no servidor e lidar com milhares de solicitações de
usuários. Existem linguagens que são ajustadas para criar belos gráficos. Semelhante às linguagens humanas, as
linguagens de programação têm um conjunto de palavras (também conhecidas como palavras-chave) e as regras
para usá-las (a sintaxe).

Neste livro, você aprenderá a sintaxe da linguagem de programação Java, que pode ser usada para programar a
maioria dos tipos de aplicativos. E por muitos anos a linguagem de programação Java tem sido uma das
linguagens de computador mais populares do mundo. Na verdade, enquanto escrevo isso, as estimativas são de
que há cerca de 10 milhões de programadores Java profissionais no mundo, mas o que a torna tão popular?

Por um lado, o mesmo programa Java pode rodar em diferentes dispositivos: de computadores de mesa com
Windows ou MacOS a dispositivos portáteis como smartphones e tablets. Na verdade, os programas Java não se
importam com o dispositivo em que estão rodando porque eles rodam dentro de um tipo de hardware virtual
chamado máquina virtual. Falaremos sobre a Máquina Virtual Java um pouco mais adiante neste capítulo.

Java pode ser incorporado em pequenos microchips que controlam vários eletrodomésticos ou dispositivos
industriais, como os que alimentam casas inteligentes, onde o aquecimento ou a luz podem ser programados
remotamente a partir do seu telefone. Essas coisas conectadas à Internet podem ser programadas em Java.

Linguagens de programação podem ter algumas características gerais e dizemos que Java é uma linguagem
orientada a objetos. Seus elementos de programa ( classes ) representam objetos do mundo real. Por exemplo,
você pode criar uma classe chamada Car e dar a ela atributos que carros reais têm, como portas, rodas e assim

[Link] 10/303
22/03/2025, 18:48 Programação Java para crianças

por diante. Em seguida, você pode criar outra classe baseada na Car classe, como Tesla , com todos os
recursos da Car classe (portas, rodas) mais um motor elétrico.
E o software necessário para escrever Java é gratuito. Com tantos milhões de programadores Java profissionais
no mundo, você encontrará muitos programas de exemplo online, então se você tiver um problema, você pode
encontrar a solução pesquisando ou perguntando em um dos fóruns online populares como Stack Overflow
([Link] , e alguém provavelmente responderá sua pergunta!

Mas chega de conversa. Vamos começar a aprender Java.

1.1. Instalando Java no seu computador


Para começar a programar em Java, você precisa baixar o Java Development Kit (JDK) da empresa chamada
Oracle, que faz lançamentos e atualizações de versões do Java. O nome completo do software para baixar é Java
SE Development Kit. Nós baixaremos o Java SE 8, que era a versão mais recente do Java disponível enquanto
escrevíamos este livro. Basta visitar o site da Oracle
([Link] . Aceite o contrato de licença e
selecione o link apropriado dependendo do Sistema Operacional (SO) instalado no seu computador.

Enquanto programadores Java precisam do JDK instalado, os usuários dos seus


aplicativos precisam ter o Java Runtime Environment (JRE) instalado em suas
OBSERVAÇÃO
máquinas. O JRE está incluso no JDK, mas também pode ser baixado
separadamente.

[Link] 11/303
22/03/2025, 18:48 Programação Java para crianças

Figura 1. Selecionando a versão do Java SE

Se você usa o sistema operacional Windows, baixe o arquivo chamado [Link]. Como trabalho
com computadores Apple executando Mac OS X, o arquivo [Link] é meu instalador Java.
Execute seu programa instalador, concorde com todas as respostas padrão (basta pressionar o botão Next) e você
estará quase pronto para começar.

No Mac OS, o Java é instalado na pasta /Library/Java/JavaVirtualMachines/[Link] (pode haver outros


dígitos após zero, que indicam o número da atualização). Em computadores Windows, ele será instalado em
c:\Program Files\Java\jdk1.8.0 , onde c: é o nome do seu disco rígido ou SSD. Se você usa o Mac OS, sua
instalação está completa.

1.1.1. Somente para usuários do Windows


Se você usa Windows, também precisará adicionar Java à variável de ambiente Path . Clique no menu Iniciar,
Painel de Controle, Sistema e pesquise por Variáveis ​de Ambiente . Você verá todas as variáveis ​de sistema que
existem no seu SO, conforme mostrado na captura de tela Windows OS - Variáveis ​de Sistema . Se você tiver
direitos de administrador no seu PC Windows, poderá definir variáveis ​de usuário que serão aplicadas somente
quando um determinado usuário fizer login no seu PC, ou variáveis ​de sistema que serão aplicadas a todos os
usuários.

[Link] 12/303
22/03/2025, 18:48 Programação Java para crianças

Figura 2. Sistema operacional Windows - Variáveis ​do sistema

Pressione o botão inferior Edit e adicione o diretório bin do seu JDK no início do Path valor da variável. Por
exemplo, adicione c:\Program Files\java\jdk1.8.0\bin; se for onde seu JDK está instalado:

[Link] 13/303
22/03/2025, 18:48 Programação Java para crianças

Figura 3. Adicionando a variável Path do diretório bin

Agora a instalação do JDK no Windows está completa! Tenho certeza de que você está ansioso para começar a
escrever seu primeiro programa agora, então vamos lá.

1.2. Três etapas principais na programação Java


Se você tiver uma ideia do que programar, normalmente precisará executar as três etapas a seguir:

1. Escreva o programa em Java e salve-o em um arquivo.

2. Compile o programa para traduzi-lo da linguagem Java para um código de bytes especial que a JVM
entenda.

3. Execute o programa.

1.2.1. Janela de comando


Neste capítulo, compilaremos e executaremos o programa Hello World na janela de comando, se você usar o
Microsoft Windows, ou no Terminal, se estiver no Mac OS.

No Windows, para abrir a janela Command, clique no menu Start e digite as letras cmd no campo que diz Search
programs and files . Em um Mac, abra a janela Spotlight clicando no ícone de espelho no canto superior direito
da tela, digite a palavra Terminal e pressione Return no teclado.

Primeiro, crie uma pasta chamada practice digitando o seguinte comando:

prática mkdir

Este será o lugar onde armazenaremos todos os nossos programas Java.

1.2.2. Etapa 1 – Escreva o programa

[Link] 14/303
22/03/2025, 18:48 Programação Java para crianças

Começando no Capítulo 2, usaremos um aplicativo especial chamado Integrated Development Environment


(IDE) para escrever, compilar e executar programas. Mas para entender melhor como as coisas funcionam,
vamos usar qualquer editor de texto simples (por exemplo, Notepad, TextEdit et al.) para digitar o código do
nosso primeiro programa Java. Depois, salve o código em um arquivo de texto com um nome terminando em
.java .

Figura 4. Digitando o código

Por exemplo, se você quiser escrever um programa chamado HelloWorld , insira seu código em um editor de
texto. Aqui está o programa que imprime as palavras Hello World! na tela do seu computador:

JAVA
public class HelloWorld{

public static void main(String[] args){

[Link]("Hello World!");

}
}

Salve o código acima com o nome [Link] na pasta practice . Tenha em mente que você não tem
permissão para usar espaços em branco em nomes de arquivos Java.

Explicarei como e por que esse programa funciona um pouco mais adiante neste capítulo. Por enquanto, se você
seguiu cada passo corretamente, o programa imprimirá as palavras Hello World na tela, que veremos no passo 3.

[Link] 15/303
22/03/2025, 18:48 Programação Java para crianças

Os programadores geralmente usam as palavras código-fonte para se referir a um programa. Então é seguro dizer
que nós escrevemos o código-fonte do programa Hello World. A menos que você seja um programador Java
experiente, você não pode simplesmente assumir que este programa foi escrito corretamente. Vamos prosseguir
para a Etapa 2 para descobrir.

1.2.3. Passo 2 – Compilar o Programa


Agora você precisa usar o compilador Java para transformar o código-fonte do programa Hello World em
bytecode que o JRE entenda. O programa chamado javac é um compilador Java, que é instalado no seu
computador como parte do JDK e pode ser localizado na pasta bin no seu JDK.

Figura 5. Compilando o código fonte

Altere o diretório para practice com o comando cd practice . Se você nunca usou o comando cd antes, leia as
instruções online sobre como fazê-lo no Windows ([Link]
ou no Mac OS ([Link] . Agora compile o programa
usando o seguinte comando:

javac Olá[Link]

[Link] 16/303
22/03/2025, 18:48 Programação Java para crianças

Você não verá nenhuma mensagem de confirmação de que seu programa HelloWorld foi compilado com
sucesso. Não ter nenhuma mensagem significa que não houve problemas durante a compilação. Digite um
comando dir no Windows ou ls no Mac e você verá a lista de arquivos na pasta practice . É assim que parece na
minha janela do Terminal:

Figura 6. HelloWorld compilado com sucesso

Primeiro, eu digitei o comando pwd para ter certeza de que estou na pasta de prática . Você deve ver um novo
arquivo chamado [Link] . Isso prova que seu programa foi compilado com sucesso. Seu arquivo
original [Link] também pode ser encontrado lá, e você pode modificar esse arquivo mais tarde para
imprimir Hello Mom ou algo assim.

Se o programa tiver erros de sintaxe, por exemplo, você esqueceu de digitar a última chave, o compilador Java
imprimirá uma mensagem de erro. Agora você precisa corrigir o erro e recompilar o programa novamente. Se
tiver vários erros, pode ser necessário repetir essas ações mais de uma vez até que o arquivo
[Link] seja criado.

1.2.4. Etapa 3 – Execute o programa


Agora vamos executar o programa. Na mesma janela Command ou Terminal, digite o seguinte:

java Olá Mundo

Após executar este comando, você verá o texto Hello World! impresso na janela Terminal, como mostrado em
Running HelloWorld . Você notou que desta vez você usou o programa java e não javac ? É assim que você
inicia o JRE, fornecendo a ele o nome do aplicativo a ser executado ( HelloWorld neste caso).

[Link] 17/303
22/03/2025, 18:48 Programação Java para crianças

Figura 7. Executando HelloWorld

Tenha em mente que Java não trata letras maiúsculas e minúsculas da mesma forma, o que significa que se você
originalmente nomeou o programa HelloWorld com uma maiúscula H e uma maiúscula W , não tente iniciar o
programa helloworld ou helloWorld – o JRE sinalizará um erro. O nome do arquivo deve corresponder ao
nome da classe também. Normalmente, cada arquivo do seu aplicativo contém o código de uma classe.

Agora vamos nos divertir um pouco tentando adivinhar como modificar o código do programa que imprime
Hello World. Explicarei como esse programa funciona no próximo capítulo, mas por enquanto tente adivinhar o
que precisa ser feito para dizer olá ao seu animal de estimação, amigo ou imprimir seu endereço. Siga todas as
três etapas para ver se o programa ainda funciona após suas alterações. Se você não tem um animal de
estimação, pode sempre dizer olá ao meu cachorrinho - o nome dele é Sammy. Você está pronto para o desafio
de escrever um programa que imprima Hello Sammy! na tela?

[Link] 18/303
22/03/2025, 18:48 Programação Java para crianças

Figura 8. Sammy tem 4 meses aqui

No próximo capítulo, você aprenderá como escrever, compilar e executar seus programas em um ambiente mais
conveniente do que apenas um editor de texto e uma janela de comando. :toc-placement!: :imagesdir: .

[Link] 19/303
22/03/2025, 18:48 Programação Java para crianças

2. Ficando confortável no IDEA IDE


A maioria dos programadores escreve, compila e executa seus aplicativos em programas especiais que atendem
pelo nome de Integrated Development Environment (IDE). Qualquer IDE fornece ajuda enquanto você digita o
código, destaca as palavras-chave Java , tem um menu Help que descreve todos os elementos da linguagem e
torna mais fácil encontrar e corrigir erros em seus programas. Existem vários IDEs excelentes que são gratuitos.
Os mais populares são Eclipse ([Link] , NetBeans ([Link] e
IntelliJ IDEA ([Link] . Neste livro, usaremos o IntelliJ IDEA Community Edition.
Este é um excelente IDE para desenvolver aplicativos Java e, se você decidir programar mais tarde em outras
linguagens de programação, o IDEA também oferece suporte a mais de uma dúzia
([Link] de outras linguagens.

Neste capítulo, começaremos baixando e instalando o IntelliJ IDEA IDE (vamos chamá-lo apenas de IDEA).
Então, criaremos um projeto chamado Hello . Você verá que criar o aplicativo Hello World é muito mais fácil
dentro do IDEA.

2.1. Instalando o IntelliJ IDEA


Existem duas versões do IDEA IDE - Ultimate e Community. A versão Ultimate não é gratuita, mas tem recursos
adicionais úteis para desenvolver aplicativos empresariais. Mas este livro é sobre aprender os fundamentos da
programação Java, então usar a edição gratuita Community é tudo o que precisamos.

Abra a página da Web IntelliJ IDEA ([Link] e clique no botão Download


Community . Ele baixará o programa instalador com o nome que começa com ideaIC - basta executá-lo. No
MAC OS, o instalador não faz perguntas. Basta arrastar o ícone para a pasta Applications.

[Link] 20/303
22/03/2025, 18:48 Programação Java para crianças

Figura 9. Instalando o IDEA no MAC OS

No Windows, você precisará selecionar a pasta onde o IDEA será instalado, conforme mostrado abaixo. O
instalador do Windows também oferecerá a criação de um ícone de desktop para o IDEA - concorde com isso.

[Link] 21/303
22/03/2025, 18:48 Programação Java para crianças

Figura 10. Selecionando a pasta de destino no Windows

Em alguns segundos, você terá o IDEA instalado clicando no botão Avançar. Se você usa o MAC OS, encontre-o
usando o Spotlight no canto superior direito da tela e clique nele. Se você usa o Windows, clique no ícone do
IDEA recém-criado na sua área de trabalho. A primeira pergunta que o IDEA faz é se você deseja importar as
configurações das versões mais antigas do IDEA. Não selecione isso. Em seguida, vem esta tela de boas-vindas:

[Link] 22/303
22/03/2025, 18:48 Programação Java para crianças

Figura 11. Bem-vindo ao IntelliJ IDEA Community Edition

2.2. Criando seu primeiro projeto


No IDEA, seus aplicativos Java estarão localizados em projetos separados. Como você provavelmente
adivinhou, você precisará selecionar a opção Create New Project na tela Welcome. Então o IDEA perguntará
sobre o tipo de projeto que você quer criar.

[Link] 23/303
22/03/2025, 18:48 Programação Java para crianças

Figura 12. Selecionando o tipo de projeto

Selecione a opção para criar um projeto Java. No IDEA, os projetos consistem em módulos. Ao selecionar Java,
declaramos que nosso projeto terá um módulo Java. Clique no botão Next e depois novamente na janela seguinte
que perguntará sobre a seleção de um modelo que será usado neste projeto. Agora precisamos dar um nome ao
nosso projeto e selecionar o JDK a ser usado com este projeto.

Figura 13. Selecionando o nome do projeto e o JDK

[Link] 24/303
22/03/2025, 18:48 Programação Java para crianças

Não queremos que nosso projeto fique sem título , então substitua esse nome por hello na caixa superior.
Observe como o nome da pasta na caixa Project location muda de acordo. Quando você tentar fazer isso no seu
computador, o local do projeto aparecerá diferente do meu. Agora você precisa selecionar o JDK. Se você nunca
trabalhou com Java antes, o único JDK que você terá é o instalado no Capítulo 1, embora os programadores Java
às vezes tenham mais de um JDK instalado. Por exemplo, eles podem não ter permissão para usar o JDK 8 mais
recente para projetos de trabalho, então eles mantêm o JDK 7 por perto, mas todos os projetos divertidos serão
criados com o JDK 8.

Não temos tais restrições, então JDK 8 é nossa única escolha. Agora descubra onde localizá-lo.

Clique no botão Novo, selecione o item de menu JDK e você verá uma tela familiar para navegar pelas pastas no
seu computador. Consulte a primeira seção do Capítulo 1 ( Instalando o Java no seu computador ) dependendo
se você está trabalhando com MAC ou Windows. Estou usando MAC, então estou escolhendo Biblioteca , Java ,
JavaVirtualMachines , [Link] . Observe que a janela anterior agora parece diferente.

Figura 14. Nome do projeto e JDK selecionado

[Link] 25/303
22/03/2025, 18:48 Programação Java para crianças

Pressione o botão Finish e seu novo projeto é criado. Toda vez que você inicia o IDEA, ele oferece pequenas
dicas sobre como usar seus recursos interessantes. Você pode optar por não participar, mas recomendo que as
leia - você pode encontrar algumas pequenas preciosidades que tornarão seu trabalho com o IDEA mais
divertido. O projeto hello está pronto e você pode começar a escrever seu programa Hello World.

Figura 15. O projeto hello

Este projeto consiste no módulo hello e Bibliotecas Externas. O código-fonte do(s) seu(s) programa(s) estará(ão)
localizado(s) na pasta src no módulo hello. O arquivo [Link] é onde o IDEA lembra as configurações do
projeto hello - você não precisa mexer nele. Em Bibliotecas Externas você encontrará um monte de arquivos que
terminam em .jar . Esses JARs são as bibliotecas de código que vieram com o JDK.

Um projeto simples como o nosso HelloWorld terá apenas um arquivo com o código-fonte [Link] .
Projetos mais avançados consistirão em vários arquivos. Para simplificar a implantação do aplicativo, todos
esses arquivos podem ser empacotados em um ou mais JARs também. Tanto o JRE quanto o Java SDK incluem
dezenas de JARs. O Java vem com um utilitário jar que é usado para arquivar várias classes Java e outros
arquivos em um arquivo com a extensão de nome .jar. Os formatos internos dos arquivos .jar e .zip são os
mesmos. Se o seu projeto IDEA tiver várias classes, você pode empacotá-las em um JAR usando o menu
Arquivo | Estrutura do projeto | Artefatos e, em seguida, selecionando o tipo JAR.

[Link] 26/303
22/03/2025, 18:48 Programação Java para crianças

2.3. Criando a classe HelloWorld no IDEA


Os programas Java consistem em classes , e você começará a se familiarizar com os internos das classes na
seção "Como o Hello World funciona". Vamos recriar a HelloWorld classe do Capítulo 1 no IDEA. Selecione a
pasta src no seu projeto e, em seguida, selecione o menu Arquivo | Novo | Classe Java. Você verá uma pequena
janela pop-up solicitando um nome de classe. Insira o nome HelloWorld lá.

[Link] 27/303
22/03/2025, 18:48 Programação Java para crianças

Figura 16. Nomeando a classe

Em um segundo, o IDEA gerará uma classe vazia, HelloWorld como mostrado abaixo. A área branca à direita
é um editor de texto muito inteligente que permitirá que você não apenas insira o texto do seu programa, mas
também o ajudará sugerindo o que digitar em seguida enquanto você digita. Este editor é realmente inteligente!

Figura 17. Uma classe vazia HelloWorld

O texto entre /** e */ é uma das maneiras de escrever comentários em seus programas. Esta é uma área onde
você pode digitar qualquer texto que queira que descreva seu programa em geral ou qualquer código específico
dentro da classe. Falaremos sobre várias maneiras de escrever comentários no próximo capítulo.

2.3.1. Adicionando o método main


É hora de digitar a main declaração do método dentro da classe, como fizemos no Capítulo 1:

public static void main(String[] args)

Você certamente pode digitar a declaração acima, e o IDEA obedientemente começará a ajudar conforme você
começa a digitar. Por exemplo, comecei a digitar a palavra public , e depois de entrar o pu IDEA sugeriu a
seguinte seleção de palavras-chave que são apropriadas no local atual dentro da classe.

[Link] 28/303
22/03/2025, 18:48 Programação Java para crianças

Figura 18. Competição de código

Pressionar o botão Tab no teclado se transformará pu em public . Você também pode pressionar as teclas
Control-Space para ver a conclusão de código sugerida a qualquer momento. Mas há uma maneira ainda mais
rápida de inserir a declaração do main método. Basta digitar as primeiras letras dessas palavras-chave psvm e
pressionar a tecla Tab . O IDEA desdobrará essas letras no seguinte:

JAVA
public static void main(String[] args) {

Ótimo trabalho, IDEA! Esse preenchimento de código minimiza a digitação e o número de erros de digitação
que você pode cometer. No final deste capítulo, na seção Leitura Adicional, você encontrará o link para uma
página da Web mostrando recursos mais avançados de preenchimento de código no IDEA. Pode ser um pouco
cedo para você entender tudo o que é explicado lá, mas marque um link para esta página para referência futura.

Para se tornar um verdadeiro profissional no IDEA, você deve usar as teclas de atalho , que
são combinações de pressionamentos de teclas no teclado. Com as teclas de atalho, você
poderá navegar em seus projetos do IDEA muito mais rápido do que clicando em menus.
DICA
Aqui está o link
([Link] para o

documento que lista as teclas de atalho do IDEA.

[Link] 29/303
22/03/2025, 18:48 Programação Java para crianças

Agora temos a classe HelloWorld com um método main vazio . A palavra método significa ação . Para
executar uma classe Java como um programa, essa classe deve ter um método chamado main . Normalmente,
seus aplicativos terão muitas classes, mas apenas uma delas terá o método main . Essa classe se torna o ponto de
entrada em seu aplicativo.

Para completar nosso programa, coloque o cursor depois da chave na linha com main , pressione o botão Enter
e digite o seguinte na nova linha:

[Link]("Hello World!");

Depois de aprender sobre o psvm atalho, você pode estar se perguntando se há uma maneira de fazer um truque
semelhante com [Link]() . Basta digitar sout e pressionar a tecla Tab . Voilá! O
sout magicamente se transforma em [Link](); . Os programadores Java geralmente usam
impressão no console, então os criadores do IDEA forneceram um atalho para isso.

Para salvar as alterações de código e compilar a classe, basta pressionar Ctrl-S no seu teclado. Se você não
cometeu nenhum erro de sintaxe, não verá nenhuma mensagem de erro, portanto o programa está compilado,
mas vamos introduzir um erro de sintaxe de propósito para ver o que vai acontecer. Apague a última chave na
classe HelloWorld e pressione Ctrl-S novamente. O IDEA adicionará uma linha ondulada onde o compilador
Java encontrou o erro, a linha é marcada com a marca vermelha à direita, e se você passar o ponteiro do mouse
sobre este pequeno retângulo vermelho, verá a mensagem de erro:

Figura 19. O compilador detectou um erro de sintaxe

[Link] 30/303
22/03/2025, 18:48 Programação Java para crianças

Conforme seu projeto se torna maior, ele terá vários arquivos e o compilador pode capturar mais de um erro.
Você consegue ver uma lista de erros de todas as classes? Por padrão, o IDEA não compila todas as classes do
seu projeto, mas você pode solicitar a compilação do projeto inteiro sempre que fizer uma alteração ou salvar o
código-fonte. Vá para o menu IDEA Preferências (ou Configurações), selecione Compilador e marque a opção
Criar projeto automaticamente . Agora selecione o menu Exibir | Janelas de ferramentas | Problemas para ver
todos os problemas em uma lista:

Figura 20. A visualização de problemas

In our case we only have one compiler error. Java reached the end of the file while parsing (trying to understand
your code), and something could not be found - the curly brace, of course. But what does this mysterious (8,6)
mean? The error was found in the line number 8 around the sixth character from the left. To see line numbers,
right-click on the gray vertical bar to the left of the code editor and select the option Show Line Numbers. Now
it’s easier to map the error messages to the lines in the source code:

[Link] 31/303
22/03/2025, 18:48 Programação Java para crianças

Figure 21. Displaying the line numbers

2.3.2. Running HelloWorld in IDEA


After all syntax errors are fixed, compiler automatically creates the [Link] when you save the code.
IDEA doesn’t show you .class files, but if you are curious where they are, open the menu File | Project Structure
to see the folder where the compiler’s output goes. When a program is written, tested, does what it supposed to
do (e.g. print Hello World), and if you want to give it to your friends you’ll need to give only compiled .class
files. They don’t need source code of your program, but they do need the JRE (not JDK) installed on their
computer.

Java programmers can run their programs not only from a command window demonstrated in Chapter 1, but
right from the IDE. Just right-click on the name HelloWorld in the Project view and select the menu item Run
[Link](). The program will run and you’ll see the results in the Console View right inside IDEA:

[Link] 32/303
22/03/2025, 18:48 Programação Java para crianças

Figure 22. Running HelloWorld in IDEA

2.4. How Does HelloWorld Work?


It’s great that you’re following my instructions and the program works. But what exactly is happening in the
program HelloWorld ? What are all these keywords, braces and parentheses for?

Every Java program has at least one class, and Chapter 3 explains classes in detail. Classes can contain methods,
which are the actions that the class can perform. The class HelloWorld has only one method main , which is a
special action. It’s a program starter or an entry point of any Java application. You can tell that main is not a
Java keyword, but a method, because it has parentheses after the word main . Methods can call (invoke) other
methods, for example our method main calls the method println to display Hello World! on the screen.

Each method starts with a declaration line a.k.a. a method signature:

public static void main(String[] args)

This method signature tells us the following:

This method has public access level. The keyword public means that the method main could be
accessed by any other Java class or the JRE itself.

This method is static . The keyword static means that you don’t have to create an instance of the
HelloWorld object in memory to use this method. We’ll talk about classes and object instances in the next
chapter.

Does the method main return any data? Say, if you’ll write a method to add two numbers, it can return a
result. The keyword void means that the method main doesn’t return any data to whomever calls it (JRE
in this case).

[Link] 33/303
22/03/2025, 18:48 Programação Java para crianças

The method name main goes right before parentheses.

Some methods have parameters (a.k.a. arguments), which go inside the parentheses. It’s the data that could
be given to the method from another place of the program that invokes this method. The method main has
parameters - and an array of text values String[] args . You’ll learn how to use the parameters of the
method main in Chapter 9 in the section Command Line Arguments.
A Java program can consist of several classes, and each class may include methods. Usually, a Java class has
several methods. For example, a class Game can have the methods startGame , stopGame , readScore , and
so on. But only one class in the application will have the method main .

The body of our method main has only only one statement:

[Link]("Hello World!");

Every statement or a method call must end with a semicolon. The method println knows how to print data on
the system console (command window). Java method names are always followed by parentheses. If you see a
method with empty parentheses, this means that this method does not have any arguments and doesn’t expect to
receive any data. The above method println has one argument - a String with the value Hello World! .

[Link] means that the variable out is defined inside the class System that comes with Java. How are
you supposed to know that there’s something called out in the class System ? IDEA will help you with this.
After you type the word System and a dot, IDEA will show you everything that is available in this class. You
can also put a cursor after the dot and press Ctrl-Space at any time to bring up a help box similar to this one:

Figure 23. Peeking inside the System class with code completion

[Link] 34/303
22/03/2025, 18:48 Programação Java para crianças

This tells me that the Java class System has a variable out of type PrintStream . Are you curious as to what
PrintStream is? Click on out in your code and select the menu View | Quick Documentation to read the dry
documentation. The fact that a period goes after out followed by a method name - [Link]() - tells us
that out represents an object, which apparently has a method called println() .

We call it a dot notation. We write class_name.method_name or variable_name.method_name. Say you have a


class PingPongGame that has a method saveScore . If the method saveScore was declared with the two
arguments player and score , you may call this method for Dave who won three games:

[Link]("Dave", 3);

In this example, the arguments may be given to the method for some kind of processing like saving the score on
the disk. Since the name Dave was placed in parentheses, we can guess that the first argument has a String
type, which is used for text. The second argument is clearly of a numeric type but we can tell what’s the exact
type only after reading the declaration of the method saveScore inside the source code of the class
PingPongGame .

In the next chapter we’ll spend a lot more time seeing what Java classes consist of. :toc-placement!: :imagesdir: .

[Link] 35/303
22/03/2025, 18:48 Programação Java para crianças

3. Meet Classes - the Main Language Constructs


In the real world you see and use various objects, and each of them is belongs to some kind such as toys, food,
animals, electronics et al. In Java, instead of saying what kind of objects, we say what class of objects. In other
words, each object belongs to a class. A class is like a blueprint of an object. In this chapter you’ll get familiar
with classes - the main constructs of the Java language.

Any program that you’ll write will have at least one class. You’ll learn how to declare a class and how to create
one or more objects based on the class declaration. You’ll also learn about a class’s internals – what a class can
consist of. Finally, I’ll show you how to create a class that inherits features of another class.

Java defines a number of data types. Some of them are simple, like int , which represents integer numbers.
Some of them are more complex - they are called classes, like System , which can be used for things like
printing text on the screen, exiting a program, or cleaning a computer’s memory.

When you installed Java on your computer, you installed thousands of Java classes. Your Java programs will also
consist of classes that can represent objects from the real world. If a class is a data type, an object is a
representative of a specific type. For instance, you can see ten dogs on the street, and they all represent the class
Dog .

Programmers start working on any application by deciding which Java classes to include in the program and
how many of each object type to create. Say, they can define a class Player in the gaming application and
create two object instances of this type.

3.1. Dissecting Classes and Objects


When programmers talk to each other, they may say "Do something with the class Player" or "Do something
with the object Player". We need to learn the difference between the meaning of the words class and object.

3.1.1. Classes
Let’s see what Java classes can consist of. A very simple class can have nothing inside. Take a look at this class
declaration:

JAVA
class VideoGame {

This class is empty. It knows nothing and can’t do anything because there is no code between the curly braces.
From the Java syntax perspective, this class is legitimate and compiler won’t complain. There is a valid keyword
class followed by its name VideoGame . The opening curly brace has the matching closing one. We need
classes that can do stuff. We can place methods and attributes inside the class.

[Link] 36/303
22/03/2025, 18:48 Programação Java para crianças

Methods define actions that a class can perform.

Attributes describe various properties of a class.

A method consists of a callable code fragment, that can be called (and executed) by name from another part of
the program. For example, a class can have a method named saveScore that contains a dozen of lines of code
to save the game score. Let’s add some methods and attributes to the class VideoGame . This class may have
several methods, which can tell what an object of this class can do: start the game, stop it, save the score, ask for
additional lives on Facebook, and so on. This class also may have some attributes (a.k.a. fields): color, price and
others. An object that represents the class VideoGame can look like this:

JAVA
class VideoGame {

String color;
int price;

void start () {
// The code to start the game goes here
}

void stop () {
// The code to stop the game goes here
}

void saveScore(String playerName, int score) {


// The code to save score goes here
}
}

This class has two attributes color and price . The color attribute has the String data type, which is used
for storing any text. The price attribute is of an int type, which is used for storing integer numbers. The
class VideoGame has three methods: start , stop , and saveScore . These are the actions that our video
game should perform. Each of these method declarations start with a keyword void , which means that these
methods do not return a value to the caller of the method. In the next chapter I’ll show you a class Fish , which
will include a method dive that returns a value.

At this point each of these methods has just a single line that starts with two slashes //.

If a line starts with two slashes, it contains a single line comment - just the description of a
NOTE code fragment. If you need to write several lines of comments, just type in a slash followed
by the asterisk /* , then key in as many lines of a text as you want followed by */ .

Our class VideoGame can be used as a starting building block for pretty much any video game – all game
consoles have the color attribute, all of them allow to save score, and all of them have price tags.

[Link] 37/303
22/03/2025, 18:48 Programação Java para crianças

Figure 24. The Video Game Object

We can be more specific and create another Java class called PlayStation4 . It also belongs to the family of
video games, but has some properties that are specific to the model Play Station 4, for example sharing on
Facebook and Twitter. So among other things, the class PlayStation4 will have methods
shareOnFacebook and shareOnTwitter .

JAVA
class PlayStation4{

int hardDiskSize;

// Some other attributes and methods go here

void shareOnFacebook(){
// Code to share on Facebook go here
}

void shareOnTwitter(){
// Code to share on Twitter go here
}
}

[Link] 38/303
22/03/2025, 18:48 Programação Java para crianças

3.1.2. Objects
We’ll often use the phrase create an instance of an object, which means to create an object in a computer’s
memory based on some class declaration. If a game factory will produce ten thousand games, a programmer can
say that they created ten thousand instances of the class PlayStation4 .

The factory description of PlayStation4 relates to an actual game the same way as a Java class relates to its
instance in memory. The process of building actual games based on this description in the game factory is
similar to the process of creating instances of PlayStation4 objects in Java. For example, the next code
sample creates one instance of the class PlayStation4 and calls its method shareOnFacebook .

JAVA
public class CreatePlayStation4Objects {

public static void main(String[] args) {

// create one instance of PlayStation4 class


PlayStation4 firstPlayStation = new PlayStation4();

// call the method shareOnFacebook


[Link]();
}
}

In many cases, a program can use a Java class only after creating the instance of an object. The same with
manufacturers - they create thousands of game copies based on the same description. Even though these copies
represent the same class, they may have different values in their attributes - some of them are black while others
can be silver. Some of them have 500GB hard disk dive while some are upgraded to 1TB.

[Link] 39/303
22/03/2025, 18:48 Programação Java para crianças

Figure 25. One Class, Two Instances

In programmer’s jargon, you can create multiple instances of the PlayStation4 objects with different values
in the hardDiskSize attribute.

3.2. Java Data Types and Variables


If you ever covered algebra at any point in school, you are familiar with expressions like x=2 , which means that
the variable x represents the number 2. In programming, we use variables a lot. In programming a variable can
store a value in computer’s memory so you can access these values from various methods in your classes. Using
the same algebra example, we can say that we assign the value of 2 to the variable x . The equal sign represents
the assignment of the value located to the right of the equal sign to the variable located on the left.

Java variables not only can store numbers, but other types of data as well so we need to declare the variable type,
the name, and then assign some value to it. For example, the class attribute that has a value of the disk size can
be stored in the variable of type String that’s called hardDiskSize , which can be declared like this:

JAVA
String hardDiskSize;

If the size of the hard disk is 500GB, we can assign this value to the variable hardDiskSize as follows:

[Link] 40/303
22/03/2025, 18:48 Programação Java para crianças

JAVA
hardDiskSize="500GB";

String values are placed inside the quotes, and the numbers aren’t.

The method parameters (a.k.a. arguments) are also stored in variables. The method saveStore has two
arguments: playerName of type String and score of type int :

void saveScore(String playerName, int score)

3.2.1. Primitives
Simple Java data types are called primitives. Their keywords are written in small letters (e.g. int , long ,
char , boolean ). So the score is of a primitive data type, while the playerName is not. In Java you have
to declare the type and the name of a variable first and then use it.

Remember algebra equations like y=x+2 ? In Java you’d need to start with declaring the variables x and y of
some numeric data type like int , float or double :

JAVA
int x;
int y;

Now you can use the variables. The next two lines show how you can assign them values. If your program
assigns the value of five to the variable x , after evaluating x+2 the variable y will be equal to seven:

JAVA
x=5;
y=x+2;

In Java you are also allowed to change the value of a variable in a somewhat unusual way. The following two
lines change the value of the variable y from five to six:

JAVA
int y=5;
y++;

Despite the two plus signs, JVM is still going to increment the value of the variable y by one. The y++ means
read the value of the variable y , increment it by one, and assign it back to y . The longer syntax to achieve the
same result would be y=y+1 . After the next code fragment, the value of the variable myScore is also equal to
six:

JAVA
int myScore=5;
myScore=myScore+1;

[Link] 41/303
22/03/2025, 18:48 Programação Java para crianças

You can also use multiplication, division and subtraction the same way. Look at the following piece of code:

JAVA
int myScore=10;

myScore--;
myScore=myScore*2;
myScore=myScore/3;

[Link]("My score is " + myScore);

What do you think this code prints? IntelliJ IDEA has a useful tool called Groovy Console (it’s under the Tools
menu). It allows you to test any code snippet (like the one above) without even creating a class or methods. If
you’ll copy the above code fragment into Groovy Console and hit the green button play, you see that the value of
the variable myScore is 6.

Figure 26. Running the code fragment in Groovy Console

JAVA
To see the result of the score calculations, just click on the console tab at the bottom of
the screen:

My score is 6

In this example the argument of the method println was constructed from two pieces – the text “My score is ”
and the value of the variable myScore . Putting two or more strings together is called concatenation. Even
though myScore is a number, Java is smart enough to convert this variable into a String and then attach it to
the text "My Score is ".

Look at some other ways of changing the values of the variables:

[Link] 42/303
22/03/2025, 18:48 Programação Java para crianças

JAVA
myScore=myScore*2; // it's the same as `myScore*=2;
myScore=myScore+2; // it's the same as `myScore+=2;
myScore=myScore-2; // it's the same as `myScore-=2;
myScore=myScore/2; // it's the same as `myScore/=2;

There are eight primitive data types in Java, and you have to decide which ones to use depending on the type and
size of data you are planning to store in your variables. These are Java primitives:

Four data types for storing integer values – byte , short , int , and long .

Two data types for values with a decimal point – float and double .

One data type for storing a single character values – char .

One logical data type boolean that allows only two values: true or false .

You can assign an initial value to a variable during its declaration, and this is called variable initialization, for
example:

JAVA
char grade = 'A';
int chairs = 12;
boolean playSound = false;
double nationalIncome = 23863494965745.78;
float gamePrice = 12.50f;
long totalCars =4637283648392l;

In the last two lines the values have letters at the end. The f is for float and l means long.

If you declare, but won’t initialize primitive variables, Java will do it for you by assigning zero to each numeric
variable, false to boolean variables, and a special code ‘\u0000’ to variables of type char .

3.2.2. Classes as Data Types


Not all variables have primitive data types. Each primitive data type has a corresponding wrapper class, for
example Integer , Double , Boolean , etc. These classes also can store the values of the corresponding
primitive type, but also have useful methods to convert data from one type to another.

In some cases there is no primitive type that suits your needs. For example, there is no primitive type for storing
long texts. While the char data type is used to store only one character, Java also has a class String for
working with a longer text, for example:

String lastName="Smith";

If you declare your own class, consider it a new data type. You can start declaring variables of this type, for
example, you can declare the variable named myFirstGame of type VideoGame :

[Link] 43/303
22/03/2025, 18:48 Programação Java para crianças

VideoGame myFirstGame

Java programmers have agreed to name variables starting with small letters. To make the variable name more
meaningful, it can consist of several words, and each word starts with the capital letter as in myFirstGame .
You’re also allowed to start variable names with the dollar sign like $myMoney or underscore:
_myBestFriend . Variable names cannot contain spaces.

Java also has a special keyword final , and if it’s used in a declaration of a variable, it means that you can
assign a value to this variable only once, and this value cannot be changed afterwards. In Java we usually name
final variables using capital letters:

final String STATE_CAPITAL="Washington";

3.2.3. How Much Memory is Needed


Variables are stored in a computer’s memory and occupy more or less space depending on the data type. We
measure memory in bits, bytes, kilobytes (1024 bytes), megabytes (1024 kilobytes or Kb), gigabytes (1024 Mb)
and so on. A bit is the smallest piece of data that can be stored in memory. It can hold either 1 or 0. A byte
consists of eight bits.

A char variable occupies two bytes in memory.

An int and a float take four bytes of memory each.

Variables of long and double types use eight bytes each.

Only one bit is required to store the value of boolean variable.

Numeric data types that take more bytes can store larger numbers.

3.3. Creation of a Pet


Let’s design and create a class Pet . First we need to decide what actions our pet will be able to do. How about
eat, sleep, and speak? We’ll program these actions in the methods of the class Pet . We’ll also give our pet the
following attributes: age, height, weight, and color.

It’s time for hands-on work. Start IDEA IDE and create a new project as explained in Chapter 2. This time name
it MyPet instead of Hello . Click on the src folder in IDEA and create a Java class called Pet using the menu
File | New | Java Class.

Your screen should look similar to this one:

[Link] 44/303
22/03/2025, 18:48 Programação Java para crianças

Figure 27. MyPet Project

Now we are ready to declare attributes and methods in the class Pet . Java classes and methods enclose their
bodies in curly braces.

To declare variables for class attributes we should pick data types for them. I suggest an int type for the age,
float for weight and height, and String for the pet’s color.

JAVA
public class Pet {

int age;
float weight;
float height;
String color;
}

The next step is to add some methods to this class. Before declaring a method you should decide if it should take
any arguments and should return a value. This is what I suggest:

The method sleep will just print a message Good night, see you tomorrow – it does not need any
arguments and will not return any value.

The same is true for the method eat .It will print the message I’m so hungry, let me have a snack like
nachos!.

The method talk will not be printing any messages, but will prepare a message based on the word or a
phrase passed to this method as an argument. This method will build a phrase using the argument and will
return it back to the calling program.

The new version of the class Pet will look like this:

[Link] 45/303
22/03/2025, 18:48 Programação Java para crianças

JAVA
public class Pet {

int age;
float weight;
float height;
String color;

public void sleep(){


[Link](
"Good night, see you tomorrow!");
}

public void eat(){


[Link](
"I’m so hungry, let me have a snack like nachos!");
}

public String talk(String aWord){


String petResponse = "OK!! OK!! " +aWord;
return petResponse;
}
}

This class represents these friendly little monsters from the "real world":

Figure 28. Little Monster

Let’s talk now about the signatures of each method in detail starting with the method sleep :

public void sleep()

[Link] 46/303
22/03/2025, 18:48 Programação Java para crianças

This method signature tells us that sleep can be called from any other Java class ( because it’s public ). This
method does not return any data (the keyword void ). The empty parentheses mean that this method does not
take any arguments - it does not need any data from the outside world to print the same text.

The signature of the method eat is similar to sleep .

The signature of the method talk looks like this:

public String talk(String aWord)

This method can also be called from any other Java class, but has to return some text, which is prescribed by the
keyword String in front of the method name. Besides, it expects some text data from outside, hence the
argument String aWord .

Figure 29. Little Monster eats

How do you decide if a method should or should not return a value? If a method performs some data
manipulations and has to give the result of these manipulations back to the calling class, it has to return a value.
You may say that the class Pet does not have any calling class! That’s correct, so let’s create one called
PetMaster . We’ll create it in the same IDEA project MyPet.

This class will need a method main to become a runnable program (the class Pet didn’t have one). Remember
from Chapter 2, typing psvm followed by the Tab key will quickly create the method main . We’ll place the
code communicating with the class Pet inside the method main .

NOTE Do not forget to press Ctrl-S (CMD-S on Mac) to save and compile this class!

[Link] 47/303
22/03/2025, 18:48 Programação Java para crianças

JAVA
public class PetMaster {

public static void main(String[] args) {

String petReaction; (1)

Pet myPet = new Pet(); (2)

[Link](); (3)

petReaction = [Link]("Tweet!! Tweet!!"); (4)

[Link](petReaction); (5)

[Link](); (6)
}
}

1. The variable petReaction will store the value returned by the method say .

2. This is how to create an instance of the object Pet using the Java operator new . This line declares a
variable of type Pet - that’s right, you can treat any classes created by you as new Java data types.

3. Calling the method eat on the object Pet . After the instance of Pet was created, the variable myPet
knows its address in memory. So you can call the method eat (as well as any other) on this particular
instance of Pet .

4. If a method returns a value, specify a variable that will store returned value to the left of the equal sign. In
our code it’s petReaction of type String . Such variable should have the same type as the return value
of the method.

5. The value of the variable petReaction is passed as an argument to the method prinln for output.

6. Calling the method sleep on the object Pet .

To run the class PetMaster right-click on its name in the Project view in IDEA, and select the option Run
[Link](). This program will output the following:

I’m so hungry,let me have a snack like nachos! OK!! OK!! Tweet!! Tweet!! Good night, see you tomorrow!

[Link] 48/303
22/03/2025, 18:48 Programação Java para crianças

Figure 30. Tweet, Tweet!

At this point the project MyPet consists of two Java classes: Pet and PetMaster . The role of the class Pet is
to represent attributes and behavior of a pet, while the class PetMaster starts the program, instantiates the
class Pet and calls its methods. Your typical projects will consist of multiple Java classes, but only one of them
will have have the main method, which is the entry point of the application.

3.4. Inheritance – a Fish Can Be a Pet Too


In the real life, every person inherits some features from his or her parents. Similarly, in the Java world you can
also create a new class, based on the existing one. The class Pet will help us learn yet another important feature
of Java called inheritance.

The class Pet can include behaviors and attributes that are shared by many pets – all of them eat and sleep,
some of them make sounds, their skin has different colors, and so on. On the other hand, not all pets are the
same. Dogs bark, fish swim and don’t make sounds, and parakeets speak better than dogs. But all of them eat
and sleep. That’s why it’s easier to create a class Fish that will inherit some common behavior and attributes
from the class Pet , rather than creating Dog , Parrot or Fish from scratch every time.

Java has a special keyword extends that will do the trick. Create a new class Fish in IDEA and then add to
its declaration extends Pet so it’ll look as follows:

JAVA
class Fish extends Pet{

[Link] 49/303
22/03/2025, 18:48 Programação Java para crianças

This class Fish is a subclass of the class Pet . Accordingly, the class Pet is a superclass of the class Fish .
In other words, you use the class Pet as a template for creating a class Fish . The keyword extends defines
relationship between classes. Since our Fish extends a Pet , we can say that a fish is a pet. But we can’t say
that a pet is a fish.

Even if you will leave the class Fish empty as it is now, you can still use every method and attribute inherited
from the class Pet , because a fish is a pet! Take a look, we’re creating an instance of the object Fish and are
calling its method sleep :

JAVA
Fish myLittleFish = new Fish();
[Link]();

Even though we have not declared any methods in the class Fish yet, we call (invoke) the method sleep ,
which was declared in its superclass Pet ! In Java all classes are automatically inherited from the class
Object . Even though we’ve declared the class Pet without using the keyword extends it still extends the
class Object . With the keyword extends you can build class hierarchies. For example, many animal classes
can extend the class Pet .

Figure 31. Class Hierarchy

Let’s not forget, however, that we’ve created the class Fish as a subclass of Pet , because we wanted to add
some additional features that only fish have and reuse some of the code that we wrote for a general [Link]
instance, not all pets can dive, but fish certainly can. Let’s add a new method dive to the class Fish .

[Link] 50/303
22/03/2025, 18:48 Programação Java para crianças

JAVA
public class Fish extends Pet {

int currentDepth=0;

public int dive(int howDeep){

currentDepth=currentDepth + howDeep;
[Link]("Diving for " +
howDeep + " feet");
[Link]("I'm at " + currentDepth +
" feet below sea level");

return currentDepth;
}
}

O método dive tem um argumento (também conhecido como parâmetro) howDeep que diz ao peixe o quão
fundo ele deve ir. Também declaramos uma variável de classe currentDepth que armazenará e atualizará a
profundidade atual toda vez que você chamar o método dive . Este método retorna o valor atual da variável
currenDepth para a classe que faz a chamada. O sinal de mais nas pintln linhas não é sobre adição - estamos
construindo sequências de caracteres concatenando suas partes.

Usando o IDEA, crie outra classe chamada FishMaster que ficará assim:

JAVA
public class FishMaster {

public static void main(String[] args) {

Fish myFish = new Fish();

[Link](2);
[Link](3);

[Link]();
}
}

O método main instancia o objeto Fish e chama seu método dive duas vezes com argumentos diferentes -
dois e três. Depois disso, ele chama o método sleep . Quando você executa o programa FishMaster , ele
imprime as seguintes mensagens:

TEXT
Diving for 2 feet
I'm at 2 feet below sea level
Diving for 3 feet
I'm at 5 feet below sea level
Good night, see you tomorrow

[Link] 51/303
22/03/2025, 18:48 Programação Java para crianças

Você notou que além dos métodos definidos na classe Fish , o FishMaster também chama o método sleep
de sua superclasse Pet ? É disso que se trata a herança – você não precisa copiar e colar o código da classe
Pet – basta usar a palavra-chave extends , e a classe Fish pode usar Pet os métodos de !

Figura 32. Qual é a profundidade atual?

Mais uma coisa, mesmo que o método dive retorne o valor de currentDepth , nosso FishMaster não o usa.
Tudo bem, porque nossa classe `FishMaster` não usa o valor retornado, mas pode haver algumas outras classes
que também usarão a classe Fish , e elas podem achar útil saber a profundidade atual. Por exemplo, pense em
uma classe FishTrafficDispatcher que tem que saber as posições de outros peixes sob o mar antes de dar
permissões para mergulhar para evitar acidentes de trânsito.

3.5. Substituição de método


Como você sabe, peixes não falam, mas nossa classe Fish foi herdada da classe Pet que tem o método talk .
Isso significa que nada impede você de escrever [Link](); .

Você realmente quer que nossos peixes falem? Se você não quer que isso aconteça, a classe Fish tem que
sobrescrever o Pet comportamento típico do - o método talk . Se você declarar um método com exatamente a
mesma assinatura em uma subclasse como em sua superclasse, o método da subclasse será usado em vez do
método da superclasse. Vamos adicionar o seguinte método talk à classe Fish .

JAVA
public String talk(String something){
return "Don't you know that fish do not talk?";
}

Agora adicione as três linhas a seguir ao método main da classe FishMaster (depois de criar a instância do
Fish ):

JAVA
String fishReaction;
fishReaction = [Link]("Hello");
[Link](fishReaction);

[Link] 52/303
22/03/2025, 18:48 Programação Java para crianças

Execute o programa e ele imprimirá

Don’t you know that fish do not talk?

Isso prova que Pet o método de talk foi substituído ou, em outras palavras, suprimido.

Uau! Aprendemos muito neste capítulo – vamos dar uma pausa.

3.6. Desafie-se
1. Usamos a variável do tipo int to para armazenar o preço na classe VideoGame . Existe um tipo de dado
primitivo mais adequado para armazenar preços?

2. Crie um novo projeto no IDEA chamado chapter3 e uma nova classe Java Car com os seguintes métodos:

public void start()

public void stop()

public int drive(int howlong)

O método drive tem um argumento - o tempo de condução. O método tem que retornar a distância total
percorrida pelo carro no tempo especificado. Use a seguinte fórmula para calcular a distância: distance =
howlong*60; . Use a declaração return distance como a última linha no método drive .

3. Execute este programa usando o menu Executar no IDEA.

4. Escreva outra classe CarOwner com o método main que cria uma instância do objeto Car e chama seus
métodos. O resultado de cada chamada de método tem que ser impresso usando [Link]() .

5. Crie uma subclasse de Car named JamesBondCar e sobrescreva o método drive lá. Agora use a seguinte
fórmula para calcular a distância: distance = howlong*180;

Seja criativo, imprima algumas mensagens engraçadas do método drive !

6. Crie uma instância da classe JamesBondCar no main método de CarOwner . Execute novamente o
programa CarOwner para ver se ele chama o método substituído drive . :toc-placement!: :imagesdir: .

[Link] 53/303
22/03/2025, 18:48 Programação Java para crianças

4. Blocos de construção Java


Classes são as principais construções em Java, mas você precisa conhecer elementos menores que ajudam a
programar o comportamento e o fluxo do programa. Você precisa saber como seu programa foi comentado para
que outras pessoas possam entender suas intenções (programadores geralmente trabalham em equipes e ajudam
uns aos outros). Você precisa saber como escrever código que invocará um método ou outro dependendo de
certas condições. Neste capítulo, mostrarei alguns elementos Java que você precisa conhecer e aplicar em
praticamente qualquer projeto.

4.1. Comentários do programa


Você pode adicionar qualquer comentário de texto ao seu programa para explicar para que serve uma linha,
método ou classe em particular. Primeiro, outra pessoa pode ler seu programa, então os comentários ajudariam a
entender suas intenções. Segundo, mesmo o autor do código não consegue se lembrar de todos os programas que
ele ou ela escreveu. Além disso, se um programador profissional decidir mudar de empregador, seria legal deixar
um código bem comentado para trás.

Existem três tipos diferentes de comentários - comentários de linha única, comentários de bloco e comentários
javadoc. Eis para que servem:

Se o seu comentário couber em uma linha, comece-o com duas barras:

JAVA
// This method calculates the distance between A and B.

Se você quiser escrever comentários de várias linhas, em vez de começar cada linha com duas barras, basta
cercar o texto inteiro com estes símbolos: /* e */ , por exemplo:

JAVA
/* Now we'll handle the current
position of the Fish.
*/

O Java vem com um programa especial javadoc que pode extrair todos os comentários dos seus programas em
um arquivo de ajuda separado que pode ser exibido por qualquer navegador da Web. Este arquivo pode ser usado
como uma documentação técnica para seus programas. Tais comentários são colocados entre os símbolos /** e
*/ . Observe os dois asteriscos após a primeira barra. Somente os comentários mais importantes, como a
descrição de uma classe ou um método, devem ser colocados entre esses símbolos.

[Link] 54/303
22/03/2025, 18:48 Programação Java para crianças

JAVA
/** This method calculates the discount that depends
on the price paid. If the price is more than $100,
give the user 20% off, otherwise only 10%.
*/

The javadoc tool can process your code, extract all comments that start with /** and create program
documentation that can be published online or kept locally on the company server. We are not going to use
javadoc in this book, but if you’re interested in learning more about this tool, read Oracle’s tutorial How to Write
Doc Comments for the Javadoc Tool ([Link]

From now on, I’ll be adding comments to code samples to give you a better idea how and where to use them.

4.2. Making Decisions


We always make decisions in our life: If she is going to tell me this – I’m going to answer that, otherwise I’ll do
something else. You can write a Java program that will "make decisions" with the help of if and switch
statements. You can also build more complex either-or conditions using logical operators.

4.2.1. The if Statement


Java has an if statement that checks if a particular expression is true or false .

Based on the result of evaluating this expression, your program execution forks, and only the relevant portion of
the code will be invoked.

For example, if the expression Do I want to go to grandma’s? is true , turn to the left, otherwise turn to the
right.

[Link] 55/303
22/03/2025, 18:48 Programação Java para crianças

Figure 33. The fork

Take a look at the following code sample. If an expression inside the parentheses is true , JVM will execute the
code between the first pair of curly braces, otherwise it goes to the code after the else statement. In other
words, if the value of the variable totalSpent is more than a hundred, give a 20% discount, otherwise take
only 10% off.

[Link] 56/303
22/03/2025, 18:48 Programação Java para crianças

JAVA
// Assume that the method getTotalAmount()
// adds up the prices from your shopping cart

int totalSpent = getTotalAmount();


float discountedPrice;

if (totalSpent > 100){


discountedPrice=totalSpent*0.8;
[Link]("You’ll get a 20% discount");
}
else{
discountedPrice=totalSpent*0.9;
[Link]("You’ll get a 10% discount");
}

[Link]("Your discounted price is " + discountedPrice);

Let’s modify the method dive() in the class Fish from Chapter 3 to make sure that our fish is not allowed to
dive below 100 feet:

JAVA
public class Fish extends Pet {

int currentDepth=0;

public int dive(int howDeep){


currentDepth=currentDepth + howDeep;
if (currentDepth > 100){
[Link]("I am a little fish and "
+ " can't dive below 100 feet");
currentDepth=currentDepth - howDeep;
}else{
[Link]("Diving for " + howDeep +
" feet");
[Link]("I'm at " + currentDepth +
" feet below the sea level");
}
return currentDepth;
}

public String talk(String something){


return "Don't you know that fish do not talk?";
}
}

Now just make a small change in the class FishMaster – let it try to make our fish go deep under the sea:

[Link] 57/303
22/03/2025, 18:48 Programação Java para crianças

JAVA
public class FishMaster {

public static void main(String[] args) {

Fish myFish = new Fish();

// Try to have the fish go below 100 feet

[Link](2); // go 2 feet down


[Link](97); // go another 97 feet down
[Link](3); // go 3 more feet down

[Link]();
}
}

Run this program and it’ll print the following on the system console:

HTML
Diving for 2 feet.
I'm at 2 feet below the sea level.
Diving for 97 feet.
I'm at 99 feet below the sea level.
I am a little fish and can't dive below 100 feet.
Good night, see you tomorrow.

4.2.2. Logical Operators


Sometimes, to make a decision you may need to check more than just one conditional expression, for example if
the name of the state is Texas or California, add the state sales tax to the price of every item in the store. This is
an example of the logical or – either Texas or California.

In Java the sign for a logical or is one or two vertical bars. It works like this – if any of the two conditions is
true , the result of the entire expression is also true .

In the following examples I use a variable of type String , which has a method equals() that compares the
values of two strings. I use it to see whether the value of the variable state is "Texas" or "California":

JAVA
if ([Link]("Texas") | [Link]("California"))
{
// do something
}

You can also rewrite this if statement using two vertical bars:

[Link] 58/303
22/03/2025, 18:48 Programação Java para crianças

JAVA
if ([Link]("Texas") || [Link]("California"))
{
// do something
}

The difference between these two examples is that if you use two bars, and the first expression is true , the
second expression won’t even be checked. If you place just a single bar, JVM will evaluate both expressions.

The logical and is represented by one or two ampersands ( && ) and each expression in the parentheses must be
true to make the entire expression true . For example, charge the sales tax only if the state is New York and
the price is more than $110. Both conditions must be true at the same time:

JAVA
if ([Link]("New York") && price >110)
{
// do something
}

or

JAVA
if ([Link]("New York") & price >110)
{
// do something
}

If you use double ampersand and the first expression is false , the second one won’t even be checked, because
the entire expression will be false anyway. With the single ampersand both expressions will be evaluated.

The logical not is also known as negation and is represented by the exclamation point. The logical not
changes expression to the opposite meaning. For example, if you want to perform some actions only if the state
is not New York, use this syntax:

JAVA
if (![Link]("New York")) {
// do something
}

The following two expressions will produce the same result, because more than 50 and not less than or equal to
50 have the same meaning:

[Link] 59/303
22/03/2025, 18:48 Programação Java para crianças

JAVA
if (price > 50) {
// do something
}

if (!(price <= 50)) {


// do something
}

In the second example the logical not is applied to the expression in parentheses.

4.2.3. Conditional operator


There is another type of an if-statement called conditional operator, which allows you to assign a value to a
variable based on the expression that ends with a question mark. It’s like you’re asking, "Is this true?". If such an
expression is true , the value after the question mark is used, otherwise the value after the colon is assigned to
the variable on the left:

discount = price > 50? 10:5;

If the price is greater than fifty, the variable discount will get a value of 10, otherwise discount will have a
value of 5. It’s just a shorter replacement of the following if statement:

JAVA
if (price > 50){
discount = 10;
} else {
discount = 5;
}

4.2.4. Using else if


You are also allowed to build more complex if statements with several else if blocks. To illustrate this
technique let’s create a new class called ReportCard . This class will have two methods: main() and
convertGrades() with one argument - the school test result. Depending on the number, it should print your
grade like A, B, C, or D.

[Link] 60/303
22/03/2025, 18:48 Programação Java para crianças

JAVA
public class ReportCard {

String studentName;

/**
The method convertGrades has one integer argument - the result of the school test. The method
returns one letter A, B, C or D depending on the argument's value.
*/
public char convertGrades( int testResult){

char grade;

if (testResult >= 90){


grade = 'A';
} else if (testResult >= 80 && testResult < 90){
grade = 'B';
}else if (testResult >= 70 && testResult < 80){
grade = 'C';
}else {
grade = 'D';
}

return grade;
}

public static void main(String[] args){

ReportCard rc = new ReportCard();

char yourGrade = [Link](88);


[Link]("Your first grade is " +
yourGrade);

yourGrade = [Link](79);
[Link]("Your second grade is " +
yourGrade);
}
}

Beside using the else if condition, this example also shows you how to use variables of type char . You can
also see that with the && operator you can check if a number falls into specific range. You can not just write if
testResult between 80 and 89, but with logical and you can check the condition when testResult is greater
than or equal to 80 and less then 89 at the same time:

testResult >= 80 && testResult < 89

Take a guess as to why we could not use the logical or operator here? Say the testResult is 100. It’s greater
than 80, and the above expression would evaluate to true, because for the || operator having one true is enough
to make the entire expression true. But this is not what we want - we need the above expression to be true only if

[Link] 61/303
22/03/2025, 18:48 Programação Java para crianças

the value of testResult is between 80 and 89. The logical and operator does the job by ensuring that both
conditions are true.

4.2.5. The switch Statement


The switch statement sometimes can be used as an alternative to if . The variable after the keyword switch
is evaluated, and program goes only to one of the case statements:

JAVA
public static void main(String[] args){

ReportCard rc = new ReportCard();


[Link] = "Jerry Lee";

char yourGrade = [Link](88);

switch (yourGrade){

case 'A':
[Link]("Excellent Job!");
break;
case 'B':
[Link]("Good Job!");
break;
case 'C':
[Link]("Need to work more!");
break;
case 'D':
[Link]("Change your attitude!");
break;
}
// Some other program code goes here

Say, the value of yourGrade is B . Then the above code will print "Good Job!" and will break out of the
switch statement to continue executing the rest of the program code if any.

Do not forget to put the keyword break at the end of each case statement to make the code jump out of the
switch . For example, if you forget to put the break in the case 'B' block, the above code would print
"Good Job!" followed by "You need to work more!".

[Link] 62/303
22/03/2025, 18:48 Programação Java para crianças

Figure 34. The switch statement

4.3. How Long Will A Variables Live?


Class ReportCard declares a variable grade inside the method convertGrades() . If you declare a
variable inside any method, such variable is called local. This means that this variable is available only for the
code within this method. When the method is complete, this variable automatically gets removed from memory.

Programmers use the word scope to say how long a variable will live, for example you can say that variables
declared inside a method have a local scope. If a variable is declared within the code block surrounded with
curly braces (e.g. in the if statement), it has a block scope and won’t be visible outside of this block.

[Link] 63/303
22/03/2025, 18:48 Programação Java para crianças

If a variable has to be reused by several method calls, or it has to be visible from more than one method in a
class, you should declare such a variable outside of any method. In the class Fish from Chapter 3, the
currentDepth is a member variable. The member variable currentDepth is alive until the instance of the
object Fish exists in the computer’s memory. You can call currentDepth a instance variable, because its
declaration doesn’t include the keyword static , which we’ll discuss shortly.

Member variables can be shared and reused by all methods of the class, and we can make them visible from
external classes too, if need be. For example the method main of the class ReportCard includes the statement
[Link]() . It uses the class variable out that was declared in the Java class System .

4.3.1. The Keyword static


Wait a minute! Can we use a member variable out from the class System if we haven’t even created an
instance of this class? Yes we can, if the class System declares the variable out with a keyword static .

When you start any Java program it loads the definition of the required classes in memory. The definition of a
class can be used for creation of one or more instances of this class. For example:

JAVA
ReportCard rc = new ReportCard();
[Link] = "Jerry Lee";

ReportCard rc2 = new ReportCard();


[Link] = "Sarah Smith";

In this example we have two instances of the class ReportCard , and each of them has its own value in the
variable studentName , which is an instance variable. Now, let’s change the declaration of this variable by
adding the keyword static :

static String studentName;

In this case both instances of the ReportCard would share the same variable studentName , and the above
code would first assign "Jerry Lee" to this variable, and then it would be replaced with "Sarah Smith". This
doesn’t seem like a good idea does it?

Moreover, if the declaration of a member variable or a method starts with static , you do not have to create an
instance of this class to use such a variable or a method. Static members of a class are used to store the values
that are the same for all instances of the class.

For example, the method convertGrades should be declared as static in the class ReportCard , because
its code does not use member variables to store values specific to a particular instance of the class.

[Link] 64/303
22/03/2025, 18:48 Programação Java para crianças

JAVA
public static char convertGrades( int testResult){
// the code of this method goes here
}

There is no need to create instances to call static methods or access static variables. Just write the name of the
class followed by the dot and the name of the static member:

char yourGrade = [Link](88);

Here’s another example: Java has a class Math that contains several dozen mathematical methods like sqrt ,
sin , abs and others. All these methods are static and you do not need to create an instance of the class
Math to invoke them, for example:

double squareRoot = [Link](4.0);

4.4. Special Methods: Constructors


You’ve already learned that Java uses the operator new to create instances of objects in memory, for example:

Fish myFish = new Fish();

Parentheses after the word Fish tell us that this class has some method called Fish . Yes, there are special
methods that are called constructors, and these methods have the following features:

Constructors are special methods that are called only once during construction of the object in memory.

They must have the same name as the class itself.

They do not return a value, and you do not even have to use the keyword void in the constructor’s
declaration.

Any class can have more than one constructor. If you do not create a constructor for the class, Java automatically
creates one during the compilation time - it’s so-called default no-argument constructor. That’s why Java
compiler has never complained about the statements new Fish() or new ReportCard() , even though
neither class Fish nor class ReportCard has any explicitly declared constructor.

In general, constructors are used to assign initial values to member variables of the class, for example the next
version of the class Fish has a one-argument constructor that just assigns the argument’s value to the instance
variable currentDepth for future use.

[Link] 65/303
22/03/2025, 18:48 Programação Java para crianças

JAVA
public class Fish extends Pet {
int currentDepth;

// This is constructor
Fish(int startingPosition){
currentDepth=startingPosition;
}
}

Now the class FishMaster can create an instance of the Fish and assign the initial position of the fish. The
next example creates an instance of the Fish that is “submerged” 20 feet under the sea:

Fish myFish = new Fish(20);

If a constructor with arguments has been defined in a class, you can no longer use the default no-argument
constructor. If you’d like to have a constructor without arguments - write one.

4.5. The Keyword this


The keyword this is useful when your code needs to refer to the instance of the object, where this code is
running. Look at the next code example, which is a slight modification of the previous one:

JAVA
class Fish {
int currentDepth ;

Fish(int currentDepth){
[Link] = currentDepth;
}
}

Have you noticed that the member variable and the constructor’s argument have the same name? The keyword
this helps to avoid name conflicts. In this code sample [Link] refers to the object’s member
variable currentDepth , while the currentDepth refers to the argument’s value. In other words, the code
points at the current instance of the Fish object.

[Link] 66/303
22/03/2025, 18:48 Programação Java para crianças

Figure 35. I’m this object

You’ll see another important example of using the keyword this in Chapter 6 in the section How to Pass Data
Between Classes.

4.6. Arrays
An array is an object that holds several values of the same type - primitives or objects. Let’s say your program
has to store the names of four game players. Instead of declaring four different String variables, you can
declare one String array that has four elements. Arrays are marked by placing square brackets either after the
variable name, or after the data type:

String [] players;

[Link] 67/303
22/03/2025, 18:48 Programação Java para crianças

or

String players[];

These declarations just tell the Java compiler that you are planning to store several text strings in the array
players . Each element has its own index (position number) starting from zero. The next sample actually
creates an instance of an array that can store four String elements and assigns the values to the elements of
this array:

JAVA
players = new String [4];

players[0] = "David";
players[1] = "Daniel";
players[2] = "Anna";
players[3] = "Gregory";

You must declare the size of the array before assigning values to its elements. If you do not know in advance
how many elements you are going to have, you cannot use arrays, but you should look into other classes - Java
collections. For example the ArrayList object does not require you to announce the exact number of elements
in advance. I’ll show you some examples of using the ArrayList collection in Chapter 10 about data
collections.

Any array has an attribute called length that stores the number of elements in this array, and you can always
find out how many elements are there:

int totalPlayers = [Link];

If you know all the values that will be stored in the array at the time when you declare it, Java allows you to
declare and initialize such array in one shot:

String [] players = {"David", "Daniel", "Anna", "Gregory"};

[Link] 68/303
22/03/2025, 18:48 Programação Java para crianças

Figure 36. The array of players

Imagine that the second player is a winner and you’d like to write the code to congratulate this kid. If the players’
names are stored in an array get its second element:

JAVA
String theWinner = players[1];
[Link]("Congratulations, " + theWinner + "!");

The output from these two lines of code will look like this:

Congratulations, Daniel!

Do you know why the second element has the index [1]? Of course you do, because the index of the first
element is always [0].

The array of players in our example is called one-dimensional array. Imagine the players sitting like ducks in a
row. The single dimension is the seat number here. If the players (or game spectators) will occupy several rows,
then we’ll have two dimensions - the row number and a set number within the row. This is the case where we’d
need to declare a two-dimensional array. Java allows creation of multi-dimensional arrays, and I’ll show you
how to do this in Chapter 10.

4.7. Repeating Actions with Loops


A loop is a language construct that allows to repeat the same action multiple times. For example, if we need to
print congratulation to several winners, the printing code should be invokes several times in a loop. When you
know in advance how many times this action has to be repeated, you can use a loop with a keyword for :

JAVA
int totalPlayers = [Link];
int counter;

for (counter=0; counter < totalPlayers; counter++){


String thePlayer = players[counter];
[Link]("Congratulations,"+
thePlayer+"!");
}

The above code means the following:

Print the value of the element from the players array whose number is the same as the current value of the
counter . Start from the element number 0: _ counter=0) , _and increment the value of the counter by
one: (counter++) . Keep doing this while the counter is less than totalPlayers`:
`counter<totalPlayers .

[Link] 69/303
22/03/2025, 18:48 Programação Java para crianças

JVM executes every line between the curly braces and then returns back to the first line of the loop to increment
the counter and check the conditional expression.

There is another flavor of the for loop known as for each loop. It allows the program to repeat the same action
to every element of the collection without even knowing how many are there. You are basically saying, do this
for each [Link] for-each loop allows to congratulate players in a more concise manner:

JAVA
for (String pl: players){
[Link]("Congratulations," + pl +"!");
}

You can read the above code as follows:

The variable pl has the type String - the same as as the array’s elements. Use this variable as a cursor, point
it to each element in the array players one by one and repeatedly execute the code inside the curly brackets
for the current element.

There is another keyword for writing loops - while . In these loops you do not have to declare exactly how
many times to repeat the action, but you still need to know when to end the loop. Let’s see how we can
congratulate players using the while loop that will end when the value of the variable counter becomes
equal to the value of totalPlayers :

JAVA
int totalPlayers = [Link];
int counter=0;

while (counter< totalPlayers){


String thePlayer = players[counter];
[Link]("Congratulations, "
+ thePlayer + "!");
counter++;
}

In Chapter 9 you’ll learn how to save the data on the disk and how to read the saved data back into computer’s
memory. If you read game scores from the disk file, you do not know in advance how many scores were saved
there. Most likely you’ll be reading the scores using the while or for-each loop, which don’t require you to
state the number of iterations upfront.

You can also use two important keywords with loops: break and continue .

As with switch statements, the keyword break is used to jump out of the loop when some particular
condition is true . Let’s say we do not want to print more than 3 congratulations, regardless of how many
players we’ve got. In the next example, after printing the array elements 0, 1 and 2, the break will make the
code go out of the loop and the program will continue from the line after the closing curly brace.

[Link] 70/303
22/03/2025, 18:48 Programação Java para crianças

The next code sample has the double equal sign == in the if statement. This means that you are comparing the
value of the variable counter with number 3. A single equal sign in the here would mean assigning the value
of 3 to the variable counter . Placing = in an if statement instead of == is a very tricky mistake, and it can
lead to unpredictable program errors that may be dificcult to find.

JAVA
int counter =0;
while (counter< totalPlayers){

if (counter == 3){
break; // Jump out of the loop
}
String thePlayer = players[counter];
[Link]("Congratulations, "+thePlayer+ "!");
counter++;
}

The keyword continue allows the code to skip some code lines and return back to the beginning of the loop.
Imagine that you want to congratulate everyone but David – the keyword continue will return the program
back to the beginning of the loop:

JAVA
while (counter< totalPlayers){
counter++;

String thePlayer = players[counter];

if ([Link]("David"){
continue;
}
[Link]("Congratulations, "+ thePlayer+ !");
}

There is yet another type of the while loop that starts with the word do , for example:

JAVA
do {
[Link]("Congratulations, "+
players[counter] + !");
counter++;

} while (counter< totalPlayers);

Such loops check an expression after executing the code between curly braces, which means that code in the
loop will be executed at least once. Loops that start with the keyword while might not be executed at all if the
loop expression is false to begin with.

[Link] 71/303
22/03/2025, 18:48 Programação Java para crianças

4.8. Challenge Yourself


1. Create a new IntelliJ Idea Java project as described in Chapter 2. Name it Chapter4 .

2. In the src directory of the project create a new class (the menu File | New) named TemperatureConverter.

3. Add the method convertTemp() so the code of the class looks like this:
JAVA
public class TemperatureConverter {
public static float convertTemp (float temperature,
char convertTo) {
}
}

4. Write the if statement inside the method convertTemp to check the value of the argument convertTo . If
it’s F , the temperature has to be converted to Fahrenheit, and if it’s C , convert it to Celsius. Return the
result. The method convertTemp should look like this:
JAVA
public static String convertTemp (float temperature, char convertTo) {

if (convertTo=='F'){
return "The temperature in Fahrenheit is " + (9*temperature/5 + 32);
} else if(convertTo=='C') {
return "The temperature in Celsius is " + (temperature - 32) * 5/9;
} else{
return "You can enter either F or C as convertTo argument";
}
}

5. Add the method main using the shortcut psvm + Tab as explained in Chapter 2. It should look like this:
JAVA
public static void main(String[] args) {

[Link]("Converting 21C to Fahrenheit. " + convertTemp(21,'F'));


[Link]("Converting 70F to Celsius. " + convertTemp(70,'C'));

6. Run the program TemperatureConverter using the IDEA menu Run | Run TemperatureConverter. If you
did everything right, you should see the following output on the IDEA console:
EXT
Converting 21C to Fahrenheit. The temperature in Fahrenheit is 69.8
Converting 70F to Celsius. The temperature in Celsius is 21.11111

7. Do a little research to change this program so it always prints the temperature with two digits after the
decimal point. Study Oracle’s tutorial about formatting numeric output: [Link] :toc-
placement!: :imagesdir: .

[Link] 72/303
22/03/2025, 18:48 Programação Java para crianças

5. Interfaces, Lambdas, Abstract and Anonymous Classes


In this chapter I’ll focus on discussing how you can program behavior in Java. Classes have attributes (e.g. color,
number of doors) and exhibit behavior (e.g. eat, sleep, or dive). There is a special group of programming
languages that are called functional (e.g. JavaScript, Scala et al). In these languages you can simply write
functions like eat , sleep , or dive , and these functions can live their independent lives and don’t have to be
declared in classes. In object-oriented languages behavior is implemented in methods defined in classes.

The phrase to implement a method simply means to write code in a method. Starting from Java 8 you can also
program behavior in so called lambda expressions covered later in this chapter.

So far I was declaring and implementing behavior in methods located inside Java classes. But there is a way and
a reason to separate the method declaration from its implementation. Such separation can be done using
interfaces.

5.1. Java Interfaces


While you can just create a Java class and implement all its methods there, a more formal way of declaring the
behavior of the class in a separate interface . Then a class declaration would include the keyword
implements followed by the name of the interface. This is a way to declare an application program interface
(API) - what the class can do - so the programmer can quickly look at the short declaration of the interface rather
than going through a longer code of the class.

For years, Java interfaces were used mainly for holding method declarations and final static variables. For
example, the interface Talkable contains the declaration of just one method talk :

JAVA
interface Talkable{
public void talk();
}

Since the method talk is not implemented here, it’s called abstract.

To create a new interface in IDEA, select the menu File | New | Java class and select Interface
NOTE
in the Kind box.

[Link] 73/303
22/03/2025, 18:48 Programação Java para crianças

Figure 37. Creating an interface in IDEA

You should be thinking, "What’s the point of simply declaring a method without implementing it?" The thing is
that more than one class can exhibit the same behavior. For example, a dog, a cat, and a parrot can "talk". But
they "implement it" differently. A parrot can repeat words, while dogs bark. Cats talk by meowing. Accordingly
you can declare three classes that will implement Talkative interface differently, as shown below:

JAVA
public class Parrot implements Talkative {
public void talk(){
[Link]("My name is Kesha.");
}
}

public class Dog implements Talkative {


public void talk(){
[Link]("Bark! Bark-bark!");
}
}

public class Cat implements Talkative {


public void talk(){
[Link]("Meow! Meow!");
}
}

These three classes use the Java keyword implements , which means they promise to implement all abstract
methods in the interface(s) listed after the keyword implements otherwise the Java compiler will complain:
"You promised to implement all abstract methods from Talkable , where are they? Keep your promise!"

What if we need to create the class Fish that uses interfaces? Fish don’t talk. But they swim. Dogs can talk
(bark) and swim, right? Why won’t we declare yet another interface Swimmable with the methods swim and
dive ?

JAVA
public interface Swimmable {

public void swim(int howFar);

public void dive(int howDeep);


}

Now let’s leave the parrots alone. Let’s create a new class Fish and change the class Dog just a little bit. The
Fish will implement Swimmable and the Dog will implement two interfaces:

[Link] 74/303
22/03/2025, 18:48 Programação Java para crianças

JAVA
public class Fish implements Swimmable {
public void swim(int howFar){
[Link]("OK, will swim " + howFar + " feet");
}
public void dive(int howDeep){
[Link]("OK, will dive " + howDeep + " feet");
}
}

public class Dog implements Talkative, Swimmable {


public void talk(){
[Link]("Bark! Bark-bark!");
}

public void swim(int howFar){


[Link]("Will swim about a half of this distance: " + howFar/2 + " feet");
}

public void dive(int howDeep){


[Link]("C'mon, don't ask a dog to dive, please!");
}
}

When a class implements several interfaces, make sure to implement each and every abstract method declared in
these interfaces. A class can extend another class and implement interfaces at the same time, for example:

JAVA
class Fish extends Pet implements Swimmable{

// your code implementing swim(), dive()


// and any other methods goes here
}

Java includes several interfaces that don’t declare any methods (e.g. Serializable ). They
are called marker interfaces. You don’t need to implement any methods in classes that
NOTE
implement marker interfaces. They are used by the Java compiler internally to generate the
byte code in a special way.

5.1.1. Default Methods in Interfaces


To tell you the truth, I don’t like the fact that I had to implement the method dive in the class Dog . The dogs
I’ve seen can’t dive. Can the interface Swimmable be changed so I’m not forced to write the implementation of
the method dive in the class Dog ? Yes, it can. Java 8 introduced a new keyword default . Now you’re
allowed to write a default implementation of a method in the interface. Such a method won’t be considered
abstract anymore, and you won’t be forced to implement it in your class. Let’s add a default implementation of
the method dive to Swimmable .

[Link] 75/303
22/03/2025, 18:48 Programação Java para crianças

JAVA
public interface Swimmable {

public void swim(int howFar);

public default void dive(int howDeep){


[Link]("Can't dive, sorry");
};
}

Now the class Dog doesn’t have to implement the method dive - the compiler will see a default
implementation and won’t complain. The next version of the class Dog implements only the method swim
from Swimmable .

JAVA
public class Dog implements Talkative, Swimmable {
public void talk(){
[Link]("Bark! Bark-bark!");
}

public void swim(int howFar){


[Link]("Will swim about a half of this distance: " + howFar/2 + " feet");
}
}

There is no need to change the class Fish . It also implements Swimmable , but has its own version of the
method dive , which will override the default implementation of the dive from Swimmable . You can still
invoke the method dive on the instance of the Dog class - the default implementation will be invoked. The
next class PetMaster will demonstrate this.

JAVA
public class PetMaster {
public static void main(String[] args) {

Dog myDog = new Dog();


[Link]();
[Link](7);
[Link](2); // will use default method

Fish myFish = new Fish();


[Link](50);
[Link](20);
}
}

Run this program and you’ll see the following output on the console:

[Link] 76/303
22/03/2025, 18:48 Programação Java para crianças

JAVA
_Bark! Bark-bark!
Will swim about a half of this distance: 3 feet
Can't dive, sorry
OK, will swim 50 feet
OK, will dive 20 feet

The message "Can’t dive, sorry" was printed by the default method dive from the interface Swimmable .

Figure 38. Dogs can’t dive

5.1.2. Static Methods in Interfaces


Starting from Java 8, interfaces are also allowed to include static methods, which are not specific to any instance
and can be used only internally by other methods of the interface. The following example illustrates the use of a
static method in the interface. Now the default implementation of the method dive won’t just reject an offer to
swim, but will check the current month: if it’s June, July, or August then diving is allowed because the water
should be warm.

The modified version of the Swimmable interface includes a static method isSummer that checks the current
month and returns true if it’s June, July, or August. I’m using the Java Date and Time API here. The default
method dive calls the static method isSummer and either agrees or disagrees to dive depending on the time of
the year.

[Link] 77/303
22/03/2025, 18:48 Programação Java para crianças

JAVA
import [Link];
import [Link];

public interface Swimmable {

public void swim(int howFar);

public default void dive(int howDeep){

if (isSummer()){
[Link]("OK, will dive. The water should be warm.");
} else {
[Link]("Can't dive, sorry. The water's cold for diving.");
}
};

// Check if it's summer now


static boolean isSummer(){
Month month = [Link]().getMonth();
if (month == [Link] || month == [Link] || month == [Link]){
return true;
} else{
return false;
}
}
}

O método isSummer usa a classe LocalTime para obter Month , que tem um tipo de dado enum que eu não
usei até agora. É um tipo de dado especial para representar um número fixo de alguns valores, como meses neste
caso. Há apenas 12 meses, e a API Java Date and Time os listou por nome no enum chamado Month . Os únicos
valores permitidos aqui são [Link] para [Link] . Usar enums torna os programas mais
legíveis - é mais fácil lidar com meses por nomes do que por números.

Pacotes e instruções de importação


Java vem com muitas classes úteis que são organizadas em pacotes. Alguns pacotes incluem classes
responsáveis ​por desenhar, enquanto outros pacotes têm classes para trabalhar com a Internet, e assim por
diante. Por exemplo, a classe LocalDate está localizada no pacote chamado [Link] , e o nome
completo da classe LocalDate é [Link] .

Para que o compilador saiba onde a classe LocalDate está localizada, você pode especificar o nome
completo da classe, por exemplo:

JAVA
[Link] todaysDate = [Link]();

[Link] 78/303
22/03/2025, 18:48 Programação Java para crianças

Mas essa sintaxe é difícil de ler, então usamos as import instruções acima da declaração de classe para
deixar o compilador saber a localização da classe, interface ou enumeração. Por exemplo:

JAVA
import [Link];

Agora você pode usar apenas o nome da classe sem precisar especificar o nome do pacote:

JAVA
LocalDate todaysDate = [Link]();

Os pacotes são armazenados em diretórios e subdiretórios no disco. Se você vir um nome de classe
completo, [Link] significa que essa classe foi criada originalmente no subdiretório time
do diretório java .

De agora em diante, usaremos pacotes e a declaração import em todos os capítulos deste livro. Se você
quiser colocar sua classe em um pacote, basta criar um subdiretório (por exemplo, pets ) e adicionar uma
package declaração no topo da definição de sua classe, por exemplo:

JAVA
package pets;

class Dog{
// your code goes here
}

Uma última coisa: Crianças preguiçosas usam os curingas em instruções import. Em vez de escrever uma
instrução import por classe, elas usariam um asterisco:

JAVA
import [Link].*;

Isso significa que as definições necessárias para meu programa estão localizadas no pacote [Link] .
Claro, escrever uma declaração import em vez de várias parece atraente, mas a legibilidade do programa
sofre. Pacotes podem ter dezenas de classes e é melhor declarar explicitamente quais classes seu programa
usa.

[Link] 79/303
22/03/2025, 18:48 Programação Java para crianças

Figura 39. Pacotes Java

5.1.3. Variáveis ​estáticas finais em interfaces


Além das declarações de método, métodos padrão e estáticos, você pode adicionar static final variáveis ​à
declaração da interface. Essas variáveis ​podem ser usadas pelo código dentro da interface ou nas classes que a
implementam. Por exemplo, a interface Swimmable pode definir a profundidade máxima permitida para
mergulho. Aqui está mais uma versão da interface Swimmable :

[Link] 80/303
22/03/2025, 18:48 Programação Java para crianças

JAVA
public interface Swimmable {

static final int MAX_DEPTH = 10; // in feet

public void swim(int howFar);

public default void dive(int howDeep){


if (howDeep > MAX_DEPTH){
[Link]("Can't dive, sorry");
}
};
}

Uma classe que implementa também Swimmable pode usar o valor de . MAX_DEPTH

5.1.4. Interfaces Funcionais


If an interface has only one abstract method declared (default and static methods don’t count) it’s called
functional interface. Both Talkative and Swimmable are examples of a functional interface - each has only
one abstract method. Java 8 introduced a special way of implementing functional interfaces using lambda
expressions, which we’ll discuss later in this lesson.

5.2. Abstract Classes


If a method is not implemented we call it abstract, but classes can be declared abstract too, and Java has the
keyword abstract for this. An abstract class is called abstract if it was declared with the keyword abstract ,
for example:

JAVA
public abstract class Animal{
// some code goes here
}

If a class is declared as abstract, you can’t create an instance of it. Typically, abstract classes have some non-
implemented methods that are also declared with the abstract keyword:

[Link] 81/303
22/03/2025, 18:48 Programação Java para crianças

JAVA
public abstract class Animal {

String animalClass;
String name;

public void setName(String name){


[Link] = name;
}

public void sleep(){


[Link]("The " + name +
" is tired and goes to sleep.");
}

abstract public void talk();


}

The class Animal has two implemented methods: setName and sleep and one abstract method talk .
Since the abstract class can not be instantiated, the programmer has to create a descendant class and implement
the method talk there if he or she wants to create an instance of such a class, for example:

JAVA
public class Dog extends Animal{
public void talk(){
[Link]("Bark! Bark-bark!");
}
}

Strictly speaking, it’s not a must to implement the method talk in the class Dog , but in this case Dog remains
abstract and can’t be instantiated. Maybe the programmer wants to create a class Puppy that extends Dog and
implements the method talk there?

And again you might be wondering, "Why complicate a programmer’s life by declaring non-implemented
methods?" If you want to build a hierarchy of classes that extend from Animal you might want to declare an
unified method signature, so each class ( Dog , Parrot , Fish et al.) will have the same way of initiating the
talk.

5.2.1. What’s the difference between abstract classes and interfaces?


Abstract classes and interfaces allow to create classes that implement polymorphism, which is an advanced topic
and won’t be covered in this book. You can read about it in Oracle’s tutorial
([Link] if interested. Abstract classes allow you to
implement some common static or instance-specific behavior, e.g. setName and sleep in the vertical class
hierarchy.

[Link] 82/303
22/03/2025, 18:48 Programação Java para crianças

Interfaces can’t have instance methods, but they don’t enforce any class hierarchy. So you can have a class Dog
that extends any class, while implementing an interface Talkative that declares the method talk .

5.3. Anonymous Classes


If you need to use an object of certain type only once, you can kill two birds with one stone: declare an
anonymous class and create an instance of it. In this case you don’t even need to give a class a name, hence why
it’s anonymous. I’ll show you an example of a program that’s first written without and then written with them.

Let’s say I want to write a simple calculator in Java. In chapters 8 and 9 you’ll create a real calculator with the
graphical Users Interface (GUI), but for now I’ll show you how to program operations such as addition and
subtraction. The multiplication and division operations can be programmed similarly, so I won’t be
implementing these operations.

I want to keep these examples in the package called calc . You can create a subdirectory named calc in your
project and save your classes there. The other option is to right-click on the folder src in your IDEA project and
select the menu New | Package and enter the package name there:

Figure 40. Creating a new package in IDEA

First comes the version that doesn’t use anonymous classes - I’ll just use one method for each operation. The
code of the class Calculator is pretty simple. Note the first line that declares the package where the class
Calculator belongs.

[Link] 83/303
22/03/2025, 18:48 Programação Java para crianças

JAVA
package calc;

public class Calculator {

static double addTwoNumbers (double first, double second){


double result = first + second;
[Link]("" + first + " + " +
second + " = " + result );
return result;
}

static double subtractTwoNumbers (double first, double second){


double result = first - second;
[Link]("" + first + " - " +
second + " = " + result );
return result;
}

public static void main(String[] args) {

addTwoNumbers(3.55, 50.00);
subtractTwoNumbers(3.55, 50.00);
}
}

This class has two methods that manipulate numbers (one per operation), and its main method invokes each
method passing the same values as arguments. After performing the arithmetic operation each method prints the
result. Running this program produces the following output:

JAVA
3.55 + 50.0 = 53.55
3.55 - 50.0 = -46.45

Now let’s redesign this application. Instead of writing a separate method for each operation, I want to write a
generic method that can receive the code of the operation and two numbers to be operated upon. This method
will have three arguments: the arithmetic operation, the first, and the second number.

The operation is a behavior, so let’s declare an interface to represent it using a functional interface with a single
abstract method:

JAVA
package calc;

public interface ArithmeticOperation {

public double performOperation(double a, double b);


}

[Link] 84/303
22/03/2025, 18:48 Programação Java para crianças

I’ll write two implementations of the ArithmeticOperation interface using anonymous classes - one for
addition and one for subtraction. I will also write a method calculate that will take three arguments: the
object that implements ArithmeticOperation and two numbers.

JAVA
package calc;

public class CalculatorWithAnonymousClasses {

// The first anonymous class for addition


static ArithmeticOperation addition = new ArithmeticOperation() {
public double performOperation(double first, double second) {
double result = first + second;
[Link]("" + first + " * " +
second + " = " + result );
return result;
}
};

// The second anonymous class for subtraction


static ArithmeticOperation subtraction = new ArithmeticOperation() {
public double performOperation(double first, double second) {
double result = first - second;
[Link]("" + first + " - " +
second + " = " + result );
return result;
}
};

public static double calculate(ArithmeticOperation whatToDo, double a, double b ){

return [Link](a,b);
}

public static void main(String[] args) {

calculate(addition, 3.55, 50.00);


calculate(subtraction, 3.55, 50.00);
}
}

The output of the CalculatorWithAnonymousClasses program will be the same as from Calculator .
What did we achieve by re-writing calculator this way? We separated the declaration of the behavior and its
implementation. The behavior is declared in the interface, and if more than one class needs to implement
ArithmeticOperation , we’ll reuse this interface. The anonymous classes allowed me to create a wrapper
object around the method performOperation , so this object could be passed as an argument to the method
calculate . In the next section I’ll rewrite this calculator again in a more elegant way with lambda
expressions.

[Link] 85/303
22/03/2025, 18:48 Programação Java para crianças

Access Levels
In many code samples I’ve been using the keyword public in declaration of member variables and
methods. This means that such a variable or a method can be accessed by any other code from the project.
In the next chapter I’ll explain how to control access levels in Java.

5.4. Lambda Expressions


Up till now, to invoke a method we’ve been creating named or anonymous classes and instantiating objects, but
lambda expressions allow to define and invoke a piece of code even without the need to declare classes or
instantiate objects.

First, let me introduce a new term - a function. So far to implement any behavior you’d write a method that
could be invoked by specifying the class name and a method name (static methods) or by specifying the object
variable and a method name (non-static methods). This is a main idea of any object-oriented programming
language - the classes and objects are the first-class citizens. You can’t write a program without them.

But there are functional programming languages that don’t need to wrap behavior inside classes. They allow you
to implement behavior by writing functions, which are similar to methods in that they can have names, take
arguments, and return results. But functions don’t have to be placed inside classes and can live independently.

A lambda expression is a function without a name or anonymous function that you can assign to a variable, pass
as an argument to a method or return from a method. In earlier versions of Java you could pass a value to a
method only if this value was an object or a primitive. But now a function (a piece of code) becomes a value that
can be passed around. Now let’s see it in action.

[Link] 86/303
22/03/2025, 18:48 Programação Java para crianças

Figure 41. The Lambda sign

In the new version of calculator I’ll declare each arithmetic operation as a lambda expression. I will reuse the
same functional interface with the three-argument method calcuate , but will pass the lambda expression that
implements ArithmeticOperation as the first argument.

[Link] 87/303
22/03/2025, 18:48 Programação Java para crianças

JAVA
public class CalculatorWithLambdas {

// Implementing addition as a lambda expression


static ArithmeticOperation addition=(first, second) -> {
double result = first + second;
[Link]("" + first + " + " +
second + " = " + result );
return result;
};

// Implementing addition as a lambda expression


static ArithmeticOperation subtraction = (first, second) -> {
double result = first - second;
[Link]("" + first + " - " +
second + " = " + result );
return result;
};

public static double calculate(ArithmeticOperation whatToDo, double a, double b ){

return [Link](a,b);
}

public static void main(String[] args) {

calculate(addition, 3.55, 50.00);


calculate(subtraction, 3.55, 50.00);
}
}

The difference between CalculatorWithAnonymousClasses from the previous section and


CalculatorWithLambdas is that the former implements the functional interface as anonymous classes and the
latter as lambdas. Lambda expressions offer a concise way of implementation of functional interfaces. To write a
lambda expression you need the play by the rules:

1. Declare an the interface that has only one abstract method.

2. Make sure that the arguments of your lambda expression match the arguments of the abstract method.

3. Make sure that the return value of your lambda expression matches the return value of the abstract method.

Review the code of the CalculatorWithLambdas . Both lambdas addition and subtraction abide by
these rules.

You may wonder, "Why are there no data types specified for the lambda parameters first and second?" The
reason being that Java compiler is smart enough to guess their data types because it knows which abstract
method this lambda implements. An educated guess such as this is called type inference.

[Link] 88/303
22/03/2025, 18:48 Programação Java para crianças

O IntelliJ IDEA pode converter automaticamente classes anônimas que implementam


interfaces funcionais em expressões lambda. Apenas certifique-se de que o nível de
NOTE
linguagem do seu projeto seja 8.0. Você pode fazer isso selecionando o menu File | Project
Structure.

5.4.1. Simplificando o código com Lambdas


Vamos retornar aos nossos exemplos com pets. Gostaria de mostrar como as expressões lambda podem
simplificar seu código reduzindo o número de classes necessárias. Anteriormente neste capítulo, criamos as
classes Dog , Parrot e a única diferença entre elas era a implementação da interface Talkative . Mas
podemos declarar apenas uma classe com um método que pode receber a implementação do Talkative em
uma forma de expressão lambda.

Vamos começar definindo a interface funcional Talkative . Desta vez, vou mudar um pouco a assinatura do
método talk em comparação com a versão mostrada anteriormente neste capítulo. Faço isso para mostrar a
você como escrever uma expressão lambda que implementa um método que tem um argumento e retorna algum
valor.

JAVA
public interface Talkative {
public String talk(String petName);
}

Agora vamos escrever a classe Pet com um método speakup que receberá a implementação da
Talkative interface como o primeiro argumento e o nome do animal de estimação como um segundo. A classe
Pet pode ter muitos outros métodos úteis, mas eu gostaria de focar no speakup que pode receber um pedaço
de código definindo as regras de conversação e aplicar esse código.

JAVA
public class Pet {

// Some other code can go here

public String speakup(Talkative talkRules, String name){


return [Link](name);
}
}

A única outra classe que precisamos criar é PetMasterLambda aquela que criará instâncias de
Pet representando cães e papagaios, mas passando implementações diferentes da Talkative interface. Aí
vem:

[Link] 89/303
22/03/2025, 18:48 Programação Java para crianças

JAVA
public class PetMasterLambda {
public static void main(String[] args) {

// dogs
Pet myDog = new Pet();

Talkative dogTalkRules = (name) -> {


return "I'm a dog. My name is " + name;
};

[Link]([Link](dogTalkRules, "Sammy"));

// parrots
Pet myParrot = new Pet();

Talkative parrotTalkRules = (name) -> {


return "I'm a parrot. Don't call me " + name;
};

[Link]([Link](parrotTalkRules, "Charlie"));
}
}

Definimos regras diferentes para papagaios e cães falantes como lambdas em variáveis parrotTalkRules ​e,
dogTalkRules consequentemente. Não que eu não tenha especificado o tipo de dado da variável name . É
mais um exemplo de tipagem inferida - a Talkative interface tem um único método abstrato com o argumento
do tipo String . O segundo argumento do método speakup será passado para o método talk . Execute este
programa e ele imprimirá o seguinte:

JAVA
I'm a dog. My name is Sammy
I'm a parrot. Don't call me Charlie

Usando expressões lambda, consegui eliminar a necessidade de criar uma classe separada para cada animal.
Claro, isso só é possível se a única diferença entre as classes Dog e Parrot fosse a implementação do
comportamento de falar.

Gostaria de chamar sua atenção para o fato de que minha classe Pet não tem estado - ela não define nenhuma
variável de classe. Isso significa que nem precisamos criar instâncias da classe Pet , mas poderíamos
simplesmente definir seu método speakup como static e chamá-lo assim:

JAVA
[Link](dogTalkRules, "Mary")

No Capítulo 9, mostrarei mais expressões lambda enquanto explico como processar eventos de GUI , como
clicar em um botão ou mover o mouse. Na Parte 2 da tarefa em que você está prestes a trabalhar, desafiarei você
a reescrever a classe Pet para que ela mantenha as regras de conversação em sua variável de classe.

[Link] 90/303
22/03/2025, 18:48 Programação Java para crianças

5.5. Projeto: Interfaces Java e Expressões Lambda


Parte 1. Nesta parte, você fará um exercício para provar que entende interfaces Java.

1. Crie um novo projeto IDEA chamado chapter5 .

2. Crie um pacote chamado pets .

3. No pacote pets recriam as versões finais das classes e Dog interfaces Fish da seção
Interfaces. Swimmable Talkable

4. No pacote pets crie uma nova classe Pet com um construtor que receberá o nome do pet (do tipo String )
como argumento.

5. Altere as declarações das classes Dog e Fish assim cada uma delas se estende Pet ao implementar
Talkable as Swimable interfaces.

6. Crie a classe PetMaster na seção "Interfaces", mas dê nomes aos animais de estimação ao instanciar as
classes Dog e Fish .

7. Modifique as implementações dos métodos talk para swim que eles imprimam o nome do animal de
estimação como parte da saída em [Link] . Por exemplo, "Meu nome é Sammy. Bark-
Bark-Bark!"

8. Execute e teste o PetMaster programa.

Parte 2. Nesta parte, você fará um exercício para provar que entende os conceitos básicos das expressões
lambda.

1. No capítulo 5 do projeto , crie um novo pacote chamado lambdapets .

2. No pacote lambdapets declare a seguinte Talkative interface:

JAVA
public interface Talkative {
public String talk(String petName);
}

3. Crie uma nova versão da classe Pet com o construtor que recebe as regras de conversação e o nome do
animal de estimação como argumentos. Seu método speakup não terá argumentos. É assim que o código
do novo Pet deve se parecer:

[Link] 91/303
22/03/2025, 18:48 Programação Java para crianças

JAVA
public class Pet {

String name;
Talkative myTalkingRules;

Pet(Talkative talkRules, String name){


[Link] = name;
myTalkingRules = talkRules;
}

public String speakup(){

return [Link](name);
}
}

4. Escreva uma nova versão da classe PetMasterLambda que definirá regras de conversação para cães e
papagaios. Ela deve criar duas instâncias de Pet (uma para um cão e uma para um papagaio) e invocar o
método speakup em cada instância. :toc-placement!: :imagesdir: .

[Link] 92/303
22/03/2025, 18:48 Programação Java para crianças

6. Níveis de acesso, coleções, genéricos e multithreading


I’ll start this chapter with the explanation of how to hide and protect data using so called access level qualifiers.
After that we’ll experiment with Java collections - the language elements that can store multiple objects of the
same type. Remember arrays and their limitations? Java collections offer alternative ways of storing similar
objects. Then you’ll get familiar with the mechanism of generics that allows Java compiler to ensure that you
won’t be using the wrong data types with data collections or other objects.

Finally, I’ll give you a very light introduction to parallel computing using multi-threading.

6.1. Access Levels


In code samples from previous chapters I’ve been using the keyword public in declaration of member
variables and methods. This means that such a variable or method can be accessed by any other code from the
project. You can declare a class, a method, or a member variable to be public , private , or protected . If
one of these keywords is missing, Java compiler assumes that it’s a package access level - this element can be
accessed only from the code located in the same package (directory).

One of the main features of object-oriented languages is encapsulation - the ability to hide and protect data or
code. But who do you need to hide or protect the code from? This is not a protection from bad guys who are not
allowed to see your code. You hide and protect the code from misuse. For example, another programmer
extended your class and is trying to change the value of a variable in your class, which may result in bug.

Let’s consider an example from the real world. Think of a car – most people have no clue how many parts are
under the hood, and what actually happens when a driver pushes the brake pedal. If car designers would not hide
control of some of the under-the-hood operations, the driver would have to deal with hundreds of buttons,
switches and gauges on the car’s dashboard.

[Link] 93/303
22/03/2025, 18:48 Programação Java para crianças

Figure 42. Overwhelmed by the "public user interface"

When you design a class, hide methods and class member variables that should not be visible from outside.
Some of the methods of member variables are meant to be used internally and not to be exposed to other classes.

We’ll start learning about hiding and protecting data with the private access level. If a variable or a method
are declared private, they can be used only within the class where they were declared. The next code sample
represents the class Car and declares some of its members as private . Note that I’ve created this class in the
package vehicles .

[Link] 94/303
22/03/2025, 18:48 Programação Java para crianças

JAVA
package vehicles;

public class Car {

// This private variable is visible only inside this class


private String brakesCondition;

// The public method brake calls private methods


// to decide which brakes to use
public void brake(int pedalPressure){
boolean useRegularBrakes;
useRegularBrakes=
checkForAntiLockBrakes (pedalPressure);

if (useRegularBrakes==true){
useRegularBrakes();
}else{
useAntiLockBrakes();
}
}

// This private method can be called inside


// this class only
private boolean checkForAntiLockBrakes(int pressure){
if (pressure > 100){
return true;
}else {
return false;
}
}

// This private method can be called inside this


// class only
private void useRegularBrakes(){
// code that sends a signal to regular brakes
}

// This private method can be called inside this


// class only
private void useAntiLockBrakes(){
// code that sends a signal to anti-lock brakes
//
}
}

By looking at this code I can say that the class Car exposes only one public method brake , which internally
may invoke several other functions that a driver does not need to know about. For example, if the driver pushes
the brakes pedal too hard, the car’s computer may apply special anti-lock brakes implemented in private
methods.

[Link] 95/303
22/03/2025, 18:48 Programação Java para crianças

I took the next screen shot in IntelliJ IDEA while writing a class CarMaster that uses Car . IDEA helps me
with suggesting the Car class members that I can use in this context. Only the method brake is visible from
the class Car (other methods are from the class Object ).

Figure 43. Can use the brake method only

The private access level is the most restrictive one. If you’re not sure when to use it, just declare all of your
call member variables and methods as private, and loosen this restriction if other classes need to use these
members.

[Link] 96/303
22/03/2025, 18:48 Programação Java para crianças

Figure 44. Private is the most restrictive access

What do you think will happen if you simply remove the private keyword from one of the methods of the
class Car ? Will the CarMaster see it? No, it won’t because the absence of the access qualifier gives a
package access level to this member. Only classes that are located in the package vehicles can access it, and
CarMaster is not one of them.

The class members declared with the protected keyword can be accessed from other members of the same
class, from its descendants or classes located in the same package. Even if a descendant class is located in a
different package, it’ll be able to access protected methods of its ancestors.

Some software developers are creating libraries or frameworks of classes to be used by other developers. These
classes can be extended, and their creators may use the keyword protected trying to allow access to certain
member only descendant classes. But in the real world no one can predict what the developer may want to do
with their libraries, and the keyword protected may become an obstacle in achieving of their goals. I do not
use the keyword protected in my projects. As you gain more experience with Java, see for yourself if the
keyword protected brings some value to your programs.

6.2. Casting
In Java all classes are directly or indirectly inherited from the class Object , which is the root of the class
hierarchy. In Figure 2 you’ve seen a class Car that has number of methods that we’ve never declared - they
belong to the class Object , and the class Car extends Object even though we’ve never asked for it. So any
of your application classes have an ancestor - Object .

[Link] 97/303
22/03/2025, 18:48 Programação Java para crianças

When you declare a variable to represent an instance of your class, you can give it a type either of your class or
any of its ancestors. For example, both of the following declarations are correct:

JAVA
Car myCar = new Car();

Object myOtherCar = new Car();

O compilador Java pode converter (cast) um tipo de dado para outro, desde que eles tenham relação de herança.
Em particular, o compilador Java pode converter automaticamente o tipo para os ancestrais da classe. Isso é
chamado de upcasting . Mas se uma variável tiver o tipo de uma superclasse, ela não verá nenhum membro da
subclasse. A próxima captura de tela mostra que a variável myOtherCar não vê o método brake declarado na
classe Car .

Figura 45. A variável do tipo Object não vê os membros do Car

Mas você pode dizer, "A variável não myOtherCar aponta para a instância da classe Car , que tem um método
público brake ?" Isso mesmo, mas como declarei essa variável do tipo, Object a variável
myOtherCar assume que é apenas um objeto geral. O programador pode fazer downcast do tipo geral para um
mais específico, mas isso tem que ser feito explicitamente colocando o tipo específico do objeto entre parênteses
antes da variável de tipo mais geral, por exemplo:

JAVA
Object myOtherCar = new Car();

Car myOtherCarAfterCasting = (Car) myOtherCar;

[Link] 98/303
22/03/2025, 18:48 Programação Java para crianças

É como se você estivesse dizendo: "Eu sei que a variável myOtherCar é do tipo `Object , mas ela na verdade
aponta para a Car instância". Agora a variável myOtherCarAfterCasting verá o método brake declarado na
classe Car :

Figura 46. A variável tipo de carro vê os membros do carro

Por que precisamos de todas essas complicações? Não podemos simplesmente declarar sempre variáveis ​dos
tipos específicos? Às vezes não podemos. Por exemplo, o JDK vem com muitas outras classes que foram
escritas para trabalhar com os Object tipos de dados. As classes de coleta de dados foram escritas para serem
capazes de armazenar instâncias de quaisquer objetos.

Os criadores de coleções de dados não tinham ideia de que você poderia precisar armazenar instâncias de
Car ou Fish lá. Mas quando você usa o objeto de coleção de dados em seu programa, o tipo de dado é
conhecido. Na próxima seção, você verá um exemplo de um FishTank programa que armazena instâncias da
classe Fish em ArrayList e então as converte de volta para o tipo Fish :

JAVA
theFish = (Fish) [Link](i);

6.3. Coleções de dados selecionadas


Agora vamos ver como trabalhar com coleções de dados. Digamos que você tenha cem músicas no seu MP3
player. É uma coleção. Se você criar uma classe, Song você pode criar cem instâncias dessa classe (uma para
cada música) e colocá-la em uma das estruturas de dados especiais chamadas coleções Java.

[Link] 99/303
22/03/2025, 18:48 Programação Java para crianças

Pacotes Java [Link] e [Link] incluem classes que são bem úteis quando um programa
precisa armazenar várias instâncias de alguns objetos na memória. Existem dezenas de classes de coleção em
Java, mas eu vou mostrar apenas algumas delas. Algumas das classes de coleção populares do pacote
[Link] são ArrayList , HashTable , HashMap , e List .

O pacote [Link] tem coleções úteis em programas que exigem acesso concorrente
(simultâneo) a alguns dados por diferentes partes de um programa (por vários threads ). Apresentarei brevemente
o conceito de multithreading mais adiante neste capítulo, mas a cobertura de coleções concorrentes não pertence
ao livro introdutório como este.

6.3.1. A classe ArrayList


No Capítulo 4, você se familiarizou com arrays Java, que têm uma limitação - você tem que especificar o
número de elementos do array durante a declaração de um array. Mas muitas vezes você não sabe com
antecedência quantos elementos existem. Por exemplo, se você quiser escrever um programa que imprima todos
os seus seguidores no Twitter, o número deles pode mudar muitas vezes por dia. A classe ArrayList pode lhe
dar mais flexibilidade - ela pode aumentar ou diminuir de tamanho conforme necessário. Pense em uma lista de
algo - uma lista de músicas, uma lista de tarefas, uma lista de nomes de amigos. Praticamente todos os objetos
que podem ser usados ​com a lista de palavras podem ser armazenados em um ArrayList .

Por que usar arrays, então? Vamos sempre usar ArrayList ! Infelizmente, nada vem de graça, e você tem que
pagar o preço por ter a conveniência de arrays de tamanho dinâmico. O ArrayList funciona um pouco mais
devagar do que um array regular. Além disso, você só pode armazenar objetos lá, enquanto arrays permitem que
você armazene primitivos também. Para criar e preencher um, ArrayList você deve instanciá-lo primeiro e,
em seguida, criar instâncias dos objetos que você está planejando armazenar lá. Adicione cada objeto ao
ArrayList chamando seu método add . O próximo pequeno programa preencherá um ArrayList com
String objetos e, em seguida, imprimirá cada elemento desta coleção.

[Link] 100/303
22/03/2025, 18:48 Programação Java para crianças

JAVA
import [Link];

public class ArrayListDemo {

public static void main(String[] args) {


// Create and populate an ArrayList
ArrayList friends = new ArrayList();
[Link]("Mary");
[Link]("Ann");
[Link]("David");
[Link]("Roy");

// How many friends are there?


int friendsCount = [Link]();

// Print the content of the ArrayList


for (int i=0; i<friendsCount; i++){
[Link]("Friend #" + i + " is "
+ [Link](i));
}
}
}

Este programa imprimirá o seguinte:

JAVA
Friend #0 is Mary
Friend #1 is Ann
Friend #2 is David
Friend #3 is Roy

O método get extrai o elemento localizado na posição especificada no ArrayList . Como você pode
armazenar quaisquer objetos nesta coleção, o método get retorna cada elemento do Object tipo. O programa
tem que converter este objeto para um tipo de dados apropriado. Não fizemos isso no exemplo anterior apenas
porque armazenamos String objetos na coleção friends , e Java sabe como converter um Object para um
String automaticamente.

Vamos ver como você pode trabalhar com alguns outros objetos em ArrayList , por exemplo, instâncias da
classe Fish mostrada a seguir.

[Link] 101/303
22/03/2025, 18:48 Programação Java para crianças

JAVA
package pets;

public class Fish {


private float weight;
private String color;

// constructor

Fish(float weight, String color){


[Link](weight);
[Link](color);
}

// getters and setters

public float getWeight() {


return weight;
}

public void setWeight(float weight) {


[Link] = weight;
}

public String getColor() {


return color;
}

public void setColor(String color) {


[Link] = color;
}
}

Note that the class fields color and weight are private variables. But this class also defines public
getters and setters - the methods that read or modify the fields. In this example the setters and getters don’t
contain any application logic, but they could. For example, you could encapsulate the logic that checks the
credentials of the users of this class so not everyone can modify the weight property. By Java naming
conventions the setter name starts with the prefix set followed by the capitalized letter of the corresponding
private variable. Accordingly, the getter starts with get .

IntelliJ IDEA can automatically generate setters and getters for the class. Just right-click on
NOTE
the class name and select the options Refactor | Encapsulate Fields.

The code to add (and extract) a particular Fish to the ArrayList collection may look similar to the program
FishTank that comes next.

[Link] 102/303
22/03/2025, 18:48 Programação Java para crianças

JAVA
package pets;

import [Link];

public class FishTank {


public static void main(String[] args) {
ArrayList fishTank = new ArrayList();

Fish fish1 = new Fish(2.5f, "Red");


Fish fish2 = new Fish(5, "Green");

Fish theFish;

[Link](fish1);
[Link](fish2);

int fishCount = [Link]();

for (int i=0;i<fishCount; i++){

theFish = (Fish) [Link](i); // casting


[Link]("Got the " +
[Link]() + " fish that weighs " +
[Link]() + " pounds.");
}
}
}

First, this program creates a couple of instances of the class Fish passing the values for the fields via
constructor. Note the letter f in the weight value of the first fish: 2.5f . In Java all decimal literals have the type
double unless you mark it with the suffix f for float .

Each instance is added to the collection fishTank . Then, the program gets the objects from this collection,
casts them to the class Fish and prints their values using getters. Here’s the output of the program FishTank :

JAVA
Got the Red fish that weighs 2.5 pounds.
Got the Green fish that weighs 5.0 pounds.

The ArrayList collection uses Java arrays internally and initially creates an array for 10 elements. But if you
keep adding more elements to ArrayList it internally will create another array of the larger size and copy all
existing elements there. Because of this additional memory allocations and data copying ArrayList
collections works a little slower than arrays, which allocate enough memory in advance.

6.3.2. The Class Hashtable

[Link] 103/303
22/03/2025, 18:48 Programação Java para crianças

While the ArrayList collection only allows referencing its elements by index (e.g. [Link](i) ),
sometimes it would be easier to reference collection elements by names as key/value pairs. I’ll illustrate by
storing my friends' contact information in a HashTable collection that allows accessing objects by key names.
Let’s declare a simple class ContactDetail , which can store contact details of one person.

JAVA
public class ContactDetail {
String fullName;
String facebookID;
String phone;
String email;
}

The program HashTableDemo will create and populate two instances of ContactDetail , will add them to
the Hashtable collection by names (the keys), and then will print the phone number of the second contact.

JAVA
import [Link];

public class HashTableDemo {


public static void main(String[] args) {

ContactDetail friend1 = new ContactDetail();


[Link] = "Jackie Allen";
[Link] = "jallen@[Link]";
[Link] = "jallen";
[Link]="212-545-5545";

ContactDetail friend2 = new ContactDetail();


[Link] = "Art Jones";
[Link] = "ajones@[Link]";
[Link] = "ajones";
[Link]="212-333-2121";

Hashtable friends = new Hashtable();


[Link]("Jackie", friend1);
[Link]("Art", friend2);

// Cast from Object to ContactDetail


String artsPhone = ((ContactDetail) [Link]("Art")).phone;

[Link]("Art's phone number is " + artsPhone);


}
}

In this example I used the first name as the key in the method put that adds elements to a Hashtable . Hence
one contact can be referred by the key get("Jackie") , and the other one as get("Art") . The method get
returns the collection element as the Object type, so I had to cast it to ContactDetail to be able to see the
field phone .

[Link] 104/303
22/03/2025, 18:48 Programação Java para crianças

Figure 47. Contacts can be programmed with Hashtable

HashTable requires each key to be unique. Say you have another contact named Art and will create a new
instance of the ContactDetail object. If you’ll add it to the same collection under the same key -
[Link]("Art", friend3); it’ll replace the contact details of the first Art with the data of the second
one. This happens because Java Hashtable internally generates a hash key (the number) from your key and
uses it as an index to find the element when need [Link] same names will generate the same hash keys. So either

[Link] 105/303
22/03/2025, 18:48 Programação Java para crianças

give the second Art a nickname like ArtFromNYC or use another Java collection like ArrayList to store your
contacts. By the way, ArrayList even allows you to store duplicates (objects with the same values) while
Hashtable doesn’t.
I’m not going to cover other Java collections here, but if you’d like to do your own research, read about such
collections from the [Link] package as HashMap , HashSet , and LinkedList . There is also a class
Collections that has a bunch of useful static methods to operate on your data collections (e.g. sort , copy ,
binarySearch et al.).

6.4. Introduction to Generics


Java generics is a feature that allows you to create so called parameterized data types . For example,
instead of just declaring a collection that can store any data you can pass it a parameter to allow only the objects
of certain data types. Instead of declaring and instantiating a general collection to store friends like this:

JAVA
ArrayList friends = new ArrayList();

you can do it with a parameter so it can store only String objects like this:

JAVA
ArrayList<String> friends = new ArrayList<>();

The parameter(s) goes in the angle brackets right after the data type. Note the so called diamond operator <> on
the right. Since you already declared the required data type on the left, there is no need to repeat it on the right -
compiler will guess the type. It’s also an example of type inference introduced in the previous lesson about
lambda expressions. Now, if by mistake you’ll try to add an object of another type to friends the Java
compiler will complain.

I was able to specify a parameter for ArrayList only because it was created with this ability. If you’ll read the
online documentation ([Link] for ArrayList you’ll see that
it’s declared as follows:

JAVA
public class ArrayList<E>
extends AbstractList<E>
implements List<E>, RandomAccess, Cloneable, Serializable

Isso <E> significa que você tem permissão para especificar um tipo de parâmetro de elementos que serão
armazenados no ArrayList . No caso da friends coleção, o compilador Java veria que nesta coleção
<String> deveria estar o <E> . A documentação online
([Link] para a classe Hashtable parece ainda mais
assustadora:

[Link] 106/303
22/03/2025, 18:48 Programação Java para crianças

JAVA
public class Hashtable<K,V>
extends Dictionary<K,V>
implements Map<K,V>, Cloneable, Serializable

Mas <K,V> significa simplesmente que você pode especificar dois parâmetros: K o tipo de dado chave e V o
valor.

Vamos escrever um programa que ilustra as vantagens de usar genéricos. Vou reutilizar o exemplo da seção
anterior chamado instâncias HashTableDemo armazenadas ContactDetail . Na verdade, vou criar duas
novas versões deste programa. A primeira será chamada HashTableBrokenDemo , e mostrarei como quebrar
este programa para que ele trave durante o tempo de execução se não usarmos genéricos. Depois disso, vou
reescrevê-lo como HashTableGenericsDemo , onde usarei genéricos para mostrar como evitar que os erros de
tempo de execução aconteçam. Aqui está o programa quebrado:

JAVA
import [Link];

public class HashTableBrokenDemo {


public static void main(String[] args) {

ContactDetail friend1 = new ContactDetail();


[Link] = "Jackie Allen";
[Link] = "jallen@[Link]";
[Link] = "jallen";
[Link]="212-545-5545";

Hashtable friends = new Hashtable();


[Link]("Jackie", friend1);

// this is a time bomb


[Link]("Art", "Art Jones, ajones@[Link], ajones, 212-333-2121");

// Cast from Object to ContactDetail


String artsPhone = ((ContactDetail) [Link]("Art")).phone;

[Link]("Art's phone number is " + artsPhone);

}
}

O HashTableBrokenDemo adiciona o primeiro objeto (para Jackie) do tipo ContactDetail à


friends coleção, mas os detalhes de contato para Arte são adicionados na forma de String :

JAVA
"Art Jones, ajones@[Link], ajones, 212-333-2121"

[Link] 107/303
22/03/2025, 18:48 Programação Java para crianças

O compilador Java não vê crime aqui - ele Hashtable pode armazenar quaisquer descendentes da classe
Object . Mas se você executar este programa, você obterá um erro na linha que tenta converter o elemento da
coleção para ContactDetail o tipo. É assim que minha tela do IntelliJ IDEA com o erro se parece:

Figura 48. A exceção de tempo de execução: ClassCastException

O programa falhou na linha 24 com o erro ClassCastException . Os erros de tempo de execução são
chamados de exceções em Java, e explicarei o tratamento de erros no Capítulo 10. Mas meu ponto principal é
que este programa travou durante o tempo de execução apenas porque eu "esqueci" que apenas os objetos do
tipo ContactDetail devem ser armazenados na coleção friends .

Agora, copiarei o código de HashTableBrokenDemo para a nova classe chamada HashTableGenericsDemo .


Farei uma pequena alteração ali - declararei a coleção friends com parâmetros:

JAVA
Hashtable<String, ContactDetail> friends = new Hashtable<>();

Agora estou explicitamente afirmando que minha intenção é usar os String objetos para chaves, e
ContactDetail objetos como valores. O programa HashTableGenericsDemo é mostrado a seguir - ele nem
compila!

[Link] 108/303
22/03/2025, 18:48 Programação Java para crianças

JAVA
public class HashTableGenericsDemo {
public static void main(String[] args) {

ContactDetail friend1 = new ContactDetail();


[Link] = "Jackie Allen";
[Link] = "jallen@[Link]";
[Link] = "jallen";
[Link]="212-545-5545";

Hashtable<String, ContactDetail> friends = new Hashtable<>();


[Link]("Jackie", friend1);

// compiler will complain about this line


[Link]("Art", "Art Jones, ajones@[Link], ajones, 212-333-2121");

// No casting from Object to ContactDetail needed


String jackiesPhone = [Link]("Jackie").phone;

[Link]("Jackie's phone number is " + jackiesPhone);


}
}

O compilador vai reclamar sobre a linha, onde estou tentando chamar o método put com dois String objetos
como argumentos. O compilador Java vai gerar uma mensagem de erro de que não pode aplicar dois
String parâmetros a um Hashtable que foi declarado com parâmetros <String, ContactDetail> .

Outra coisa importante a ser notada é que não há necessidade de casting quando o programa obtém as
informações sobre o telefone de Jackie. Agora, a friends coleção sabe desde o começo que ela armazena não
apenas alguns Object tipos, mas as ContactDetail instâncias.

O que alcançamos? O programa HashTableBrokenDemo nos permitiu armazenar qualquer coisa na coleção,
mas travou durante o tempo de execução, mas HashTableGenericsDemo impediu que esse erro acontecesse.
Ter um erro do compilador é muito melhor do que ter surpresas durante o tempo de execução, não é? Além
disso, com genéricos eliminamos a necessidade de lançar objetos.

Tenho usado o tipo de dado parametrizado Hashtable que foi convenientemente oferecido pelos criadores do
Java, mas você pode definir suas próprias classes com parâmetros também. Criar suas próprias classes
parametrizadas é um dos tópicos mais avançados, e não vou abordá-lo neste livro. Confira o tutorial da Oracle
([Link] se estiver interessado.

6.5. Introdução leve ao multithreading


Até agora, todos os nossos programas realizam ações em sequência – uma após a outra. Então, se um programa
chama dois métodos, o segundo método é invocado somente após o primeiro ser concluído. Em outras palavras,
tal programa tem apenas um thread de execução , onde o código funciona sequencialmente.

[Link] 109/303
22/03/2025, 18:48 Programação Java para crianças

Na vida real, porém, podemos fazer várias coisas em paralelo, como comer, falar ao telefone, assistir TV e fazer
o dever de casa. Para fazer todas essas ações em paralelo, usamos vários "processadores": mãos, olhos e boca.

Hoje, apenas o computador da sua avó tem um único processador (também conhecido como Unidade Central de
Processamento ou CPU). Uma CPU realiza cálculos, envia comandos para o monitor, disco rígido ou unidade de
estado sólido, computadores remotos na Internet e assim por diante. Muito provavelmente seu computador tem
pelo menos duas CPUs e uma GPU (Unidade de Processamento Gráfico) para processar gráficos, se houver.

Mas mesmo um único processador pode executar várias ações de uma vez se um programa usar vários threads .
Uma classe Java pode iniciar vários threads de execução que se revezarão para obter fatias de tempo do tempo
do processador. Por exemplo, o programa faz uma pergunta ao usuário e espera pela resposta. Enquanto isso, a
CPU pode ser usada para executar alguma outra lógica de aplicativo em vez de ficar ociosa, como mostrado na
Figura 7.

[Link] 110/303
22/03/2025, 18:48 Programação Java para crianças

Figura 49. Processamento paralelo

Um bom exemplo de um programa que cria múltiplos threads é um navegador da Web. Por exemplo, você pode
navegar na Internet enquanto baixa alguns arquivos, então um programa (o navegador) executa dois threads de
execução (navegação e download) em paralelo.

6.5.1. Como criar um tópico


Todos os aplicativos Java que criamos até agora (até mesmo o Hello World) estavam sendo executados no
chamado thread principal . Não precisamos fazer nenhuma programação especial para criar um thread principal
- o Java runtime sempre cria um thread para cada programa. Mas se você quiser que o código do seu aplicativo
seja executado em um thread paralelo, você precisa escrever um código para solicitar que o Java runtime crie um
thread(s) separado(s) e execute algum código lá em paralelo com o thread principal.

Existem diferentes maneiras de criar threads. Não explicarei detalhes de cada método porque é um tópico bem
avançado e não é adequado para este livro. Mas listarei apenas algumas das maneiras de criar threads e as
ilustrarei com um exemplo simples. Estes são os principais métodos de escrever código a ser executado em uma
thread separada:

Você pode herdar sua classe da classe Java Thread e substituir seu método run , que deve conter o código a
ser executado em paralelo.

[Link] 111/303
22/03/2025, 18:48 Programação Java para crianças

Você pode adicionar implements Runnable à declaração de uma classe e implementar o método run ,
que, novamente, deve conter o código a ser executado em paralelo.

Em vez de herdar sua classe da classe, Thread você pode criar uma nova instância do Thread objeto

Você pode adicionar implements Callable à declaração da sua classe e implementar o método call ,
que desempenha um papel semelhante ao método run .
A maneira mais fácil de implementar multithreading é usando expressões lambda que foram introduzidas no
Capítulo 5. Como um lembrete, você pode usar lambdas para implementar interfaces funcionais - aquelas que
têm apenas um método abstrato. A interface Runnable declara um único método abstrato run , o que a torna
uma candidata perfeita para ser implementada com lambdas.

Vamos aprender por exemplo. Primeiro, vou mostrar um programa bem simples que executa todo o código
sequencialmente em um thread principal, e então vou reescrevê-lo para ser executado em paralelo.

A classe SingleThreadedDemo executa dois loops sequencialmente. Primeiro, ela imprime cinco valores de i
em potência de 4, e então cinco valores de k.

JAVA
public class SingleThreadedDemo {
public static void main(String[] args) {

for (int i=0; i<5;i++){


[Link]("The value of i in power of 4 is "
+ i*i*i*i*i);
}

for (int k=0; k<5;k++){


[Link]("*** The value of k is " + k + "!");
}

}
}

O primeiro loop simplesmente multiplica a variável i para si mesma quatro vezes. No segundo loop, eu
simplesmente concateno uma String, o valor de k e um ponto de exclamação. O segundo loop começará
somente após o primeiro loop ser concluído, e não importa quantas vezes você execute este programa, a saída no
console sempre será parecida com esta:

[Link] 112/303
22/03/2025, 18:48 Programação Java para crianças

JAVA
The value of i in power of 4 is 0
The value of i in power of 4 is 1
The value of i in power of 4 is 32
The value of i in power of 4 is 243
The value of i in power of 4 is 1024
*** The value of k is 0!
*** The value of k is 1!
*** The value of k is 2!
*** The value of k is 3!
*** The value of k is 4!

Este foi um exemplo de execução de código sequencial em um único thread. Mas as ações que fazemos em cada
loop não dependem umas das outras e podem ser executadas em paralelo, certo?

Vamos mudar um pouco esse exemplo. A classe a seguir MultiThreadedDemo executa dois loops em paralelo.
Ela cria um thread separado para o primeiro loop e o inicia em um thread separado para que o thread principal,
que tem o segundo loop, não espere o primeiro terminar.

JAVA
public class MultiThreadedDemo {
public static void main(String[] args) {

Thread myThread = new Thread( (1)


() ->{ (2)
for (int i=0; i<5;i++){
[Link]("The value of i in power of 4 is " + i*i*i*i*i);
}
} (3)
);

[Link](); (4)

for (int k=0; k<5;k++){


[Link]("*** The value of k is " + k + "!");
}
}
}

1. Começamos o programa criando uma nova instância da Thread classe usando seu construtor que recebe
um objeto que implementa Runnable a interface.

2. Writing a lambda expression is the easiest way to implement Runnable . Note that the lambda expression
doesn’t specify any parameter. Java compiler is smart enough to guess that since the constructor of Thread
expects an instance of Runnable then our lambda expression implements this interface. The for loop
automatically becomes an implementation of the method run . This is what we want to run in a separate
thread

3. The lambda expression ends here.

[Link] 113/303
22/03/2025, 18:48 Programação Java para crianças

4. To start the execution of the thread, we need to call the method start , which is defined in the class
Thread and will internally invoke the method run , which is implemented as lambda. The method start
doesn’t wait for the completion of the method run so the next line in our main method is executed.
If you run the program MultiThreadedDemo several times, it may print the output differently each time
depending on how busy is the CPU is on your computer. I ran this program several times and selected the
console output that illustrates that the code was not executed sequentially, take a look:

JAVA
*** The value of k is 0!
*** The value of k is 1!
The value of i in power of 4 is 0
The value of i in power of 4 is 1
*** The value of k is 2!
*** The value of k is 3!
*** The value of k is 4!
The value of i in power of 4 is 32
The value of i in power of 4 is 243
The value of i in power of 4 is 1024

Note that the first two lines print the output from the second loop! This means that after calling the method
start on the thread myThread the program didn’t wait for the completion of the first loop, which ran in
parallel thread. Then the first loop had something to print. Then the second, etc. The entire console output is a
mix of two parallel number-crunching threads.

You may say, is it even a real-world example? Who needs to run such simple loops in parallel? I made this
example simple to get across the message that one program can do stuff in parallel.

For a more realistic scenario think of a game with fancy graphics that needs to update the images on the screen
and perform some complex algorithms. If such a program would sequentially do the screen updates and
algorithms, the game would run slow with noticeable delays in the graphics during times when the program does
number crunching. In Chapter 8 I’ll illustrate the effect of the "frozen" screen and how to deal with it using a
separate thread for screen updates.

6.6. Project: Using ArrayList and Generics


In this exercise I’d like you to try create your own collection that uses ArrayList , generics, private variables
and public getters and setters.

1. Create a new IDEA project named Chapter6.

2. Create a package named contacts.

3. In the package contacts create the class ContactDetail that looks like this:

[Link] 114/303
22/03/2025, 18:48 Programação Java para crianças

JAVA
public class ContactDetail {
private String fullName;
private String facebookID;
private String phone;
private String email;

public String toString(){


return "Name: " + fullName +
", Facebook ID: " + facebookID +
", phone: " + phone +
", email: " + email;
};
}

Note that I’m overriding the method toString that exists in the class Object .
4. In IntelliJ IDEA right-click on the class name and select the options Refactor | Encapsulate Fields to
generate public getters and setters for all fields.

5. In the package contacts write a program MyContacts that will declare and instantiate an ArrayList
called friends it should allow only the objects of type ContactDetail .

6. Create two or more instances of ContactDetail object and populate them with your friends' data using
setters.

7. Add all instances of ContactDetail to the friends collection by using the method add .

8. Write a for-each loop that will iterate through the collection friends and print all their contact information by
simply printing each object from the collection friends . Since the class ContactDetails has an
overriden method toString , you can simply print the objects as shown below - the method toString
will be invoked automatically:
JAVA
for (ContactDetail friend: friends){
[Link](friend);
}

9. The output of the program MyContacts should look similar to this one:
JAVA
Name: Jackie Allen, Facebook ID: jallen, phone: 212-545-5545, email: jallen@[Link]
Name: Art Jones, Facebook ID: ajones, phone: 212-333-2121, email: ajones@[Link]

[Link] 115/303
22/03/2025, 18:48 Programação Java para crianças

7. Introduction to GUI with JavaFX


After creating lots of code samples producing outputs to the system console, it’s time for creating a nice looking
Graphic User Interface (GUI). We’re accustomed to programs that open windows with buttons, text fields,
menus and other GUI components.

Java has an older library of GUI components called Swing ([Link] and the
new one called JavaFX ([Link] We’ll use only JavaFX in
this book. JavaFX is also a library that’s included with JDK, and you can write your GUI programs using
familiar Java language. On the other hand, JavaFX allows you to create and arrange GUI components in a
special FXML format, while writing application logic in Java.

In this chapter I’ll explain the basics of GUI programming with JavaFX. You’ll learn how to create GUI
containers and arrange GUI components inside them. In the next chapter you’ll learn how to write code that
reacts on user’s actions (a.k.a. events) like a click of a button or a mouse move.

By the end of this chapter you should be ready to work on the following assignment: "Create the GUI for a
calculator that will look similar to this one":

[Link] 116/303
22/03/2025, 18:48 Programação Java para crianças

Figure 50. The Calculator

7.1. Introduction to JavaFX


With JavaFX you can create Graphic User Interface in two ways:

By writing the code in Java as you did in previous chapters.

With the help of the visual layout tool called Scene Builder, where you’ll be dragging and dropping
components on the window and saving the design in the FXML format in a file with extension .fxml. Then
the Java program will load this .fxml file and display your creation.

I’ll show you both ways, but let’s start with some basics of development with JavaFX. Let’s set the stage -
JavaFX uses theater terminology.

[Link] 117/303
22/03/2025, 18:48 Programação Java para crianças

IntelliJ IDEA will help you to get started quickly. Just create a new project (the menu File | New Project), select
JavaFX application as the project type and give it a name. In a second new project will be created with two Java
classes Main and Controller and a file named [Link] as shown below.

Figure 51. The newly generated IDEA project

The Main class of a JavaFX application extends Application and is an entry point of your application.
JavaFX classes are located in the packages whose names start with javafx (e.g. [Link] and
[Link] ).The main method invokes the method launch from Application , which creates a stage
by calling its method start , which was was declared as abstract . Hence, we must override start in our
Main class. When the method start is invoked, it’ll receive a reference to the Stage object - this is where
your GUI components will live and perform.

Pretend that you’re a play director and need to set up one or more scenes (views) on stage. But if in a real scene
you’d expect to see some chairs, tables and other pieces of furniture, each JavaFX scene consists of GUI
containers and components. In JavaFX you’ll create components, add them to the scene and then add a scene to
the stage. When the stage is ready, open the curtain by calling the method show .

All GUI components are subclasses of the class [Link] , and when I’ll be using the word node
just think of a GUI component. Now you have a choice: create these nodes using Java classes or load the pre-
created design from the .fxml file as it was done in the code generated by IDEA.

The method start loads the file [Link], sets the title of the stage and creates a Scene 300 by 275
[Link] content of the generated [Link] looks like this:

[Link] 118/303
22/03/2025, 18:48 Programação Java para crianças

XML
<?import [Link]?>
<?import [Link]?>

<?import [Link]?>
<?import [Link]?>
<GridPane fx:controller="[Link]"
xmlns:fx="[Link] alignment="center" hgap="10" vgap="10">
</GridPane>

FXML is a markup language based on XML (a popular data presentation format). The idea is to separate the
creation of the GUI in a declarative language (FXML) from the application logic (Java). If we didn’t use IDEA,
the FXML would be generated by the Scene Builder itself. In FXML the GUI is represented by tags in angle
brackets, e.g. <GridPane> . Each tag has a matching closing tag that starts with a forward slash, e.g.
</GridPane> and may have attributes (e.g. alignment="center" ). The <GridPane> tag corresponds to
the Java class GrindPane , which is one of the JavaFX layouts - I’ll explain them very shortly. Every FXML tag
has a corresponding Java class behind it.

The generated Java class Controller has just the pair of curly braces at this point, but in the next chapter
we’ll be writing the application logic there. Later on you’ll connect the generated FXML views with the Java
code of the Controller . Run the Main program and it’ll show an empty window shown next:

Figure 52. Running the generated application

7.2. Brief Overview of JavaFX Layouts


Users of your application can have computer monitors of different screen sizes and resolutions. JavaFX comes
with layouts that help with arranging GUI controls on the scene and keeping the arrangement for different stage
sizes (think window sizes). There are following layout container Java classes (and similarly named FXML tags):

HBox

[Link] 119/303
22/03/2025, 18:48 Programação Java para crianças

VBox

FlowPane

GridPane

BorderPane

StackPane

TilePane

AnchorPane
The HBox class (the horizontal box) places controls in a row next to each other. The vertical box VBox places
controls vertically. The FlowPane places the nodes in a row and then wraps to the next row if there is no room
left in the current one.

The GridPane allows to arrange UI controls in rows and columns and assign constraints (properties) to each
cell.

The BorderPane splits the scene into five regions, which are called left , top , right , bottom , and
center .

The TilePane layout is similar to the FlowPane , but it places each GUI components in a cell of the same size
similarly to tiles on the wall. Say, you need to display several images in a tile layout. Adding the ImageView
components to the TilePane will shows them as tiles next to each other.

The StackPane layout works as a deck of playing cards - only one child node will be shown at a time covering
the other nodes.

The AnchorPane lets you to anchor nodes at left, top, right, and bottom of the scene. Imagine a music player
application with the buttons Rewind on the left and the Fast Forward on the right. For example, the AncorPane
allows you to force the Rewind button to always remain at 20 pixels from the left border of the window and 10
pixels from the bottom even when the window resizes. For that you can use the leftAnchor and
bottomAnchor properties. For example,

JAVA
[Link](rewindBtn, 20);
[Link](rewindBtn, 10);

Components that are located in a container are considered children of this container. Accordingly, a container is
called a parent of these components. If you’d be writing the code manually in Java, you’d be going through the
following steps with any layout:

1. Create instances of child nodes to be used within the layout container.

[Link] 120/303
22/03/2025, 18:48 Programação Java para crianças

2. Create an instance of the selected layout class (e.g. HBox ). This instance will serve as a container and a
layout manager for all child nodes that you’ll add to it.

3. Add the child nodes to the container using either the method add() or addAll() .

4. If this layout instance needs to be used inside another layout (e.g. an HBox can be placed inside the
BorderPane ) add the instance created in Step 1 to the parent container by using the method add() .
In this chapter we’ll use only some of the JavaFX layouts, but for detailed coverage of layouts visit Oracle
tutorial at [Link]

It’s easier to create layouts and components using a visual tool, and this is what we’ll do next.

7.3. Getting Started With Scene Builder


Scene Builder 2.0 is a visual layout tool for JavaFX applications by Oracle. Download it from
[Link] Follow the installation instructions ([Link] for your operational system and
install Scene Builder on your computer. In this section I’ll show you how to quickly get started with Scene
Builder, but you should also watch this helpful Youtube video ([Link]

You can start the Scene Builder either independently or from IDEA. For example, if you right-click on the
[Link] file in your newly generated IDEA project it’ll show you a popup menu, which includes the item
Open in SceneBuilder. Select this item. The very first time IDEA will ask you to confirm the location of Scene
Builder application on your computer. Then it’ll open [Link] in Scene Builder. This is how it looks on my
computer:

Figure 53. Scene Builder with opened [Link]

[Link] 121/303
22/03/2025, 18:48 Programação Java para crianças

On the left panel you can select containers, controls, menus, shapes and drag and drop them onto the central
canvas area. Note the GridPanel layout shown at the bottom left - the arrangement of GUI components inside of
this scene will be controlled by GridLayout . Let me select the Button from the Controls section on the left and
drop it on the canvas in the middle. The Screen Builder’s window will look like this:

Figure 54. Adding a button to the scene

The right panel allows you to change the properties of this button. These little boxes with the digit one represent
so called row and column constraints - we’ll discuss them shortly.

The Scene Builder’s menu Preview | Show Preview in Window will show how your GUI will look during the
runtime. So far our one-button screen is not too fancy, and this is how it’s preview looks like:

Figure 55. Scene Builder: previewing in window

Let’s save the changes in [Link] (menu File | Save) and open this file in the IDEA text editor. When IDEA
generated [Link] there was no content between <GridPanel> and `</GridPanel>`in the generated
[Link], but now there is:

[Link] 122/303
22/03/2025, 18:48 Programação Java para crianças

XML
<?xml version="1.0" encoding="UTF-8"?>

<?import [Link].*?>
<?import [Link].*?>
<?import [Link].*?>
<?import [Link]?>
<?import [Link]?>
<?import [Link]?>
<?import [Link]?>

<GridPane alignment="center" hgap="10" vgap="10" xmlns:fx="[Link]


xmlns="[Link] fx:controller="[Link]">
<columnConstraints>
<ColumnConstraints />
<ColumnConstraints />
</columnConstraints>
<rowConstraints>
<RowConstraints />
<RowConstraints />
</rowConstraints>
<children>
<Button mnemonicParsing="false" text="Button"
[Link]="1" [Link]="1" />
</children>
</GridPane>

I’ll go through the details of the GridPane layout in the next section, but please note that Scene Builder created
some tags to specify the constraints for the rows and columns of the grid. The Button component is placed
inside the grid in the cell located in the intersection of the column 1 and row 1.

7.4. GridPane Layout


I’m not going to cover each JavaFX layout in detail, but will show you how to use a pretty powerful layout -
GridPane . When we’ll work on the GUI for the calculator, I’ll also show you how to design a scene using a
combination of layouts.

GridPane divides the area into rows and columns and places GUI components (the nodes) into the grid cells.
With GridPane layout cells don’t have to have the same size - a node can span (be as wide or as tall as several
others). If the screen size changes, the content won’t be rearranged and will maintain the grid look.

Before placing the node into a particular cell you have to specify the grid constraints such as rowIndex and
columnIndex (the coordinate of the cell, which starts with 0,0). The rowSpans and columnSpan allow you
to make the cell as wide (or as tall) as several other cells. The GridPane documentation
([Link] describes lots of various constraints that
can define the behavior of each cell’s content if the windows gets resized. I’ll show you a basic example that
uses some of these constraints.

[Link] 123/303
22/03/2025, 18:48 Programação Java para crianças

7.4.1. Designing a Sign In Window in Scene Builder


I want to create a Sign In window where the user can enter the id, password and press the button Sign In. The
scene will use GridPane layout. The first row will contain a Label and TextField for user id, the second
row will have a similar pair for the password, and the third row of the grid will have one Button Sign In that
should span two columns. This is how this window should look like:

Figure 56. The Sign In Window

I’ll start with creating a new IDEA JavaFX project (menus File | New Project | JavaFX Application) giving it the
name Signin . The project with classes Main , Controller and the file [Link] will be generated. Let’s
rename this FXML file into [Link]. IDEA will automatically change the corresponding line in the Main
class to load this file instead of [Link]:

JAVA
Parent root = [Link](getClass().getResource("[Link]"));

Rename the package from sample to signin (right-click menu, Refactor | Rename). Now open the file [Link]
in Scene Builder and start thinking about laying out the components of our Sign In scene. Let’s take another look
at the image of the Sign In window. I can clearly see that GUI components are placed in three rows. The first two
have a Label and TextField and the third one has a wide Button . I can also recognize two columns in the
layout of the Sign In window. The first column has two Label components and the left side of the Button .
The second column has two TextFiled components and the right side of the Button . We can also say that
the Button spans two columns. We’ve got a 2x3 grid!

Open the generated [Link] in Scene Builder. Since this file has already empty <GrigPane> tag, you’ll
see GridPane(0,0) as the root of the hierarchy in the bottom left corner as in Figure 4 above. So far this grid has
zero rows and zero columns. Right-click on the grid in the middle of the screen and add three rows and two

[Link] 124/303
22/03/2025, 18:48 Programação Java para crianças

columns to the grid by using the right-click menus GridPane | Add Row Below and Add Column After. When the
GridPane is selected The Scene Builder’s window may look similar to this:

Figure 57. A GridPane (2,3)

Now let’s drag two Label controls and a Button from the Controls section on the left and drop them into the
appropriate cells in the first grid column. Change the text on these components to be UserID:, Password, and
Sign In. Then we could drag and drop two TextField objects in the top two cells in the second column.
Actually, it’s not a good idea to enter password in the clear text. I’ll use the TextField for the user ID, and the
PasswordField (it marks user’s input) for password.

[Link] 125/303
22/03/2025, 18:48 Programação Java para crianças

Figure 58. A GridPane with nodes in Scene Builder

Note that the hierarchy of nodes is shown in the bottom left panel of Scene Builder. If you want to change the
properties of a component on a scene with a complex GUI layout it might be easier to select the GUI control in
the Hierarchy panel than in the design area in the middle. Now select the menu Preview | Show Preview in
Window and you’ll see the following window:

Figure 59. Previwing in Scene Builder

This window doesn’t look exactly as we wanted: there are some issues with alignments, there is no spacing
between the container and components, and the button Sign In doesn’t span. But on the bright side, the
GridPane controls the layout and if you’ll try to stretch this window, GUI components won’t change their

[Link] 126/303
22/03/2025, 18:48 Programação Java para crianças

relative positioning:

Figure 60. Streching the preview window in Scene Builder

Let’s do a couple of more property changes before we’ll run this application from IDEA. In Scene Builder the
Properties panel is located on the right and has three sections: Properties, Layout, and Code, and you’ll find the
properties to be changed in one of these sections.

1. On the left panel of Scene Builder select the GridPane and on the right panel change alignment to be
TOP_LEFT .

2. Enter 10 for the padding on top, right, bottom and left for the GridPane . We need some spacing between
the borders of the scene and the grid.

3. Select the Button on the left and then change the column span to be 2 and the preferred width to be a large
number, say 300. This will make the button wide.

4. Select the first column of the grid row by clicking on the little 0 on top of the grid. Set the both preferred
and maximum width for this column to be 70.

[Link] 127/303
22/03/2025, 18:48 Programação Java para crianças

5. Select the second column of the grid row by clicking on the little 1 on top of the grid. Set the both preferred
and maximum width for this column to be 100.
After you do all these changes and save them, the file [Link] will look like this:

XML
<?xml version="1.0" encoding="UTF-8"?>

<?import [Link].*?>
<?import [Link].*?>
<?import [Link].*?>
<?import [Link].*?>
<?import [Link]?>
<?import [Link]?>
<?import [Link]?>
<?import [Link]?>

<GridPane hgap="10" vgap="10" xmlns="[Link]


xmlns:fx="[Link] fx:controller="[Link]">
<rowConstraints>
<RowConstraints minHeight="10.0" prefHeight="30.0" />
<RowConstraints minHeight="10.0" prefHeight="30.0" />
<RowConstraints minHeight="10.0" prefHeight="30.0" />
</rowConstraints>
<columnConstraints>
<ColumnConstraints maxWidth="70.0" minWidth="10.0" prefWidth="70.0" />
<ColumnConstraints maxWidth="100.0" minWidth="10.0" prefWidth="100.0" />
</columnConstraints>
<children>
<Label alignment="CENTER" text="User ID:" />
<Label text="Password:" [Link]="1" />
<Button mnemonicParsing="false" prefWidth="300.0" text="Sign In" [Link]="2"
[Link]="2" />
<TextField [Link]="1" />
<PasswordField [Link]="1" [Link]="1" />
</children>
<padding>
<Insets bottom="10.0" left="10.0" right="10.0" top="10.0" />
</padding>
</GridPane>

In the <GridPane> section you see <rowConstraints> and <columnConstraints> tags defining the the
properties of the rows and columns. The <children> section contains the declaration of GUI components that
the user will see on the screen: <Label> , <Button> , <TextField> , and <PasswordField> . The
<Insets> section ensures that there is some space between the grid borders and its children.

This is a declarative way of creating GUI in FXML. No Java coding was required to create the GUI for this
application.

Finally, let’s set the size of the stage so it can accommodate all components from our scene. In IDEA, open the
class Main , and in the code set the size of the scene to be 200x150 pixels.

[Link] 128/303
22/03/2025, 18:48 Programação Java para crianças

JAVA
[Link](new Scene(root, 200, 150));

Run the Main program and you’ll see the window that looks similar to the one in Figure 7 above. The work that
we’ve done in Scene Builder was a little tedious, but it didn’t require any knowledge of Java. This means that
this work can be given to a UI designer, while you’ll concentrate on programming the application logic in Java.

7.4.2. Programming the Sign In Window in Java


Some people like visual design tools, but others don’t. If you prefer to program everything in Java without using
Scene Builder and FXML, you can certainly do it. Below is the Java code of the Sign In window that I’ve
written purely in Java without using Scene Builder. It’ll produce the same output as in Figure 7.

[Link] 129/303
22/03/2025, 18:48 Programação Java para crianças

JAVA
public class GridPaneSample extends Application {

public void start(Stage primaryStage) {

final int TWO_COLUMN_SPAN = 2;

Label userIdLbl = new Label("User ID:");


TextField userIdTxt = new TextField();
Label userPwdLbl = new Label("Password:");
PasswordField userPwdTxt = new PasswordField();

GridPane root = new GridPane();


[Link](10);
[Link](new Insets(10));
[Link]([Link]);

// Using static methods for setting node constraints


[Link](userIdLbl, 0, 0);
[Link](userIdTxt, 1, 0);
[Link](userPwdLbl, 0, 1);
[Link](userPwdTxt, 1, 1);

[Link]().addAll(userIdLbl, userIdTxt,
userPwdLbl, userPwdTxt);

Button signInBtn = new Button ("Sign In");

// Allow the button to be wider overriding preferred width


[Link](Double.MAX_VALUE);

// using instance method for directly adding the node


[Link](signInBtn,0,2,TWO_COLUMN_SPAN,1);

Scene scene = new Scene(root,250,150);


[Link](scene);
[Link]();
}

public static void main(String[] args) {


launch(args);
}
}

After all your efforts in Scene Builder, this Java program shouldn’t be difficult for you to understand. As you see,
I use classes named similarly to FXML tags. FXML tags can have attributes (e.g. vgap="10" `), and in
Java you’d need to call the corresponding setter (e.g. `[Link](10) ). So the choice is
yours - FXML or Java. If you have visual personality use FXML, otherwise use Java.

[Link] 130/303
22/03/2025, 18:48 Programação Java para crianças

7.5. Styling With CSS


It would be boring if all applications would look the same. Application windows may have different colors,
fonts, buttons with rounded corners or use special visual effects. In other words, applications have different
styles. Even though you can style JavaFX GUI components programmatically (e.g. by calling methods
setFont() or setFill() ) separating styling from programming allows professional UI designers to take
care of the look and feel while software developers implement application logic.

Separating the work of programmers and designers became popular in Web applications. Cascading Style Sheets
(CSS) is a special language for styling UI. Styles of GUI components are stored in separate .css files and are
loaded and applied to components by the application’s code. Sometimes this process is called skinning - you can
create an application that can "wear different skins" changing its look to the user’s liking. JavaFX has a default
skin, and if you’re interested in how to create custom skins, visit Oracle online tutorial Skinning JavaFX
applications with CSS ([Link]

Even if you won’t create your own CSS file, your JavaFX application applies default CSS style to the
components of your view. In Scene Builder you can see these styles. Just select any component and then go to
the menu View | Show CSS Analyzer. You’ll see a number of styles the start with the prefix fx- , which makes
JavaFX CSS a little different from a standard CSS syntax.

Covering CSS in detail would require a separate book, but I’ll show you a simple example of how the look of the
GUI can be changed without the need to modify the Java code.

You can either create so-called CSS selectors to style a specific GUI component, a type of components (e.g. all
buttons), or create a reusable style that can be applied programmatically to a selected component.

To style a specific component it has to have a unique id. If you program GUI in Java, set in your Java code using
the method setId() , for example:

JAVA
Button signInBtn = new Button ("Sign In");
[Link]("submitBtn");

In FXML just add an id attribute to the tag of the component:

XML
<Button id="submitBtn" text="Sign In">

For a button with an id submitBtn you can add the following section to the CSS file to make its background
color red:

[Link] 131/303
22/03/2025, 18:48 Programação Java para crianças

CSS
#submitBtn{
-fx-background-color: red;
}

You can find the names of the main CSS colors online ([Link] In CSS
the id type selectors start with the #-sign as in #submitBtn .

If you want to apply a style to several components of the same type, you need to define a type selector. For
example, to make the text of all Label components red, you can define the following CSS type selector:

XML
.label{
-fx-text-fill: red;
}

Note that CSS type selectors start with the dot. To create a CSS class selector that can be applied to any
component, define the selector with an arbitrary name and apply it programmatically to the components of your
choice. For example, you can specify the class selector .blueLable :

XML
.bluelabel{
-fx-text-fill: blue;
-fx-font-family:verdana;
-fx-font-style:italic;
}

This class selector defines the rules that will display text of the component in blue bold verdana font in italic
style. Typically, you’ll be loading the entire CSS file when the application starts so all styles are available for
use. If you use Java for GUI programming, you can apply a class selector to a specific button just like this:

JAVA
Label userPwdLbl = new Label("Password:");
[Link]().add("bluelabel");

In FXML assigning a CSS class selector is done by adding the attribute styleClass to the tag element:

XML
<Label text="Password:" styleClass="bluelabel" [Link]="1" />

You may ask, "How am I supposed to know which style properties are available for a given JavaFX
component?" All JavaFX styles are described in the online document titled "JavaFX CSS Reference Guide"
([Link]

Let’s learn how to apply all these styling techniques to the Sign In window from the previous section. Using
IDEA menu File | New create a new file [Link] in Signin project. Then add the following content to it:

[Link] 132/303
22/03/2025, 18:48 Programação Java para crianças

CSS
#submitBtn{
-fx-background-color: lightskyblue;
-fx-font-family:verdana;
-fx-font-size:20;
-fx-font-weight: bold;
-fx-stroke:navy;
-fx-font-style:italic;
-fx-border-radius: 20;
-fx-background-radius: 20;
-fx-padding: 5;
}

.label{
-fx-text-fill: red;
}

.bluelabel{
-fx-text-fill: blue;
-fx-font-family:verdana;
-fx-font-style:italic;
}

The file [Link] defines three styles:

an id selector for the component with the id submitBtn

a type selector for all Label components

a class selector bluelabel that can be applied to certain labels.

To apply this CSS file to our Sign In application add the attribute id="submitBtn" to the <Button> element
in [Link].

Then add the attribute styleClass="bluelabel" to the <Password> tag in [Link] .

Finally, in [Link] load the [Link] and apply it to the scene. The new version of [Link] will
look like this:

[Link] 133/303
22/03/2025, 18:48 Programação Java para crianças

JAVA
public class Main extends Application {

@Override
public void start(Stage primaryStage) throws Exception{
Parent root = [Link](getClass().getResource("[Link]"));
[Link]("Sign In");

Scene scene = new Scene(root, 200, 150);


[Link]().add(getClass()
.getResource("[Link]").toExternalForm());

[Link](scene);
[Link]();
}

public static void main(String[] args) {


launch(args);
}
}

Run the Main application and you’ll see a differently styled Sign In window:

Figure 61. Styled Sign In Window

When the application starts loading our CSS file it sees that all labels must be red because of the type selector for
labels. But then the application notices a more specific style for the Label Password:
styleClass="bluelabel" , so it paints the text Password in blue.

[Link] 134/303
22/03/2025, 18:48 Programação Java para crianças

7.6. BorderPane and Combining Layouts


Pretty often you see applications that split the window into several distinct areas - the header goes on top, the
navigation bar is on the left (or right), the footer’s at the bottom of the page and a large content area occupies the
middle portion of the window. The BorderPane layout allows you to do exactly this - split the scene into up to
five regions called left , top , right , bottom , and center .

Each of these regions can contain either a single GUI component or a container that will have "children" -
components allocated in their own container, e.g. inside a GridPane . You’ll use BorderPane layout with a
nested GridPane while working on the calculator following instructions from the Project section at the end of
this chapter. Meanwhile, let’s create a very basic window illustrating how the BorderPane layout works.

Open Scene Builder and create a new FXML file by selecting the menu File | New. Then drag the BorderPane
from the left and drop in the middle. Click on the BorderPane and you’ll see a screen that can look as follows:

Figure 62. An Empty BorderPane

Now select Insert TOP at the bottom left, and then drag and drop a Label from the Controls section onto the
middle section of Screen Builder. Set the label’s title to "This is the Header". This text will be displayed at the
top.

Select Insert LEFT and then drag and drop VBox from the Containers area to the left side of the middle section
of the Screen Builder. The VBox is a container for arranging GUI components vertically, which is what we need
for creating a navigation menu. You’ll see an empty gray area on the left.

[Link] 135/303
22/03/2025, 18:48 Programação Java para crianças

Figure 63. Adding a VBox for navigation

Now select VBOX at the bottom left and add a couple of menu items to the empty VBox . Drag a Button from
the Controls section and drop it onto the VBox . Change its text to read "Menu 1", and make it a little wider so it
fits the VBox nicely. Add two more buttons labeled "Menu 2" and "Menu 3".

Figure 64. Adding buttons to VBox

Our left navigation bar has a menu that’s implemented as buttons. In Chapter 10 while developing a Tic-Tac-Toe
game I’ll show you how to create real menus.

[Link] 136/303
22/03/2025, 18:48 Programação Java para crianças

Let’s add a footer to the window now. Select Insert BOTTOM at the bottom left and then drag the HBox from
the Containers area to the middle section. It’ll look like a gray area at the bottom. Adjust its height so the footer
doesn’t take too much real estate in our scene. Now add three Hyperlink components from the Contols section
to the footer and set their text to "Link 1", "Link 2", and "Link 3" correspondingly. The Scene Builder’s window
should look like this:

Figure 65. Adding a footer with links

Select the menu Preview | Show Preview in Window will help you to see how the window will look during the
runtime:

[Link] 137/303
22/03/2025, 18:48 Programação Java para crianças

Figure 66. Previewing the window

Of course, this window may need more work on styling controls and adjusting sizes and alignments, but as long
as you understand how to lay out a scene, they shouldn’t be too difficult. Creating and applying CSS styles can
make this windows a lot prettier.

Save the layout in a file [Link] using Scene Builder’s menu File | Save. While you’ve been dragging and
dropping components, Scene builder was working hard generating the corresponding FXML code in [Link].
If you open this file in any text editor, its content may look similar to this:

[Link] 138/303
22/03/2025, 18:48 Programação Java para crianças

XML
<?xml version="1.0" encoding="UTF-8"?>

<?import [Link].*?>
<?import [Link].*?>
<?import [Link].*?>
<?import [Link].*?>

<BorderPane maxHeight="-Infinity" maxWidth="-Infinity" minHeight="-Infinity" minWidth="-


Infinity" prefHeight="400.0" prefWidth="600.0" xmlns="[Link]
xmlns:fx="[Link]
<top>
<Label text="This is the Header" [Link]="CENTER" />
</top>
<left>
<VBox prefHeight="200.0" prefWidth="100.0" [Link]="CENTER">
<children>
<Button mnemonicParsing="false" prefHeight="26.0" prefWidth="99.0" text="Menu 1" />
<Button mnemonicParsing="false" prefHeight="26.0" prefWidth="99.0" text="Menu 2" />
<Button mnemonicParsing="false" prefHeight="26.0" prefWidth="99.0" text="Menu 3" />
</children>
</VBox>
</left>
<bottom>
<HBox prefHeight="42.0" prefWidth="600.0" [Link]="CENTER">
<children>
<Hyperlink text="Link 1" />
<Hyperlink text="Link 2" />
<Hyperlink text="Link 3" />
</children>
</HBox>
</bottom>
</BorderPane>

Don’t be overwhelmed with the amount of tags and attributes in the above code. You can identify the regions of
the BorderPane layout. The <top> region contains a label, while the left and <bottom> regions have
containers with their own layouts. In this example I have not used the <center> and <right> regions.
Typically your program will be changing the content of the central area based on the user actions. For example,
if the user clicks on the "Menu 1" button in the left region, JavaFX will generate a clicked event and you’ll show
the content required for this selection in the central area.

You’ll learn how to process events in the next chapter. Now it’s time to practice in working with combined
layouts

7.7. Project: Creating a GUI for Calculator


Using Scene Builder and a combination of the BorderPane and GridPane layout, create GUI for the
calculator that looks as seen in Figure 7.1. Add the TextField to the north region of the BorderPane .
Then add a GridPane container to the center area - you’ll add buttons to this container.

[Link] 139/303
22/03/2025, 18:48 Programação Java para crianças

Most of the calculators have a display field on top and the buttons just below it. As you can see on Figure 1, the
grid with buttons has four columns and six rows. The default GridPane contains two columns and three rows.
You’ll need to right-click on the grid and use the menus GridPane | Add Row Above and Add Column After to
until you see a 4x6 grid as shown below.

Figure 67. The 4x6 GridPane in the center

Note that I set the Padding property to be 10 for all sides of the grid and the Hgap and Vgap to 5 (the gap
between the cells).

Save the layout in the file [Link]. Then drop a Button into the top left cell of the grid. Set the Margin
property to 5 for each side of this button. This is the distance between the button and cell borders. Drag the
button’s border to make it larger. This is what you should see:

[Link] 140/303
22/03/2025, 18:48 Programação Java para crianças

Figure 68. The grid with one button

If you’re curious how this button looks in the [Link], open this file in any text editor and note the section
<children> that in my case looks like this:

XML
<children>
<Button mnemonicParsing="false" prefHeight="37.0" prefWidth="132.0" text="Button">
<[Link]>
<Insets bottom="5.0" left="5.0" right="5.0" top="5.0" />
</[Link]>
</Button>
</children>

There is no indication of the cell (0,0) because zeros are the default values for [Link] and
[Link] properties. Now you need to replicate this button in other cells. You can use multiple
Ctrl-C/Ctrl-V commands and then drag/drop the buttons into other cells. See how the content of the
[Link] changes as you add more buttons. I find it faster to copy/paste the generated code in the FXML
file than using Scene Builder for mass duplication.

Note that in Figure 7.1, the button with coordinates (0,5) spans two columns, and the button with coordinates
(3,4) spans two rows. For these buttons you’ll need to enter 2 as the row (or column) span, and select
MAX_VALUE as maximum width (or height). This is what you should see by now:

[Link] 141/303
22/03/2025, 18:48 Programação Java para crianças

Figure 69. Replicated buttons

Change the text of each button to look Figure 7.1, and the layout is done.

Then create a new JavaFX project Calculator in IDEA and replace the generated [Link] with
[Link] created by Scene Builder. Modify the generated class Main to use [Link]. Rename the
package from sample to mycalculator. Set the size of the scene to be large enough to accommodate your design.
This is how my class Main looks like:

JAVA
public class Main extends Application {

@Override
public void start(Stage primaryStage) throws Exception{
Parent root = [Link](getClass().getResource("[Link]"));
[Link]("My JavaFX Calculator");
[Link](new Scene(root,650,600));
[Link]();
}

public static void main(String[] args) {


launch(args);
}
}

[Link] 142/303
22/03/2025, 18:48 Programação Java para crianças

Run the Main program from IDEA to ensure that your calculator looks as expected. Don’t allow the users to
resize your calculator by invoking the method setResizable on the stage object.

Then create a CSS file to add some cool styling to the calculator’s buttons. Save the CSS file in your IDEA
project and modify the code of the Main class to use your CSS file similarly to how it was done in the section
"Styling With CSS" above. Make your calculator look better than mine - it’s not too difficult.

After completing this assignment your buttons won’t work just yet. In the next chapter you’ll learn how to make
the buttons (or other components) to react to user actions, so you’ll be able to complete the calculator. In this
chapter my goal was to introduce you to basic rules of designing JavaFX GUI with the help of Scene Builder.
Watch this YouTube video ([Link] to see how easy it is to design more
complex views with Scene Builder. :toc-placement!: :imagesdir: .

[Link] 143/303
22/03/2025, 18:48 Programação Java para crianças

8. Programming User Interaction in JavaFX


After the GUI design is done, we need to hook it up with the application code written in Java. The Sign In and
Calculator windows from Chapter 7 look good, but none of them would react to a user’s actions. No matter how
hard you click on the Sign In or calculator’s buttons, nothing will happen because we didn’t teach the application
how to react to user-generated events. Events are notifications that something important for the application has
happened (e.g. the user clicked on the button). In this chapter I’ll explain how to write code to handle such
events.

When IDEA creates a new JavaFX project it generates an empty class Controller , which is the right place for
the code that communicates with GUI components. In this chapter we’ll establish a link between GUI and the
controller. We’ll also add event handlers and will write code to modify the GUI. I’ll continue working with
FXML samples created in the previous chapter, but this time the GUI events will be handled by the code from
the controller class.

You’ll learn how data binding can automatically update the properties of a GUI component if a property of a
Java controller class changes. I’ll also show the difference between wrong and the right way of updating the GUI
to make the used interaction more responsive.

8.1. Events
JavaFX applications have to deal with various events. For example, a button click, the movement of the mouse
etc. When the event happens, the event object is represented by one of the subclasses of the class Event located
in the packages [Link] and [Link] . You need to decide what events are important to
your program and, as the programmers say, "listen to these events". You’ll always write event handlers (a.k.a.
event listeners) in Java, but there are different ways of assigning event handlers to GUI elements. If your GUI is
designed using FXML, you’ll need to specify the name of your controller class right in the FXML file. If your
GUI is designed with Java, using a separate controller class is not a must, but is a good idea if your code has to
process multiple events.

[Link] 144/303
22/03/2025, 18:48 Programação Java para crianças

You can create an instance of your controller class either with the new operator or inject it into Java code. I’ll
explain what injection means in a bit.

8.1.1. Assigning Event Handlers in FXML


Scene Builder allows you to not only design and arrange the GUI components on the scene, but also assign the
Java code that will be handing events. We’ll stick to our principles of separating GUI and application logic, and
will keep the GUI in .fxml file, meanwhile application logic will be programmed in Java.

In Scene Builder you may have noticed the Controller bar in the bottom left corner. This is the place were you
can specify a Java class that will contain event handling code and may use other classes implementing
application logic. You can also open your .fxml file in the text editor and type in the name of the controller
class there. If you’ll look at any of the FXML files from Chapter 7, you’ll see that the name of the controller was
specified there when IDEA generated the project for us.

8.1.2. Adding Controller to Sign In application


To illustrate the use of controllers, I’ll continue working on the sample Sign In project from Chapter 7. It has a
file [Link] that includes the GridPane tag as a root element:

XML
<GridPane hgap="10" vgap="10"
xmlns="[Link] xmlns:fx="[Link]
fx:controller="[Link]">

[Link] 145/303
22/03/2025, 18:48 Programação Java para crianças

The hgap and vgap attributes specify the padding between the grid columns and rows. The xmlns attributes
specify so called namespaces required for proper parsing of FXML files. And the attribute fx:controller
specifies the full name of the class Controller , which in our project is located in the package signin .

When the file [Link] is loaded, FXMLLoader creates an instance of the Java class based on the FXML
content and then instantiates and injects the`[Link]` object into the GUI object. The word inject
describes the process when a runtime automatically instantiates a class B and makes it available in class A. For
us it means that there is no need to manually create an instance of the [Link] by using the new
operator.

The first version of the Controller class is shown next:

JAVA
package signin;

import [Link];

public class Controller {

public void signInClicked(ActionEvent evt){

[Link]("Hello from signInClicked method in controller");


}
}

The class Controller uses the class ActionEvent from package [Link] , and I want to warn you -
be careful when IDE will offer to insert an import statement for you. There is also an ActionEvent in the
package [Link] , which we don’t want in JavaFX applications.

We want the method signInClicked to be called on the controller if the user clicks on the button. For this to
happen, we can specify the name of this method as a handler of the onAction property in the <Button>
element in [Link] as shown on Figure 8-2.

[Link] 146/303
22/03/2025, 18:48 Programação Java para crianças

Figure 70. Mapping onAction property to the signInClicked method

If you run the Main program and click the Sign In button three times, the console will print the hello message
three times as shown on Figure 8-3.

Figure 71. After clicking 3 times on Sign In button

So there is a link between the GUI and the controller. If we had several buttons on the GUI, we could either map
each of them to a separate method in controller, or have one method for all buttons with the code recognizing
which button was clicked. The controller will invoke your event handler providing the ActionEvent object as
an argument. Its property target identifies the target of the event, which is a Sign In button in our case.

I ran our application in the debug mode just to show you that the target property on the ActionEvent
correctly recognizes the event target shown in Figure 8-4.

[Link] 147/303
22/03/2025, 18:48 Programação Java para crianças

Figure 72. Viewing properties of ActionEvent in debugger

The ActionEvent has another property called source , which has the same value as target in our
application. There are cases when source and target are different because an event travels through all
containers until it reaches the target. Then it bubles up through all the containers. This is an advanced topic, but I
still want to give you an illustration.

While handling button clicks, you don’t really care where exactly inside the button was the mouse pointer when
the user clicked on the button. So handing ActionEvent was sufficient. But there is another event called
MouseEvent , which gives you more details on the click event like the coordinate of the mouse pointer, or if
some of the keys were down during the click.

In [Link] you’re allowed to use onMouseClicked instead of onAction for the button. But if you do
so, the Button will be considered a container for a special skin class LabeledText with the text Sign In, and
if you click on the words Sign In the source of the event will be Button , and the target would be the class
LabeledSkin . Just for the illustration purposes, I’ve created an event handler signInMouseClicked and ran
it through a debugger. Now the source and target of the event are different.

[Link] 148/303
22/03/2025, 18:48 Programação Java para crianças

Figure 73. Viewing properties of MouseEvent in debugger

8.1.3. Data Exchange Between GUI Components And Controller


Now that we know how to link the controller’s event handlers to FXML components, the next question is how to
read/write data from/to these components. In the case of the sign in application we need to know what
ID/password the user entered and update the GUI from the controller accordingly.

To read the values from GUI components we’ll need to give them unique id’s in the FXML file. We don’t need
to give id’s to all components - only to those that we want to process in the controller’s code. Take a look at the
<childrens> section of [Link] :

XML
<children>
<Label alignment="CENTER" text="User ID:" />
<Label text="Password:" styleClass="bluelabel" [Link]="1" />
<Button id="submitBtn" mnemonicParsing="false" prefWidth="300.0" text="Sign In"
[Link]="2" [Link]="2"
onAction="#signInClicked"/>
<TextField [Link]="1" fx:id="id" />
<PasswordField [Link]="1" [Link]="1" fx:id="pwd"/>
</children>

[Link] 149/303
22/03/2025, 18:48 Programação Java para crianças

Only the TextField and PasswordField have the attribute fx:id - this is how you can assign id’s in
FXML. The next step is to inject references to these GUI components into the variables in the Controller
class. The following code fragment shows how to inject component references into the id and pwd fields. I’ve
declared two Java variables in the Controller class with the names that match those from [Link] :

JAVA
@FXML private TextField id;

@FXML private PasswordField pwd;

Java has so called annotations ([Link] (not covered in this book). They
start with the @ sign and can be placed in front of the variable, class, or a method declaration depending on how
the annotation was defined. Some annotations are used by Java compiler, and some by the JVM. The JavaFX
annotation @FXML instructs runtime to inject the references to the specifies GUI objects into the variables.

In other words, JavaFX runtime will read the first line as follows: "I need to get the object that I created after
loading [Link] file, and find the component with fx:id="id" inside this object. Finally, I need to
insert the reference to this component into the Java variable id ". The same applies to the variable pwd .

The rest is easy. Just use the injected values in your event handler. The code of our Controller is shown next.
Its method signInClicked checks the value entered in the User ID field in the GUI, and if it’s not equal to
"Yakov", then the code sets the background of the GUI component to the light pink color.

JAVA
public class Controller {

@FXML private TextField id; (1)

@FXML private PasswordField pwd; (1)

public void signInClicked(ActionEvent evt){

String userID = [Link](); (2)


String password = [Link](); (2)

if (!"Yakov".equals(userID)){ (3)
[Link]("-fx-background-color:lightpink;"); (4)
} else{
[Link]("-fx-background-color:white;"); (5)
}

[Link]("got id:" + userID + ", got password: " + password);

[Link]("Hello from signInClicked method in controller");


}
}

1. Inject the references to GUI components into member variables.

[Link] 150/303
22/03/2025, 18:48 Programação Java para crianças

2. Extract the text from the GUI objects

3. Has the user not entered Yakov in the User ID field? We use the negation operator ! here.

4. Set the background color to lightpink if the entered user id is not Yakov. You can find major CSS color
names at [Link]

5. Set the background color to back to white if the entered user id is not Yakov.
If you run the Main program and enter the wrong user id, the window will look as follows:

Figure 74. After entering the wrong user id

8.1.4. Assigning Event Handlers in Java


If your program is written completely in Java without any use of FXML, you’ll be assigning event handlers
using so called convenience methods ([Link] that have names
that start with setOn like setOnAction , setOnKeyTyped , setOnEditStart etc. Each of the GUI
components have several of such methods.

You can provide event handling code to the convenience methods using anonymous inner classes, lambda
expressions, or method references ([Link] (not
covered in this book). Implementing event handlers as lambda expressions is easier than with anonymous inner
classes. Typically, you’ll be writing code to react if an event has happened. For example, if you have a button
represented by a variable myButton you can write an event handler for the click event:

[Link] 151/303
22/03/2025, 18:48 Programação Java para crianças

JAVA
Button signInButton = new Button("Sign In");
[Link](evt ->
[Link]("The Sign In button was clicked.")
);

You’ve been introduced to lambda expressions in Chapter 5. The above code snippet means that lambda
expression gets the event object as an argument, but doesn’t really use its values but just prints the message that
the Sign In button was clicked.

What’s the type of evt argument? Java compiler will figure it out automatically. Since the method
setOnAction expects to get the ActionEvent object from the JVM, the compiler guesses that the type of
evt is ActionEvent so you don’t even need to write it in the program code. You’ve seen a similar example of
type inference in Chapter 5.

To bring all pieces of the puzzle together, I’ll show you another version of the Sign In application that will look
the same, but won’t use FXML - everything will be programmed in Java. The following class MainPureJava
and the file [Link] are all we need for programming the functionality of our Sign In window. There is not
need to use [Link] or [Link] in this case.

[Link] 152/303
22/03/2025, 18:48 Programação Java para crianças

JAVA
package signin;

import [Link];
import [Link];
import [Link];
import [Link].*;

public class MainPureJava extends Application {

public void start(Stage primaryStage) {

final int TWO_COLUMN_SPAN = 2; (1)

Label userIdLbl = new Label("User ID:"); (2)


TextField userIdTxt = new TextField();
Label userPwdLbl = new Label("Password:");
[Link]().add("bluelabel");
PasswordField userPwdTxt = new PasswordField();

GridPane root = new GridPane(); (3)


[Link](20);
[Link](new Insets(10));
[Link]([Link]);
[Link]("root");

// Setting constraints for firs 2 rows


[Link](userIdLbl, 0, 0); (4)
[Link](userIdTxt, 1, 0);
[Link](userPwdLbl, 0, 1);
[Link](userPwdTxt, 1, 1);

[Link]().addAll(userIdLbl, userIdTxt,
userPwdLbl, userPwdTxt); (5)

Button signInBtn = new Button ("Sign In"); (6)


[Link]("submitBtn"); // used in CSS

// Event handler with lambda expression


[Link](evt -> { (7)

String userID = [Link]();


String password = [Link]();
if (!"Yakov".equals(userID)){
[Link]("-fx-background-color: lightpink;");
} else{
[Link]("-fx-background-color: white;");
}

[Link]("Got id " + userID +


" and password " + password);
});

[Link] 153/303
22/03/2025, 18:48 Programação Java para crianças

// Allow the button to be wider


[Link](Double.MAX_VALUE);

// Adding a wide button to the third row


[Link](signInBtn,0,2,TWO_COLUMN_SPAN,1);

Scene scene = new Scene(root,250,180);


[Link]() (8)
.add(getClass()
.getResource("[Link]")
.toExternalForm());

[Link](scene); (9)
[Link]();
}

public static void main(String[] args) {


launch(args);
}
}

1. This programs uses the GridPane layout with three rows and two columns. Since the Sign In button will
span two columns, I declared a final variable TWO_COLUMN_SPAN that will be used when the button will be
added to the grid.

2. Then I instantiate labels and text fields.

3. After that I create an instance of the GridPane container.

4. To add the labels and text fields to the proper cells of the first two rows of the grid, I set the constraints on
the GridPane object.

5. The GUI components for the first two rows are instantiated, constraints are set so I add them as children to
the root of the scene graph - the GridPane .

6. Now I create the instance of the Sign In button and give it an id. This was explained in the "Styling with
CSS" section in Chapter 7.

7. This lambda expression implements the application logic to be invoked as a reaction to the ActionEvent .

8. We create a scene object and apply the CSS to it. This is probably the first time you see so called method
chaining. All these lines that starts with dots are methods chained together - all of them are sequentially
invoked on the scene object.

9. Finally, the scene is added to the stage and the curtain goes up.

Some programmers prefer working GUI designer tools where they can drag and drop components. Some prefer
writing Java code for UI. I like the declarative way of designing GUI components with FXML, because it’s just
more productive. The fact that FXML separates the screen design from the application logic is great because

[Link] 154/303
22/03/2025, 18:48 Programação Java para crianças

even a person who doesn’t know programming (e.g. a UI designer) can master Scene Builder and create nice
GUI layouts allowing programmers to take care of application logic.

8.1.5. Further Reading on Event Handling


I’ve covered the basics of event handling using the ActionEvent and onAction event handler as an
example. Some other examples of the events are:`KeyEvent` (the user pressed a key on the keyboard),
MouseEvent (the user pressed the mouse key and we need to know coordinates of the mouse pointer),
TouchEvent (the user touched the screen), WindowEvent (e.g. the user is about to close the window) et al.
For more detailed explanation of JavaFX events visit Oracle’s tutorial about handling events at
[Link]

8.2. Data Binding and Properties


JavaFX has the interface Property located in the package [Link] , which defines a very
useful functionality allowing to bind the GUI components with properties of other Java objects. If a property on
a Java object changes, the new value will be automatically reflected on the appropriate GUI component and visa
versa. Bi-directional binding is available too, so no matter what changes - the GUI or the Java object - the other
party will be immediately notified.

Imagine that you’re developing a multi-player game that has a Java object receiving the moves of other gamers
from a central server. When a Java object receives a new move, you need to modify the content of the
corresponding GUI component of the game. With JavaFX you can simply bind a property of a Java class that
stores player’s moves (e.g. playersMove ) to the property of, say a Label component on the GUI. No more
coding is required. As soon as the playersMove value changes, the Label will be automatically updated.
JavaFX properties greatly simplify the synchronization of the data and the GUI.

Existing implementations of the Property interface add the change notification functionality to regular class
attributes. The interface Property declares the following methods: bind , unbind , bindBidirectional ,
unbindBidirctional , and isBound . You can bind to a JavaFX property only the value of an
ObservableValue type, which is explained in the sidebar.

Design Patterns Briefly


Over the years software developers have come up with a number of design patterns, which are reusable
solutions for various programming tasks. Programmers casually use design pattern names in their
conversations and technical literature. For example, one programmer can say to another , "You’d better
implement MVC in this program" and both understand what this means. Let me introduce you briefly to a
couple of design patterns - MVC and Observer - so you’ll be a little better prepared for chatting with
programmers.

[Link] 155/303
22/03/2025, 18:48 Programação Java para crianças

MVC stands for Mode View Controller. This design pattern recommends separating the code that stores
application data (Model) from the code implementing the user interface (View) and from the code that
controls the data exchange and implements application logic (Controller). As a matter of fact we’ve
almost implemented MVC in one of the versions of the Sign In application. The file [Link] was a
view, and the class Controller played a role of a controller. Since this example had just two variables
( id and pwd ) we didn’t create a special model class for them.

Observer design pattern is used to implement scenarios when one object, a.k.a. the observer needs to
watch changes in other object(s), the observables. For example, if a Twitter user (the observable) posts a
twit all of his followers (observers) will get notified. If a programming language or a library supports data
binding, implementing the observer design pattern becomes pretty easy, which you’ll see later in this
chapter.

If you’re interested in detailed coverage of design patterns, get the book "Head First Design Patterns"
published by O’Reilly Media.

Classes that implement Property interface are located in the package [Link] . For each
property type there are two classes: one that allows only reading property values and the other one for read and
writing (changing the values). For example, if you need a String property, use either
ReadOnlyStringWrapper or SimpleStringProperty . Similarly named classes exist for other data types
and some collections too.

As we always do in this book, let’s learn by coding. I’ll continue adding features to our Sign In application. This
time I’ll add a Label component with fx:id="errMsg" to the view in FXML file to display sign in error
messages, if any. In the controller class I’ll add the corresponding variable errMsg and will inject a reference to
the Label into this variable.

The next step is to declare a bindable property signinError in the class Controller that will get the value
of the error message if any. But since a regular String can’t be bindable, we’ll use the data type
SimpleStringProperty

Finally, I’ll bind the label to the variable to insure that an error message is immediately displayed on the screen
as soon as its value changes.

Let’s place an additional Label component at the bottom of the Sign In window. I’ll add another row to the
GridPane and place a Label there that will span two columns. This label will have fx:id="errMsg" and
initially won’t have any text - it’ll be invisible. The <children> section of the FXML file will look as follows:

[Link] 156/303
22/03/2025, 18:48 Programação Java para crianças

XML
<children>
<Label alignment="CENTER" text="User ID:" />
<TextField [Link]="1" fx:id="id" />
<Label text="Password:" styleClass="bluelabel" [Link]="1" />
<PasswordField [Link]="1" [Link]="1" fx:id="pwd"/>
<Button id="submitBtn" mnemonicParsing="false" prefWidth="300.0" text="Sign In"
[Link]="2" [Link]="2"
onAction="#signInClicked"/>
<Label alignment="CENTER" [Link]="3"
[Link]="2" prefWidth="300.0" fx:id="errMsg"/>
</children>

Injecting a reference of the new label into controller and declaring a property to store the error message will look
like this:

JAVA
@FXML private Label errMsg;

SimpleStringProperty signinError = new SimpleStringProperty();

The next question is when and where do the binding? If I’d been creating an instance of the Controller with
the new operator I could have done it in the class constructor after the GUI component was created. But JavaFX
runtime instantiates the Controller for us, so how can we catch the moment when the GUI components are
ready?

In JavaFX if you’ll add to the controller the method initialize annotated with @FXML , FXMLLoader will
invoke it after all GUI components are constructed.

JAVA
@FXML public void initialize() {

[Link]().bind(signinError);
}

JavaFX properties are observables. So you can read the above code as follows: "I want the text property of the
label errMsg to be the observer (a.k.a. listener) to the property signinError (observable). So whenever
signinError changes, the text property of the label will get the latest value."

To complete the Sign In example with the binding, the event handler for the Sign In button should not only paint
the wrong ID in light pink, but also modify the value of the signinError property. The complete code of the
class BindableController is shown next.

[Link] 157/303
22/03/2025, 18:48 Programação Java para crianças

JAVA
public class BindingController {

@FXML
private TextField id;

@FXML
private PasswordField pwd;

@FXML private Label errMsg;

SimpleStringProperty signinError = new SimpleStringProperty();

@FXML public void initialize() {


[Link]("Controller's ready. Let's bind some components");

[Link]().bind(signinError);
}

public void signInClicked(ActionEvent evt){

String userID = [Link]();


String password = [Link]();
if (!"Yakov".equals(userID)){
[Link]("-fx-background-color: lightpink;");
[Link]("Wrong id:" + userID);

} else{
[Link]("-fx-background-color: white;");
[Link]("");
}

[Link]("got id:" + userID + ", got password: " + password);

[Link]("Hello from signInClicked method in controller");


}
}

Note that in the if statement I set the error message when the ID is wrong, and reset the signinError to an
empty string when the ID is correct. To test the program I’ve entered Alex as the user ID and clicked the button
Sign [Link] window looked like this:

[Link] 158/303
22/03/2025, 18:48 Programação Java para crianças

Figure 75. Binding in action after entering the wrong user id

Enter the right user ID, click on Sign In again, and the binding mechanism will remove the error message from
the window.

8.3. The Application Thread in JavaFX


In Chapter 6 I gave you a light introduction to multi-threading. When you work with JavaFX you have to run the
code that updates the GUI and the code that performs application logic in separate threads. Allow me to
ellaborate.

Imagine a program with a GUI that’s constantly being updated based on some intensive calculations. It could be
a game with multiple moving shapes. It could be an application for a TV channel that may show a video stream,
commercials, viewers polls and more. It could be a business application that displays several pieces of constantly
changing information in different parts of the window like prices on eBay auction.

Updates of the GUI in JavaFX are done in so called application thread. The idea is to separate calculations from
the GUI updates. Say, the user clicked on the button Play on a JavaFX video streaming application like Netflix.
If the requests for the remote video and actual playing of the video (GUI updates) would be done in the same
application thread, the video would be choppy - it would be interrupted by running business logic that prepares
the GUI content. The screen would be "frozen" and the user wouldn’t be able to use any screen components.

8.3.1. The Frozen Screen Demo


I will demonstrate for you a "frozen GUI" effect by making a small change in the class Controller in our
Sign In application. The simplest way to emulate a long running process is to place the currently running thread
to sleep, as if there is an application logic that takes some time to complete. For example, to put the current

[Link] 159/303
22/03/2025, 18:48 Programação Java para crianças

thread to sleep for 10 second, you can write the following:


JAVA
try {
[Link](10000); // Sleep for 10 sec

} catch (InterruptedException interExp) {


[Link]();
}

This code snippet has so-called try-catch block, which is required in some cases for error handling. The next
chapter explains the error processing subject in details. But at this point let’s just focus on the code located inside
the curly braces after the keyword try .

The method sleep of class Thread takes one argument - the sleeping time in milliseconds. There are 1000
milliseconds in one second, so the above code snippet will place the current thread to sleep for 10 seconds.

Remember, the controller class has an event handler for the Sign In button? It executes in the JavaFX application
thread. I’ll add the 10-second sleeping code to the application thread to emulate the process that would perform
the actual sign in. Actually, this is wrong - you should execute the application logic in a separate thread. But I do
this on purpose to demonstrate the frozen effect.

The following code fragment from the new controller class shows how the event handler signInClicked
invokes the method named wrongStartOfLongRunningProcess , which sleeps for 10 seconds and then
checks if the entered user ID is Yakov.

[Link] 160/303
22/03/2025, 18:48 Programação Java para crianças

JAVA
public void signInClicked(ActionEvent evt){

String userID = [Link]();


String password = [Link]();

wrongStartOfLongRunningProcess(userID);

[Link]("got id:" + userID + ", got password: " + password);


}

private void wrongStartOfLongRunningProcess(String uID) {


try {
[Link](10000); // Sleep for 10 sec
} catch (InterruptedException interExp) {
[Link]();
}

if (!"Yakov".equals(uID)){
[Link]("-fx-background-color: lightpink;");
} else{
[Link]("-fx-background-color: white;");
}
}

When the user clicks on the Sign In button, the application thread will become busy for 10 seconds, and only
then checks the user ID and set the background color of the TextField on the screen. If you’ll run the Sign In
sample with such event handler, the application window becomes frozen and unresponsive for 10 seconds. If the
user will try to reenter the ID, he’ll see a wait cursor. On MAC OS computers such a cursor looks as a spinning
wheel of death as shown on Figure 8-7.

[Link] 161/303
22/03/2025, 18:48 Programação Java para crianças

Figure 76. Frozen Screen with a wheel of death

Ten seconds later the application thread wakes up, and the GUI becomes responsive again. Let’s fix this code
and create a separate thread emulating the long running process so that the application thread can continue
working with GUI. The following code listing shows the complete code of the class
ControllerLongRunningThread , which doesn’t freeze the window.

[Link] 162/303
22/03/2025, 18:48 Programação Java para crianças

JAVA
public class ControllerLongRunningThread {

@FXML private TextField id;

@FXML private PasswordField pwd;

public void signInClicked(ActionEvent evt){

String userID = [Link]();


String password = [Link]();

rightStartOfLongRunningProcess(userID);

[Link]("got id:" + userID +


", got password: " + password);
}

private void rightStartOfLongRunningProcess(String uID) {

Runnable loginTask = () -> { (1)


try {
[Link](10000); (2)

[Link](() -> { (3)


if (!"Yakov".equals(uID)){
[Link]("-fx-background-color: lightpink;");
} else{
[Link]("-fx-background-color: white;");
}
});

} catch (InterruptedException interExp) {


[Link]();
}
}; (4)

Thread workerThread = new Thread(loginTask); (5)


[Link](); (6)
}
}

1. The code in the method rightStartOfLongRunningProcess declares the lambda expression


loginTask as an implementation of the Runnable interface. At this point no thread has been created yet
- we’ll do it at the end of the method rightStartOfLongRunningProcess .

2. The lambda expression places the current thread to sleep for 10 second, but it won’t be the application
thread, because we’ll create a separate worker thread for it (see the notes 5 and 6 below).

3. Quando o sleep termina, precisamos passar o controle de volta do worker para o thread do aplicativo para
atualizar a GUI. Para isso, o JavaFX tem um método especial runLater na classe Platform . O método
runLater colocará a solicitação para atualizar a GUI em uma fila de eventos especial do thread do

[Link] 163/303
22/03/2025, 18:48 Programação Java para crianças

aplicativo.
4. Fim da declaração da expressão lambda

5. Agora criamos a instância do thread de trabalho passando a expressão lambda para ele.

6. O método start da classe Thread inicia a execução do código lambda em um thread de trabalho
separado.
No capítulo sobre o jogo Ping-Pong, usaremos vários threads também. Um thread será responsável por exibir a
mesa de ping-pong, enquanto o outro calculará as coordenadas da bola e das raquetes.

8.4. Implantando com o JavaFX Packager


Como você inicia um aplicativo JavaFX? Bem, você pode iniciá-lo a partir do IDE ou de uma linha de comando
como qualquer outro aplicativo Java. Mas se você quiser dar seu aplicativo para sua avó, que pode não ser tão
boa em Java quanto você? Claro, você pode fazer uma visita a ela, instalar o Java runtime em seu computador e
ensiná-la a abrir uma janela de comando ou Terminal e digitar java [Link] .

Você pode aprender como usar linguagens de script e criar um arquivo [Link] no Windows ou
[Link] no MAC OS que terá o java [Link] comando dentro. Você pode até mesmo criar um ícone
que executará esse script. Mas e se todos na sua escola quiserem ter seu programa instalado em seus
computadores? Agora se torna uma tarefa demorada.

Mas a melhor maneira de preparar seu aplicativo JavaFX para distribuição é criar um arquivo self-contained
[Link] para Windows ou [Link] MAC OS. Este arquivo conterá tanto o Java runtime quanto o
código do seu aplicativo. Este processo é descrito em detalhes no tutorial da Oracle intitulado "Self-Contained
Application Packaging" ([Link] . Não vou
repetir este tutorial aqui, mas vou deixá-lo para você como um projeto de autoestudo.

Tenho certeza de que muitos de vocês querem saber se é possível usar JavaFX para escrever aplicativos para
smartphones. A Oracle não oferece as bibliotecas JavaFX para plataformas móveis, mas ainda é possível.

Para desenvolver aplicativos JavaFX para iOS, você precisa instalar e aprender por conta própria algum software
adicional, chamado RoboVM ([Link] , que é um SDK para converter bytecode Java em um
código de dispositivo nativo como se tivesse sido escrito na linguagem de programação C, o que o torna
implantável em dispositivos iOS.

Há também um site comunitário JavaFX Ports [ [Link] ] onde as pessoas estão


trabalhando na implantação de aplicativos JavaFX em dispositivos iOS e Android.

[Link] 164/303
22/03/2025, 18:48 Programação Java para crianças

8.5. O que estudar a seguir sobre JavaFX


Nos Capítulos 7 e 8, dei uma breve introdução ao JavaFX. Você escreverá mais código JavaFX nos capítulos 9,
10 e 13, mas o JavaFX tem muitos recursos interessantes que você pode querer explorar por conta própria. O
JavaFX tem mais de 60 componentes GUI, então tente brincar com eles. Além disso, o JavaFX permite que você
integre áudio e vídeo em seu aplicativo, crie efeitos especiais e transições para tornar seus programas tão legais e
divertidos quanto você deseja. Você pode encontrar alguns recursos interessantes pesquisando classes localizadas
no pacote [Link] .

Pegue um livro sobre JavaFX 8 ou posterior e experimente você mesmo. Um dos melhores livros sobre o
assunto é "Pro JavaFX 8: A Definite Guide to Building Desktop, Mobile, and Embedded Java Clients" publicado
pela Apress.

8.6. Projeto: Adicionando Manipulação de Eventos para Calculadora


O objetivo deste projeto é completar o programa da calculadora. Se você completou o projeto do Capítulo 7,
você pode continuar trabalhando nele. Mas se você não conseguiu completá-lo sozinho, baixe a versão da GUI
da calculadora que vem com o código de exemplo para este capítulo.

1. Crie uma classe Java CalculatorController no mesmo projeto IDEA onde a GUI da calculadora está
localizada.

2. Modifique o arquivo [Link] : adicione o atributo


fx:controller="CalculatorController" para que ele saiba o nome da classe com a lógica do
aplicativo. Use o código [Link] deste capítulo como referência.

3. Crie dois métodos de manipulador de eventos separados na classe CalculatorController . Nomeie o


primeiro método digitClickedHandler - ele conterá o código para processar cliques nos botões de
dígitos. Nomeie o segundo método operationClickHandler - ele conterá o código para processar
cliques em botões como Mais, Menos, et al.

4. Modifique o arquivo [Link] e atribua o nome do método manipulador de cliques para cada
botão usando o atributo, onAction como fizemos no exemplo de Login.

5. Em cada método manipulador, adicione o código para reconhecer qual botão foi clicado. Você pode fazer o
rótulo do botão clicado consultando o ActionEvent objeto que será fornecido para cada método
manipulador de eventos. Por exemplo, se a variável evt representa o ActionEvent objeto, o código pode
ficar assim:

JAVA
Button clickedButton = (Button) [Link]();
String buttonLabel = [Link]();

6. Se o usuário clicar no botão de dígito, obtenha o valor atual do campo de exibição da calculadora, concatene
o rótulo do botão e atribua o novo valor de volta ao campo de exibição.

[Link] 165/303
22/03/2025, 18:48 Programação Java para crianças

7. Você precisa declarar uma variável, digamos valueOne no controlador para armazenar o valor atual do
campo de exibição quando o usuário clica no botão de operação. Por exemplo, se o usuário clicou no botão
com o rótulo + , - , / , ou * , é um sinal de que o usuário terminou de inserir o primeiro número.
Armazene-o na variável valueOne e limpe o campo de exibição para que o usuário possa começar a inserir
o segundo número.

8. Declare a variable, say operation , to remember the operation that the user wants to perform. For
example, if the user clicked on + , store + in the variable operation .

9. If the user clicks on the button = , get the value from valueOne and from the display field and perform the
operation according to the value in operation . Use the switch statement to perform different
operations.

10. After the operation is complete, assign the result to the display field by using the method setText of the
TextField component.

11. Store the calculated result in the variable valueOne so the user can continue performing other operations.
For example if the first operation was 2+3, the display shows 5, and the user can click on the buttons *
followed by 4 requesting multiplication of 5 by 4.

8.6.1. Challenge Yourself


The step 10 in the project assignment suggests that you should use the the method setText of the TextField
component. See if you can apply the property binding technique to display the result in the display field. :toc-
placement!: :imagesdir: .

[Link] 166/303
22/03/2025, 18:48 Programação Java para crianças

9. Dealing With Run-time Errors


In this chapter I’ll explain to you how to handle run-time errors, which in Java are called exceptions.

Say you forgot to write one closing curly brace in your Java code. This will result in a compilation error that can
be fixed easily. But there are so called run-time errors, when your program stops working properly and prints
error messages.

For example, a Java class reads a file with the game scores. What’s going to happen if someone will delete this
file? Will the program crash with a scary error message, or will it stay alive displaying a user friendly message
like this one: Dear friend, for some reason I could not read the file [Link]. Please make sure that the file
exists? This is an example of a situation when Java compiler won’t be able to help - the Java syntax was written
properly.

You should make your programs ready for unexpected situations. you should foresee what might go wrong when
the program will be running, and what to do if something went wrong. In many programming languages the
programmer decides if he wants to add error processing code to a program. But in many cases Java forces you to
include error processing code, otherwise the programs will not even compile.

Runtime errors in Java are called exceptions, and error processing is called exception handling. You have to
place code that may produce errors in so-called try/catch block. It’s as if you’re saying to JVM the
following: Try to read the file with scores, but if something happens, catch the error and execute the code that
will deal with it:

JAVA
try{
[Link]();
}
catch (IOException ioe){
[Link](
"Dear friend,I could not read the file [Link]" +
[Link]());
}

The ioe in the above code fragment is a variable that represents the IOException object given to the catch
block by the Java runtime. You can give this variable any name you like. The getMessage will return the text
describing what happened during the file read.

We’ll learn how to work with files in Chapter 11, but at this point I’d like to introduce a new term I/O or
input/output. Read and write operations (from/to disk or other device) are also known as I/O operations, and the
class IOException is a class that contains information about input/output errors.

[Link] 167/303
22/03/2025, 18:48 Programação Java para crianças

In the Java world, a method throws an exception in case of a runtime error. Different exceptions will be thrown
for different type of errors. If the catch block exists in the program for this particular type of an error, it will be
caught and the program will jump into the catch block to execute the code located there. The program will
stay alive, and this exception is considered to be taken care of.

The print statement from the code above will be executed only in case of a file read error.

9.1. Reading the Stack Trace


If an unexpected exception occurs that is not handled by the program, it prints a multi-line error message on the
screen. Such message is called a stack trace. If your program called several methods before it ran into a problem,
the stack trace can help you to trace the program, and find the line that have caused the error.

We know that dividing by zero is illegal, but I wrote a program TestStackTrace that divides by zero on
purpose just to show how the error and the stack trace could look like.

JAVA
1 class TestStackTrace{
2 TestStackTrace()
3 {
4 divideByZero();
5 }
6
7 int divideByZero()
8 {
9 return 25/0;
10 }
11
12 static void main(String[] args)
13 {
14 new TestStackTrace();
15 }
16 }

The output of this program shows the sequence of method calls that were made up to the moment when the run-
time error had happened. Start reading this output from the last line going up.

JAVA
Exception in thread "main"
[Link]: / by zero
at [Link]([Link])
at TestStackTrace.<init>([Link])
at [Link]([Link])

This means that the program started in the method main , then went to init , which is a constructor, and then
called the method divideByZero . The numbers 14, 4 and 9 show the program line numbers where these
methods were called. After that, an exception (an error) ArithmeticException was thrown – the line number

[Link] 168/303
22/03/2025, 18:48 Programação Java para crianças

nine tried to divide by zero.

9.2. Genealogical Tree of Exceptions


Exceptions in Java are also classes, and some of them are shown in the following inheritance tree:

[Link] 169/303
22/03/2025, 18:48 Programação Java para crianças

[Link] 170/303
22/03/2025, 18:48 Programação Java para crianças

Figure 77. Exceptions Hierarchy

Subclasses of the class Exception are called checked exceptions and you must process them in your code.

Subclasses of the class Error are fatal JVM errors and the running program can’t handle them.

The TooManyBikesException is an example of an exception that can be created by a programmer.

How is a programmer supposed to know in advance if some Java method may throw an exception and that a
try/catch block should be used? Not to worry, if you call a method that may throw an exception, Java
compiler will print an error message similar to this one:

JAVA
"[Link]": unreported exception: [Link]; must be caught or declared to
be thrown at line 57

Of course you are welcome to read Java documentation that describes exceptions that may be thrown by any
particular method. The rest of this chapter will explain how to deal with these exceptions.

9.3. Try/Catch Block


There are five Java keywords that can be used for error handling: try , catch , finally , throw , and
throws .

After one try block you may put several catch blocks, if you believe that more than one error may happen.
For example, when a program tries to read a file, the file may not be there, and you’ll get the
FileNotFoundException , or the file is there, but the code keeps reading the file after reaching the end of file
– this generates EOFException . The next code fragment will print messages in plain English if the program
can’t find a file with game scores or reached the end of the file. For any other read errors it’ll print the message
Problem reading file and a technical description of the error.

[Link] 171/303
22/03/2025, 18:48 Programação Java para crianças

JAVA
public void getScores(){
try{
[Link]();
[Link](“Scores loaded successfully”);
}catch(FileNotFoundException e){
[Link](“Can not find file Scores”);
}catch(EOFException e1){
[Link](“Reached end of file”);
}catch(IOException e2){
[Link](“Problem reading file “ +
[Link]());
}
}

If the method read fails, the program jumps over the line println and tries to land in the catch block that
matches the error. If it finds such block, the appropriate method println will be executed, but if the matching
catch block is not found, the method getScores will re-throw this exception to its caller.

If you write several catch blocks, you may need to place them in a particular order if these exceptions are
inherited from each other. For example, since the EOFException is a subclass of the IOException , you have
to put the catch block for the subclass first. If you would put the catch for IOException first, the program
would never reach the FileNotFound or EOFException , because the first catch would intercept them.

Some lazy programmers would write the method getScores just like this:

JAVA
public void getScores(){
try{
[Link]();
}catch(Exception e){
[Link](“Problem reading file ”+
[Link]());
}
}

This is an example of a bad style of Java coding. When you write a program, always remember that someone
else may read it, and you don’t want to be ashamed of your code.

Catch blocks receive an instance of the object Exception that contains a short explanation of a problem, and
its method getMessage will return this info. Sometimes, if the description of an error is not clear, try the
method toString instead:

JAVA
catch(Exception e){
[Link](“Problem reading file ”+ [Link]());
}

[Link] 172/303
22/03/2025, 18:48 Programação Java para crianças

If you need more detailed information about the exception, use the method printStackTrace . It will print the
sequence of method calls that lead to this exception similar to an example from the section Reading Stack Trace.

9.4. The keyword throws


In some cases, it makes more sense to handle the exception not in the method where it happened, but in the
method’s caller. In such cases the method signature has to declare (warn) that it may throw a particular
exception. This is done using a special keyword throws . Let’s use the same example that reads a file. Since the
method read may throw an IOException , you should either handle or declare it. In the next example we are
going to declare that the method getAllScores may throw an IOException:

JAVA
class MySuperGame{

void getAllScores() throws IOException{


// …
// Do not use try/catch if you are
// not handling exceptions in this method
[Link]();
}

public static void main(String[] args){


MySuperGame msg = new MySuperGame();
[Link](“List of Scores”);

try{
// Since the getAllScores()declares exception,
// we handle it over here
[Link]();

}catch(IOException e){
[Link](
"Sorry, the list of scores is not available");
}
}

Imagine that the MySuperGame program invokes multiple methods that read or write files and get some data
from a remote server. We may want to process all possible exceptions in one place – the main method. In this
case there is no need to handle exceptions inside these methods (e.g. getAllScores ). We could rather declare
that these methods may throw exceptions. Since we are not even trying to catch exceptions in getAllScores ,
the IOException will be propagated from the getAllScores to its caller - the method main . Now the main
method has to handle this exception.

9.5. The Keyword finally


Any code within a try/catch block can end in one of the following ways:

[Link] 173/303
22/03/2025, 18:48 Programação Java para crianças

The code inside the try block successfully ended and the program continues.

The code inside the try block runs into a return statement and the method is [Link] example, you
may read a file line by line, and if the line contains a certain text, you may want to stop reading the file. Just
write a return statement, and the method is exited, e.g.
JAVA
if ([Link]("Mary")){
return;
}

The code in the try block throws an exception and control goes to the matching catch block, which
either handles the error and the method execution continues, or it re-throws the exception to the caller of this
method.

If there is a piece of code that must be executed no matter what, put it under the keyword finally :

JAVA
try{
[Link]();
}catch(Exception e){
printStackTrace();
}finally{
// the code that must always be executed
// goes here, for example [Link]();
}

The code above has to close the file regardless of success or failure of the read operation. Usually, you can find
the code that releases some computer resources in the block finally , for example, disconnection from a
network or file closing.

If you are not planning to handle exceptions in the current method, they will be propagated to the caller. In this
case, you can use the finally even without a catch block:

JAVA
void myMethod() throws IOException{
try{
// your code that reads a file goes here
}
finally{
// your code that closes the file goes here
}
}

If the myMethod will throw an exception it will be handled in the calling method. But we still want to close the
file, and placing the code that closes a file into the finally section will guarantee that it will be done. So we
have the` finally` without the catch here.

[Link] 174/303
22/03/2025, 18:48 Programação Java para crianças

9.6. The Keyword throw


When you read in Java documentation that some methods may throw an exception, it means that the
programmer who wrote this method used a special throw keyword to do this. The throw keyword is used to
throw Java objects, which are throwable. You can only throw objects that are direct or indirect subclasses of the
class Throwable . We can guess, that the author of the method that reads a file used the throw keyword in the
method read . This could have been done as follows:

JAVA
throw new IOException(“The file [Link] contains invalid characters”);

The constructor of any exception should get a message that describes the error as an argument. When you’ll be
invoking the getMessage method on the exception object in the catch block, it’ll print the message that was
given to the constructor in the code that has thrown the exception.

Figure 78. Throwing exceptions

In the next section I’ll show you how create your own exception classes and throw them with the throw
keyword.

[Link] 175/303
22/03/2025, 18:48 Programação Java para crianças

9.7. Creating Custom Exceptions


Programmers could also create new exception classes that did not exist in Java before. Such classes have to
derive from one of the Java exception classes. Let’s say you are in business of selling bikes and need to validate
customer orders. Different number of bikes can fit in your small truck depending on the model. For example,
you can fit no more than three FireBird bikes in your truck. You can create a new subclass of Exception called
TooManyBikesException , and if someone tries to order more than three of these bikes, throw this exception:

JAVA
class TooManyBikesException extends Exception{

// Constructor
TooManyBikesException (){

super("Can't ship so many bikes.");


}
}

This class has only a constructor that takes the message describing this error and passes it to the superclass of
TooManyBikesException for reporting the same way as Java runtime reports any other exception. When
some catch block receives this exception it can extract the message describing what happened by calling the
method getMessage on the caught object TooManyBikesException .

Visualize a JavaFX GUI where the user selects several bicycles of some model and hits the button Place Order.
As you know from Chapter 8, this action will result in the call to the event handler method (e.g. placeOrder )
assigned to the onAction property of the button. The event handler can apply some business logic (e.g. call a

[Link] 176/303
22/03/2025, 18:48 Programação Java para crianças

method validateOrder ) to check if the order can be delivered.


The next code fragment shows how the method placeOrder invokes validateOrder , which can throw
TooManyBikesException .

JAVA
@FXML private ComboBox model;
@FXML private TextField quantity;

@FXML private Label txtFieldOrderConfirmation;

public void validateOrder(ActionEvent evt){

String selectedModel = [Link]()


.getSelectedItem();
String selectedQuantity =
[Link]();
int quantity = [Link](selectedQuantity);

try{
validateOrder(selectedModel, quantity);

//the next line will be skipped in case of exception


[Link](
"Your order is complete");

} catch(TooManyBikesException bikesException){
[Link](
[Link]());
}
}

void validateOrder(String bikeModel, int quantity)


throws TooManyBikesException{

/* Here should go the code to checks if the requested


quantity of bikes of selected model fits in the
truck. If they won't fit, do the following:
*/

throw new TooManyBikesException("Can not ship" +


quantity + " bikes of the model " + bikeModel + " in one shipment" );
}
}

If the order won’t fit in the truck, the method validateOrder throws the exception, the catch block in
placeOrder intercepts it and displays an error message in a text field on the window. When you throw custom
exceptions, provide a user-friendly message that clearly describes the error.

[Link] 177/303
22/03/2025, 18:48 Programação Java para crianças

Figure 79. Showing a user-friendly message

I’m not going to provide you with an explanation of how JavaFX ComboBox control works, because I want you
to do a little research as a part of the project assignment below.

In a perfect world, every program would work properly, but realistically you have to be ready for unexpected
situations. It helps that Java often forces you to write code that is prepared for these situations. You can also use
the Java exception handling mechanism to process situations specific to your application as illustrated using the
bike store example.

For more detailed coverage of exceptions read Oracle’s lesson on exceptions


([Link]

[Link] 178/303
22/03/2025, 18:48 Programação Java para crianças

9.8. Project: Create a JavaFX Bike Store


In this assignment I’d like you to create a JavaFX application for a bicycle store. It should have GUI that allows
the user to select a bicycle model (do a little research and learn on your own how to use the JavaFX ComboBox
for this). You can find the description ([Link] of the
ComboBox component in Oracle tutorial.

Use a TextField control for entering the quantity, a Button for placing an order, and a Label to display
either order confirmation or an error message.

In the controller class use the code fragment from the section "Creating Custom Exceptions". :toc-placement!:
:imagesdir: .

[Link] 179/303
22/03/2025, 18:48 Programação Java para crianças

10. Creating a Tic-Tac-Toe Game


In this chapter we’ll return to GUI programming and will develop a Tic-Tac-Toe game using JavaFX and Scene
Builder.

This game may go by different names around the world, but it comes down to placing X’s and O’s on the game
board. If you’re not familiar with this game, read its description in this Wikipedia article
([Link]

Every game implements a set of rules or a strategy that has to be applied depending on the player’s actions. Let’s
come up with a simple algorithm for the Tic-Tac-Toe game. Our version of this game will implement the
following rules:

The game will be played by two players on a 3x3 board.

Two players can play this game. One will play with the symbol X, and the other will use O.

The winner must have a full row, column, or diagonal of X’s or O’s.

After each move, the program has to check if there is a winner.

The winning combination of squares has to be displayed in different colors.

After the winner is found or there are no empty squares left, the players may select the menu Actions | Play
to play again.

In a new game the first player plays with X’s.

[Link] 180/303
22/03/2025, 18:48 Programação Java para crianças

The content of this chapter is based on the materials covered in Chapter 7 and 8. While developing the game
you’ll learn how to add menus, dynamically change styling of GUI components and apply an animation effect.

10.1. Developing the Game: Step by Step


In Chapter 7 we went through the procedure of creating a new IDEA project, and now you’ll need to do it again.
Create a new project selecting JavaFX as a project type. Press Next, and on the next popup window enter
TicTacToe as a project name. Press the button Finish and IDEA will generate a new project for you. Rename
(right-click | Refactor | Rename) the file [Link] into [Link] and [Link] into [Link].
Accordingly, the TicTacToe class should load the file [Link], and the window title should read Tic-
Tac-Toe :

[Link] 181/303
22/03/2025, 18:48 Programação Java para crianças

JAVA
public class TicTacToe extends Application {

@Override
public void start(Stage primaryStage) throws Exception{
Parent root = [Link](getClass().getResource("[Link]"));
[Link]("Tic-Tac-Toe");
[Link](new Scene(root, 300, 325));
[Link]();
}

public static void main(String[] args) {


launch(args);
}
}

Rename the generated package from sample into mygame. Inside the [Link] change the reference to
controller to be fx:controller="[Link]" . Now you’re ready to design the GUI for Tic-Tac-
Toe in Scene Builder.

10.1.1. Developing the GUI part in Scene Builder


Similarly to the examples from Chapter 7, we’ll separate the GUI design from implementation. So right-click on
the file [Link] and select the menu option Open in SceneBuilder. This is how the IDEA-generated file
[Link] looks like in Scene Builder:

Figure 80. Opening the generated [Link] in Scene Builder

[Link] 182/303
22/03/2025, 18:48 Programação Java para crianças

First of all, the <GridPane> is not a good candidate to serve as a root container for our game, which has to
have a menu on top. The <BorderPane> is a better choice when you need to have some GUI components to be
located on the top of the window. Our game will have a menu on top and a 3x3 grid of squares in the center of
the window.

Let’s delete the GridPane from the Hierarchy panel at the bottom left and drag-drop the BorderPane there.
The Scene Builder’s Window should look like this:

Figure 81. The BorderPane is a root container

JavaFX menus are created as a hierarchy of nested components. A Menu container can contain one or more
MenuItem components and other Menu components. You can also create a MenuBar or a ContextMenu that
includes one or more Menu components. I’ll show you how to create a menu bar with two menus Actions and
Help for our Tic-Tac-Toe game.

A menu bar is usually located at the top of a window. In Scene Builder drop the MenuBar component from the
Controls panel onto Insert TOP line in the BorderPane at the bottom left panel. Press a little plus sign to
expand the MenuBar in the Hierarchy panel. You’ll see that it’ll have the default menus named File, Edit and
Help.

[Link] 183/303
22/03/2025, 18:48 Programação Java para crianças

Figure 82. Dropped the MenuBar on Top of the BorderPane

We’re not going to edit anything in the TicTacToe game, so right-click on Edit and select Delete option. Rename
the menu File into Actions using the Properties panel of Scene [Link] Menu File was created with the
MenuItem Close - rename it into Quit.

Now we’ll add menu items to the menus Actions and Help. Drop a MenuItem component from the panel Menu
onto the menu Actions in the Hierarchy panel. Scene Builder will automatically create an Unspecified Action.
Rename it to Play. You can use drag and drop to change the order of the menu items.

Drop another MenuItem component onto the menu Help. Scene Builder by default creates two menu items:
About and Unspecified Action. Rename the latter to be How to Play. The Hierarchy panel should look as
follows:

[Link] 184/303
22/03/2025, 18:48 Programação Java para crianças

Figure 83. The menu bar with 2 menus and 4 menu items

Now drop a GridPane from the Containers panel onto the center of the BorderPane. By default, Scene Builder
creates a 2x3 grid. Right-click at the column tab "1" and add a column to change the grid dimensions to be 3x3.
Change the preferred height of each row to 100 by selecting each row and entering 100 in the Pref Height field
on the right panel named Layout: RowConstraints. This is what we’ve got so far:

[Link] 185/303
22/03/2025, 18:48 Programação Java para crianças

Figure 84. The menu bar on top and the grid in center

Save this layout in Scene Builder and run the TicTacToe class in IDEA. You’ll see a window with a menu on top.
The grid won’t be visible yet, because it has no content. Click on the menu Actions, and the window will look
like this:

[Link] 186/303
22/03/2025, 18:48 Programação Java para crianças

Figure 85. Running TicTacToe with an empty grid

The grid has 9 cells and we want to add 9 buttons - each button will represent a square on the Tic-Tac-Toe board.
You can add the buttons to the grid in Scene Builder as we did in the Calculator in Chapter 7. But it’ll be faster
to do it manually by editing the content of the file [Link] in IDEA’s editor. Modify the content of this file
to look as follows:

[Link] 187/303
22/03/2025, 18:48 Programação Java para crianças

XML
<?xml version="1.0" encoding="UTF-8"?>

<?import [Link].*?>
<?import [Link].*?>
<?import [Link].*?>
<?import [Link]?>

<BorderPane xmlns="[Link]
xmlns:fx="[Link]
fx:controller="[Link]">
<top>
<MenuBar [Link]="CENTER">
<menus>
<Menu text="Actions">
<items>
<MenuItem text="Play" />
<MenuItem text="Quit" />
</items>
</Menu>
<Menu text="Help">
<items>
<MenuItem text="About" />
<MenuItem text="How to play" />
</items>
</Menu>
</menus>
</MenuBar>
</top>
<center>
<GridPane fx:id ="gameBoard" [Link]="CENTER">
<children>
<Button fx:id="b1" prefHeight="100.0" prefWidth="100.0" />
<Button fx:id="b2" prefHeight="100.0" prefWidth="100.0" [Link]="1" />
<Button fx:id="b3" prefHeight="100.0" prefWidth="100.0" [Link]="2" />
<Button fx:id="b4" prefHeight="100.0" prefWidth="100.0" [Link]="1" />
<Button fx:id="b5" prefHeight="100.0" prefWidth="100.0" [Link]="1"
[Link]="1" />
<Button fx:id="b6" prefHeight="100.0" prefWidth="100.0" [Link]="2"
[Link]="1" />
<Button fx:id="b7" prefHeight="100.0" prefWidth="100.0" [Link]="2" />
<Button fx:id="b8" prefHeight="100.0" prefWidth="100.0" [Link]="1"
[Link]="2" />
<Button fx:id="b9" prefHeight="100.0" prefWidth="100.0" [Link]="2"
[Link]="2" />
</children>
</GridPane>
</center>
</BorderPane>

Note that each button has an id. We’ll need them while processing button clicks in the controller class. Run the
TicTacToe class and the window will look pretty close to the final version of our Tic-Tac-Toe game.

[Link] 188/303
22/03/2025, 18:48 Programação Java para crianças

Figure 86. Running TicTacToe - the first square has a focus

Do yo see this thin border around the top left square? It occurs because by default the firs grid cell has a focus,
which means that this particular GUI component is ready to receive input. But we don’t want to suggest the
player starting the game from the top left corner, do we? We want to remove this little border, and it’s time to
create a special style for a button that will not show the focus.

Let’s create a new file named [Link]. In IDEA, right click on the package name mygame and use the menu
File | New | File. It’ll create an empty file. Type the following in there:

CSS
.button{
-fx-focus-color: transparent;
-fx-background-insets: -1, 0, 1, 1;
}

From Chapter 7 you may remember that this means that every button in our application will have these
attributes. Web designers call the styles created for certain types of GUI element type selectors. Hence the
attributes defined in the .button section of CSS will apply only for buttons. If we wanted to style menus, we’d
need to add a section .menu to the CSS file. Labels would be styled in the .label section, and so on.

[Link] 189/303
22/03/2025, 18:48 Programação Java para crianças

When I did my search on line to figure out how to remove the focus border, the online documentation suggested
that adding the rule -fx-focus-color: transparent; would do the trick. But it didn’t. Every programmer
knows, that not everything works by the book. By doing a little more online research I figured out that adding -
fx-background-insets: -1, 0, 1, 1; is needed too.

Don’t be scared that not everything works as it should the first time around. Luckily, each programming
language has an online community of people who are willing to share their findings and answer the questions of
the rookies. One of the best resources for asking questions and getting help is the Web site StackOverflow
([Link]

Now we need to add a line to the main method of the TicTacToe class to load the file [Link] . We
did something like this in Chapter 7 while styling the Sign In application. We’ll also need to do small changes in
the main method to store the reference to a scene in a separate variable. We also want to set fix the size of the
game board by invoking setResizable(false); on the stage object. After these modifications, the class
TicTacToe will look like this:

JAVA
public class TicTacToe extends Application {

@Override
public void start(Stage primaryStage) throws Exception{
Parent root = [Link](getClass()
.getResource("[Link]"));
[Link]("TicTacToe");
Scene scene = new Scene(root, 300, 275);
[Link]().add(getClass()
.getResource("[Link]").toExternalForm());
[Link](false);
[Link](scene);
[Link]();
}

public static void main(String[] args) {


launch(args);
}
}

Run the TicTacToe class now and the focus is gone:

[Link] 190/303
22/03/2025, 18:48 Programação Java para crianças

Figure 87. Running TicTacToe - the first square has no focus

The GUI is ready. The name of the Java class that will play the role of the controller was specified in the file
[Link] as fx:controller="[Link]" . Now let’s program the application logic in the
controller class.

10.1.2. Handling Button Clicks in Controller


There are different ways of programming computer games. In some games you play against another player, in
others - against the computer. Our version of TicTac-Toe will have two players. The first one will place X’s on
the blank buttons and the other one will place O’s. Hence we need to keep track of the player’s number.

When the player will click on the button, the event handler should place the appropriate label on the button. The
code of the class Controller will take care of this functionality:

[Link] 191/303
22/03/2025, 18:48 Programação Java para crianças

JAVA
public class Controller {
private boolean isFirstPlayer = true;

public void buttonClickHandler(ActionEvent evt){

Button clickedButton = (Button) [Link]();


String buttonLabel = [Link]();

if ("".equals(buttonLabel) && isFirstPlayer){


[Link]("X");
isFirstPlayer = false;
} else if("".equals(buttonLabel) && !isFirstPlayer){
[Link]("O");
isFirstPlayer = true;
}
}
}

The method buttonClickHandler will handle events generated when the player clicks on a button. Note that
we check if the button’s label is blank, then the program displays either X or O depending on which player
clicked on the button. To let the GUI know about this event handler we need to add the attribute
onAction="#buttonClickHandler" to each <Button> tag in the file [Link]. After this is done, run
the TicTacToe program again. Start clicking on empty squares, and the program will take turns in placing the
X’s and O’s on them.

[Link] 192/303
22/03/2025, 18:48 Programação Java para crianças

Figure 88. Running TicTacToe - after 3 clicks

Great,the View communicates with the Controller! But the X’s and O’s look unproportionally small in these
large squares. Besides, the gray color does not look too exciting. It’s time to add some styling to our GUI
components.

10.1.3. Styling Buttons and the Menu Bar


Let’s add more style attributes to the .button and add a new type selector for the .menu-bar to the file
[Link]. You can find the color names and their codes in the JavaFX CSS Reference Guide
([Link] This is what I came up with:

[Link] 193/303
22/03/2025, 18:48 Programação Java para crianças

CSS
.button{
-fx-focus-color: transparent;
-fx-background-insets: -1, 0, 1, 1;

-fx-font-weight: bold;
-fx-font-size: 36;
-fx-text-fill: blue;
-fx-background-color: violet;
-fx-border-color:darkblue;
}

.menu-bar{
-fx-background-color: gold;
}

If you run the TicTacToe program now and start clicking on buttons, the game board will look like this:

Figure 89. Adding colors to the game board

[Link] 194/303
22/03/2025, 18:48 Programação Java para crianças

As you can see, my artistic abilities are limited, but if you spend some time learning CSS, you may come up
with a much fancier game board than mine.

All JavaFX components are pre-styled, and the combination of the styles is called theme. The default theme of
all JavaFX components is called caspian. By defining your own CSS rules you can override the defaults. Scene
Builder has a menu View | Show CSS analyzer, which allows you to see the default styles of your GUI
components. If you’re interesting in learning more about styling with Scene Builder, watch the video titled "In-
Depth Layout and Styling with the JavaFX Scene Builder" ([Link]

10.1.4. Implementing the Game Strategy


In the beginning of this chapter I’ve described the game strategy. We’ll implement it in the Controller class.
For each button click we need to check if there is already a winning combination of X’s or O’s. If there is, the
program should highlight the winning combination. In case of a draw, the player may select the menu option
Play to start playing again.

We’ll write a method find3InARow , which on every click will check each row, column, and diagonals on the
board to see if they have the same labels. The method find3InARow will be invoked from the method
buttonClickHandler . If the winning combination is found, the program will invoke the method
highlightWinningCombo to show the winning combination in a different style.

To compare the labels of the buttons we need to have references to their Button objects, which we’ll get using
the injection mechanism offered by the @FXML annotation as we did in Chapter 8. We’ll also need to have a
reference to the GridPane , which is a container for all buttons. You’ll see its use in the section "Handling the
Tic-Tac-Toe Menu Play".

Each button will have a matching variable in the controller annotated with @FXML . The grid will also have a
reference variable. We’ll just add the following member variables to the Controller class:

JAVA
@FXML Button b1;
@FXML Button b2;
@FXML Button b3;
@FXML Button b4;
@FXML Button b5;
@FXML Button b6;
@FXML Button b7;
@FXML Button b8;
@FXML Button b9;

@FXML GridPane gameBoard;

Now let’s write the method find3InARow that will methodically compare the non-blank labels of the buttons in
each row, column, and both diagonals. If three labels are the same, the code should highlight the winning
combination. This is how the code in the method find3InARow will look:

[Link] 195/303
22/03/2025, 18:48 Programação Java para crianças

JAVA
private boolean find3InARow(){
//Row 1
if (""!=[Link]() && [Link]() == [Link]()
&& [Link]() == [Link]()){
highlightWinningCombo(b1,b2,b3);
return true;
}
//Row 2
if (""!=[Link]() && [Link]() == [Link]()
&& [Link]() == [Link]()){
highlightWinningCombo(b4,b5,b6);
return true;
}
//Row 3
if (""!=[Link]() && [Link]() == [Link]()
&& [Link]() == [Link]()){
highlightWinningCombo(b7,b8,b9);
return true;
}
//Column 1
if (""!=[Link]() && [Link]() == [Link]()
&& [Link]() == [Link]()){
highlightWinningCombo(b1,b4,b7);
return true;
}
//Column 2
if (""!=[Link]() && [Link]() == [Link]()
&& [Link]() == [Link]()){
highlightWinningCombo(b2,b5,b8);
return true;
}
//Column 3
if (""!=[Link]() && [Link]() == [Link]()
&& [Link]() == [Link]()){
highlightWinningCombo(b3,b6,b9);
return true;
}
//Diagonal 1
if (""!=[Link]() && [Link]() == [Link]()
&& [Link]() == [Link]()){
highlightWinningCombo(b1,b5,b9);
return true;
}
//Diagonal 2
if (""!=[Link]() && [Link]() == [Link]()
&& [Link]() == [Link]()){
highlightWinningCombo(b3,b5,b7);
return true;
}
return false;
}

[Link] 196/303
22/03/2025, 18:48 Programação Java para crianças

If you’ll check the fx:id of each button in the file [Link], you’ll see that the first row is represented by
the buttons b1 , b2 , and b3 . The first column is represented by the buttons b1 , b4 , and b7 . One diagonal
consists of the buttons b1 , b5 , and b9 . It should be pretty easy to read and understand the code of the method
find3InARow , isn’t it? The method highlightWinningCombo will get the references to the three winning
buttons as the method arguments, and it has to change their styles.

10.1.5. Highlighting the Winning Combination


The styles of the winning buttons should be changed dynamically (during the runtime). First of all, we need to
come up with the style for displaying the winning button and add it to the CSS file. Then the class Controller
will invoke the method setStyle on them providing the name of the winning style.

I want to change the background of the winning buttons, but this time I won’t use just a single color, but a color
gradient. In computer graphics, color gradients refer to filling the area with different colors that are smoothly
transitioning from one color to another. The color transitioning can be linear or radial, and this Wikipedia article
([Link] gives you some examples of both.

We’ll use radial gradients in our game. With gradients you can use more than two colors. I’ll use three colors in
the gradient for the winning squares. The background color will transition from white to light yellow, and then to
lawn green. I’ll use red for the text of the label on the winning square.

To dynamically change the style of a GUI component you can call the method setStyle and specify the color
as an argument, for example:

[Link]("-fx-text-fill: red;");

But embedding CSS rules in your Java program is not a good idea. What if you decide to change the styling (e.g.
to change the color from red to pink)? You don’t want to search for all the places in your Java code where this
style was used. Besides, changing the styles in the code would require to recompile your Java program. It’s much
better to keep the style definitions in the CSS file.

So far we’ve been using CSS type selectors that can change the style of the specified component types. But CSS
allows you to define and name a style that’s not intended for a specific component type and can be applied by
name to various components. In CSS such styles are called class selectors. Let’s add a style selector called
.winning-square to the file [Link] .

CSS
.winning-square {
-fx-text-fill: red;
-fx-background-color: radial-gradient( radius 100%, white, lightyellow, lawngreen);
}

[Link] 197/303
22/03/2025, 18:48 Programação Java para crianças

The style selector .winning-square includes two style rules: one for setting the button’s text color to red, and
another to set the button’s background color to radial gradient. Our Java program has to get a reference to the
existing styles of the button and add a .winning-square , which will override both the text and the
background color of the [Link] method highlightWinningCombo will look like this:

JAVA
private void highlightWinningCombo(Button first, Button second, Button third){
[Link]().add("winning-square");
[Link]().add("winning-square");
[Link]().add("winning-square");
}

Try playing the game after adding the methods find3InARow and highlightWinningCombo to the class
Controller . The winning combination will look as follows:

Figure 90. We’ve got the winner!

[Link] 198/303
22/03/2025, 18:48 Programação Java para crianças

JavaFX includes various visual effects ([Link] and


transition based animations ([Link] that can make your GUI
more fun to use.

To use the effect or animation you need to pick one from the package [Link] or
[Link] respectively. I’ll show you how to apply a fade transition the FadeTransition to our
winning buttons. Each winning button will keep fading and coming back to its original state. We’ll add the
method applyFadeTransition to the Controller class:

JAVA
private void applyFadeTransition(Button winningButton) {

FadeTransition ft = new FadeTransition([Link](1000), winningButton);

[Link](1.0);
[Link](0.1);
[Link](10);
[Link](true);
[Link]();
}

This code creates an instance of the animation class FadeTransition that will span 1000 milliseconds (1
second) and assigns this animation to the winning button. Then the code sets the fading parameters to change the
opacity of the button from 1.0 to 0.1 (changing to 0.0 would make the button completely transparent).

Setting the style count to 10 plays the animation 10 times. Because of setAutoReverse(true) , the animation
will proceed forward on the first cycle, then reverses on the second cycle, and so on. The method play starts
the animation. Adding the following three lines to the method highlightWinningCombo will play the
animation on the winningButton component.

JAVA
applyFadeTransition(first);
applyFadeTransition(second);
applyFadeTransition(third);

The screen shot shown on Figure 10-12 should give you an idea of how the end of the animation cycle will look
like.

[Link] 199/303
22/03/2025, 18:48 Programação Java para crianças

Figure 91. Faded winning buttons

Compare this image with Figure 10-11, or better run the code that comes with the book to see the animation in
action.

10.1.6. Handling the Tic-Tac-Toe Menu Play


The winner is found, but how to start a new game? Our gane has a menu Actions with the menu item Play. Now
we need to make it working so the players can start a new game when either a winning combination is found or
it’s a draw.

[Link] 200/303
22/03/2025, 18:48 Programação Java para crianças

The good news is that clicks on menu items are processes the same way as clicks on buttons. In the file
[Link] we’ll assign onAction event handler for the menu Play:

HTML
<MenuItem text="Play" onAction="#menuClickHandler"/>

When the user clicks on the menu Play, the controller needs to reset buttons' labels to blank and remove styling
from the winning buttons. We’ll do this by getting a hold of all children of our GridPane and invoking the
method forEach passing a short lambda expression to it. This is what the method menuClickHandler will
look like:

JAVA
public void menuClickHandler(ActionEvent evt){

MenuItem clickedMenu = (MenuItem) [Link]();


String menuLabel = [Link]();

if ("Play".equals(menuLabel)){ (1)
ObservableList<Node> buttons = (2)
[Link]();

[Link](btn -> {
((Button) btn).setText(""); (3)

[Link]().remove("winning-square"); (4)
});

isFirstPlayer = true; (5)


}
}

1. This code processes just the clicks on the menu Play, but I included the if statement to check the menu label
in case you decided to implement other menus too.

2. We’re getting references to all children of the grid (the buttons) in one shot. The method getChildren
returns a JavaFX collection of type ObservableList located in the package [Link] .

3. Each Java collection implements the method forEach , which gets a lambda expression to set the label of
each button to an empty string.

4. Then we’re getting the reference to the styles of the button and remove the style winning-square if
exists.

5. Finally, the code sets the variable isFirstPlayer to true so the next game will place an X as the first
label.

Enjoy our Tic-Tac-Toe game!

[Link] 201/303
22/03/2025, 18:48 Programação Java para crianças

10.2. Project: Playing Against Computer


Our version of the game is created for two players. In this assignment you’ll need to change the program so the
player can play against the computer. The player will keep playing with X’s, and the computer with O’s.

Write a method goComputer that should try to find if there are any two buttons with O’s in each row, column
or a diagonal. If found, the program should place a O to the winning position. If not found, the computer should
place a O next to another O. If no O’s are found, the computer should try to place an O in the middle of the
board. If the middle square is occupied, place a O on the first blank button.

The method goComputer should be called from the method buttonClickHandler right after the line that
invokes the method find3InARow .

10.2.1. Challenge Yourself


Play an audio when the winning combination is found. To do this learn how to use the JavaFX class
AudioClip located in the package [Link] . :toc-placement!: :imagesdir: .

[Link] 202/303
22/03/2025, 18:48 Programação Java para crianças

11. Working With Files and Serialization


After a program ends, it gets erased from the memory. When you run it again, its content is loaded into the
memory and all Java objects are created from scratch. If you’d like to save some results of the program
execution, they must be stored in files on a hard disk, a solid-state drive, a memory stick, or any other device that
can store the data for a long time.

In this chapter you’ll learn how to save data on disks and read them back into memory using Java
Input/Output(I/O) streams.A program can open an output stream with a file on disk and write the important data
there. Similarly, you can open an input stream and read the data from a file.

For example, if a player wins a game and you want to save the score, you can save it in a file called [Link]
using an output stream. If you want to save the player’s preferences (e.g. colors or fonts) you can save them in a
file, and read and apply them when the user runs your program again.

A program reads or writes data from/to a stream serially byte after byte, character after character, etc. Since your
program may use different data types like String , int , double , you should use an appropriate Java stream,
for example a byte stream, a character stream, or a data stream.

In this chapter I’ll show you how to use I/O streams with files located in your computer. In the next chapter
you’ll learn about I/O streams that can work with remote data located in other computers connected into a
network.

All classes that can work with file streams are located in packages [Link] and [Link] . Classes from the
[Link] implement blocking I/O: When bytes are being read/written, they become unavailable for other
threads of execution. This may not be an issue with small files like a history of game scores, but may become an
issue with large files that contain a gigabyte or more. The package [Link] offers a set of classes with
improved performance as well as some useful utility classes.

I’ll start with explaining the basics of working with streams of bytes using classes from the [Link] package,
and then give you some examples of working with classes from [Link] .

11.1. Basics of Working With Streams


Think of a stream as a pipe. If you just need to read the data from some source, imagine that the data flows
through a pipe into your program. If you need to write the data into storage, it’s another pipe where the data flow
from your program to this storage. As with any pipe, it has to be opened to start the flow and closed to stop it.

Java supports several types of streams, but no matter what type you are going to use, the following three steps
should be done in your program:

[Link] 203/303
22/03/2025, 18:48 Programação Java para crianças

• Open a stream that points at some data store e.g. a local or remote file.

• Read or write data from/to this stream.

• Close the stream (Java can do it automatically).

In the real world people use different types of pipes for carrying different content (e.g. gas, oil, milkshakes).
Similarly, Java programmers use different classes depending on the type of data they need to carry over a stream.
Some streams are used for carrying text, some for bytes, et al.

11.1.1. Byte Streams


To create a program that reads a file, interprets and displays its content on the screen, you need to know what
type of data is stored in this file. On the other hand, a program that just copies files from one place to another
does not even need to know if this file represents an image, a text, or a file with music. Such a copy program
reads the original file into computer’s memory as a set of bytes, and then writes them into another file located in
the destination folder.

The [Link] package includes the classes FileInputStream and FileOutputStream that allow you to
read and write files one byte at a time. If your program has to work only with text files, you could use the classes
Reader and Writer , which are specifically meant for reading character streams.

After selecting, say FileInputStream you’d be invoking one of its methods to read the file data. For example
the online documentation ([Link] of the class
FileInputStream includes the method read having the following signature:

JAVA
public int read() throws IOException

This should tell you that the method read returns an integer value and may throw the IOException , which is
an error that may happen if the file is corrupted or deleted, a device failure happened et al. Hence, you must
enclose the invocation of the method read into a try-catch block as explained in Chapter 9. To get a specific
reason for this exception you’ll call the method getMessage on the exception object.

Each byte in a file is represented by a code, which is a positive integer number. The method read returns the
value of this code.

The next example shows how to use the class FileInputStream to read the bytes from a file named [Link].
This little program won’t interpret the meaning of each byte - it’ll just print their code values.

I’ll start with creating a new Java project Chapter11 in IDEA. Then I’ll create a new empty file [Link] in the
root folder of the project (right-click on the project name and select the menu New | File). Finally, I’ll type the
following text in [Link]:

[Link] 204/303
22/03/2025, 18:48 Programação Java para crianças

This is a test file

Then I’ll create a new Java class MyByteReader that will read and print the content of the file [Link]. But let’s
pretend that we don’t know that the content of this file is text - I want to read it byte by byte and print each byte’s
code (not a letter) separated by a space character. The class MyByteReader will look like this:

JAVA
import [Link];
import [Link];

public class MyByteReader {

public static void main(String[] args) {

try (FileInputStream myFile = (1)


new FileInputStream("[Link]")){

int byteValue;

while ((byteValue = [Link]()) != -1) { (2)

[Link](byteValue + " "); (3)


}
} catch (IOException ioe) { (4)
[Link]("Could not read file: " +
[Link]());
}
}
}

1. First we open the file for reading (using a default character set) by creating an instance of the class
FileInputStream passing the file name [Link] as a parameter. In Chapter 9 you’ve learned the
syntax of the try-catch blocks, but here I used a special syntax called try-with-resources. When there are
some program resources that have to be opened and closed (e.g. FileInputStream ), just instantiate them
in parentheses right after the try keyword and Java will close them for you automatically. This spares you
from writing a finally block containing the code for closing resources.

2. This line starts a while loop that calls the method read() , which reads one byte, assigns its value to the
variable byteCode , and compares it with -1 (the end of file indicator).

3. If the value in the current byte is not equal to -1 , we print it followed by a space character. The loop ends
when it reads the -1 byte.

4. If an IOException occurs, catch it and print the reason for this error.

Running this program prints the following numbers that represent encoding of the text "This is a test file":

JAVA
84 104 105 115 32 105 115 32 97 32 116 101 115 116 32 102 105 108 101

[Link] 205/303
22/03/2025, 18:48 Programação Java para crianças

Writing bytes into a file works similarly, but you’d use the class FileOutputStream and its method write()
as shown in the program MyByteWriter below.

JAVA
import [Link];
import [Link];

public class MyByteWriter {

public static void main(String[] args) {

// Some byte values represented by integer codes


int someData[]= {56,230,123,43,11,37}; (1)

try (FileOutputStream myFile = new FileOutputStream("[Link]")){ (2)

int arrayLength = [Link];

for (int i = 0; i < arrayLength; i++){


[Link](someData[i]); (3)
}
} catch (IOException ioe) {
[Link]("Could not write into the file: " + [Link]()); (4)
}
}
}

1. The program MyByteWriter populates an array someData with integer codes that may represent some
characters

2. Then the program opens the file [Link].

3. Then it proceeds to writes each of the integers into the file.

4. If an error occurs, we catch it and print the reason.

11.1.2. Bufferred Streams


The code examples in the Byte Streams section were reading or writing into a file one byte at a time. One
invocation of read would read one byte, and one invocation of write would write one byte. In general, disk
access is much slower than the processing performed in memory; that’s why it’s not a good idea to access the
disk a thousand times to read a file of 1,000 bytes. To minimize the number of times the disk is accessed, Java
provides buffers, which serve as reservoirs of data.

[Link] 206/303
22/03/2025, 18:48 Programação Java para crianças

The class BufferedInputStream works as a middleman between FileInputStream and the file itself. It
reads a big chunk of bytes from a file into memory (a buffer) in one shot, and the FileInputStream object
then reads single bytes from there, which are fast memory-to-memory operations. BufferedOutputStream
works similarly with the class FileOutputStream .

The main idea here is to minimize disk access. Buffered streams are not changing the type of the original streams
— they just make reading more efficient. A program performs stream chaining (or stream piping) to connect
streams, just as pipes are connected in plumbing.

A próxima listagem de código mostra uma classe MyBufferedByteReader , que é uma versão ligeiramente
modificada de MyByteReader . Acabei de anexar "outro fragmento ao pipe" - o BufferedInputStream do
[Link] pacote.

[Link] 207/303
22/03/2025, 18:48 Programação Java para crianças

JAVA
import [Link];
import [Link];
import [Link];

public class MyBufferedByteReader {

public static void main(String[] args) {

try (FileInputStream myFile = new


FileInputStream("[Link]"); (1)
BufferedInputStream buff = new
BufferedInputStream(myFile);){

int byteValue;

while ((byteValue = [Link]()) != -1) { (2)

[Link](byteValue + " ");


}
} catch (IOException e) {
[Link]();
}
}
}

1. Aqui usamos a sintaxe try-with-resources novamente. Desta vez, criamos uma instância de
FileInputReader e então e instância de BufferedInputReader fornecendo o
FileInputReader como argumento. É assim que nos conectamos a fragmentos do pipe que usa o arquivo
[Link] como fonte de dados.

2. Por baixo do capô, BufferedInputReader o método lê bytes do disco em blocos em um buffer de


memória e, então, read lê um byte de cada vez da memória.

O programa MyBufferedByteReader produz a mesma saída que MyByteReader , mas funcionará um pouco
mais rápido.

11.2. Fluxos de Personagens


Texto em Java é representado como um conjunto de char valores, que são codificados com base nos conjuntos
de caracteres capazes de representar o alfabeto ou outros símbolos usados ​em uma linguagem humana
específica. Como você pode imaginar, o texto em inglês, ucraniano e japonês deve usar codificações de
caracteres diferentes. Os nomes de alguns dos conjuntos de caracteres padrão para pessoas que falam inglês são
US-ASCII, UTF-8 e UTF-16.

Cada JVM tem um conjunto de caracteres padrão, que pode ser alterado durante a inicialização da JVM. Você
também pode descobrir qual é o caractere padrão na sua instalação Java invocando o método
defaultCharset na classe Charset , e eu mostrarei como fazer isso na seção "Lendo Arquivos de Texto".

[Link] 208/303
22/03/2025, 18:48 Programação Java para crianças

As classes Java FileReader e FileWriter o pacote [Link] foram criados especificamente para trabalhar
com arquivos de texto, mas funcionam apenas com codificação de caracteres padrão e não lidam com a
localização corretamente.

Para eficiência, a leitura pode ser canalizada com BufferedReader ou BufferedWriter , que lê ou escreve
de/para os caracteres de buffering de fluxo. Mostrarei exemplos de trabalho com arquivos de texto na próxima
seção.

11.3. Trabalhando com arquivos usando [Link]


O [Link] pacote contém classes que oferecem uma maneira simplificada e mais eficiente de trabalhar com
arquivos, e você verá alguns exemplos úteis aqui. Mas primeiro eu gostaria de apresentar as classes Path e
Paths isso representará um arquivo com o qual você está planejando trabalhar.

11.3.1. Usando classes Path e Paths


Até agora, trabalhamos com arquivos localizados no diretório raiz do nosso projeto IDEA. Mas os arquivos são
agrupados em diretórios (pastas), que por sua vez podem incluir diretórios e arquivos aninhados. Além disso, os
arquivos são representados de forma diferente nos sistemas operacionais Windows, Mac OS e Linux. Por
exemplo, no Windows, o caminho de pull para um arquivo pode ser parecido com este:
c:\mystuff\games\[Link]

No Mac OS ou Linux, os discos não são nomeados com letras como c: ou d: . Por exemplo, o caminho para os
arquivos do usuário começa no diretório Users . Além disso, uma barra invertida não é usada como símbolo
separador lá. Um caminho completo para um arquivo [Link] do usuário mary pode ser parecido com
este:

/Users/mary/mystuff/games/[Link]

Então, antes mesmo de abrir um arquivo, você pode criar uma instância do objeto Path , que não abre nem lê
um arquivo, mas representa a localização do arquivo no disco.

Há uma classe especial Paths (sim, no plural) que inclui uma série de métodos estáticos e, em particular, pode
construir o Path objeto para você. Por exemplo, você pode invocar o método get passando o nome do arquivo
como argumento:

JAVA
Path path = [Link]("[Link]");

Como especificamos apenas o nome do arquivo sem um diretório, o programa procurará o arquivo no diretório
atual, que no IDEA é o diretório do seu projeto (por exemplo, Chapter11 ). Fora do IDE, o diretório atual é
aquele de onde o programa foi iniciado.

[Link] 209/303
22/03/2025, 18:48 Programação Java para crianças

Mas se criássemos um diretório data na raiz do nosso projeto e movêssemos o arquivo [Link] para lá, então o
caminho relativo para o arquivo começando da raiz do projeto ficaria como "data/[Link]" no Mac OS ou
"data\\[Link]" no Windows. Duas barras invertidas em uma string Java correspondem a uma barra
invertida no sistema operacional Windows.

Mas seu projeto IDEA também está localizado em algum diretório no disco, por exemplo, chapter11 , que é um
subdiretório de PracticalJava . O arquivo pode ser representado pelo caminho absoluto , que pode se parecer
com isto:

c:\practicalJava\capítulo11\dados\[Link]

ou

/Users/mary/practicalJava/chapter11/data/[Link]

11.3.2. Usando os arquivos de classe


A classe Files tem vários métodos que ajudarão você com manipulações de arquivos. Ela pode criar, excluir,
renomear e copiar arquivos. Há métodos para ler e escrever arquivos também.

11.3.3. Lendo um arquivo


A maneira mais simples de ler um arquivo é chamando o método readAllBytes na classe Files . A linha a
seguir lê o arquivo [Link] em um array de bytes:

JAVA
byte[] myFileBytes = [Link]([Link]("[Link]");

Se o arquivo contiver texto, você pode ler o arquivo em uma String variável como esta:

JAVA
String myFileText = new String([Link]([Link]("[Link]")));

Se você quiser ler um arquivo de texto em uma coleção, onde cada elemento contém uma linha do arquivo, use o
método readAllLines .

JAVA
List<String> myFileLines = [Link]([Link]("[Link]"));

Both readAllBytes and readAllLines do not use buffers, but for small files is not important. For more
efficient reading you can ask the class Files to create a buffered stream. For example, the program
MyTextFileReader uses the method newBufferedReader for more efficient reading. Here I used the same
file [Link] located in the root directory of our IDEA project Chapter11.

[Link] 210/303
22/03/2025, 18:48 Programação Java para crianças

JAVA
package niosamples;

import [Link];
import [Link];
import [Link];
import [Link];
import [Link];
import [Link];
import [Link];

public class MyTextFileReader {

public static void main(String[] args){

Path path = [Link]("[Link]"); (1)


[Link]("The absolute path is " +
[Link]());

try {
if ( [Link](path)){ (2)
[Link]("The file size is " + [Link](path));
}

BufferedReader bufferedReader= (3)


[Link](path, StandardCharsets.UTF_8);

String currentLine;

while ((currentLine = (4)


[Link]()) != null){

[Link](currentLine);

}
} catch (IOException ioe) {
[Link]("Can't read file: " +
[Link]());
}

[Link]( (5)
"Your default character encoding is " + [Link]());
}
}

1. The program starts with creating a Path object from [Link] and printing its absolute path.

2. Then it checks if the file represented by the path exists and prints its size in bytes.

3. Here we’re opening the buffered reader capable of reading text encoded with a character set UTF-8 .

4. Reading the text lines from the buffer.

5. Print the default character set being used for those who are interested.

[Link] 211/303
22/03/2025, 18:48 Programação Java para crianças

When I ran the program MyTextFileReader it printed the following:

JAVA
The absolute path is /Users/yfain11/IdeaProjects/jfk/Chapter11/[Link]
The file size is 19
This is a test file
Your default character encoding is UTF-8

Now experiment to see if the IOException is thrown if the file is not found where it is expected to be. Just
move the file [Link] into a different directory and re-run MyTextFileReader . Now the console output looks
different:

JAVA
Can't read file: [Link]
Your default character encoding is UTF-8

This output was produced by the catch section from MyTextFileReader where the code invoked the
getMessage method on the IOException object.

11.3.4. Writing Into a File


Writing into a file is as reading one. Start with creating create an instance of the Path object. If you want to
write bytes, create a byte array, populate it with data and call the method write on the class Files . If you
want to write some text into a file, just convert the text from a String into a byte array and then call the
method write , for example:

JAVA
Path path = [Link]("data/[Link]");

[Link](path, [Link](),
[Link]);

When your program opens a file for writing, you need to consider different options. For example, you may want
to append text to an existing file, hence the above code snippet passes the argument
[Link] to method write . If you want to create a file from scratch every time you
run the program, use the option [Link] .

The following program MyTextFileWriter writes the text into a file [Link] in the directory data .

[Link] 212/303
22/03/2025, 18:48 Programação Java para crianças

JAVA
package niosamples;

import [Link];
import [Link];
import [Link];
import [Link];
import [Link];
import [Link];

public class MyTextFileWriter {

public static void main(String[] args){

[Link]("The current directory is "+


[Link]("[Link]")); (1)

String myScore = (2)


"My game score is 28000 " +
[Link]() + "\n";

Path path = [Link]("data/[Link]"); (3)

try {

if ( [Link](path)){ (4)
[Link](path, [Link](),
[Link]);
} else {
[Link](path, [Link](),
[Link]);
}

[Link]("The game score was saved at " + [Link]());


} catch (IOException ioe) {
[Link]("Can't write file: "
+ [Link]());
}
}
}

1. For illustration purposes I want the program to print its current directory, which is stored in a special Java
variable [Link] .

2. Then I populate a string with the content "My game score is 28000" and concatenate the current date and
time followed by \n , which is the end of line marker.

3. Creating a Path object pointing at the file [Link] .

4. Check if the file [Link] already exists, append the new content to it. If the file doesn’t exists – create it
and write the content there.

The program MyTextFileWriter printed the following on my console:

[Link] 213/303
22/03/2025, 18:48 Programação Java para crianças

JAVA
The current directory is /Users/yfain11/IdeaProjects/jfk/Chapter11
The game score was saved at /Users/yfain11/IdeaProjects/jfk/Chapter11/data/[Link]

After running MyTextFileWriter twice I opened the file [Link]. Here’s what I found there:

JAVA
My game score is 28000 2015-01-11T09:07:49.352
My game score is 28000 2015-01-11T09:10:11.049

Cada vez que o programa salvava a mesma pontuação de 28000 anexando a data e hora do sistema. Claro, você
poderia calcular e escrever a pontuação real de um jogo. Esta é uma maneira simples de imprimir a data e hora
locais. A parte da hora vai depois da letra "T" e mostra horas, minutos, segundos e nanossegundos. No pacote
Java, [Link] você pode encontrar várias classes e métodos que fornecem formatação de data e hora para
impressão bonita. Leia o tutorial da Oracle sobre como trabalhar com a API de data e hora
([Link] se estiver interessado.

Para escrever arquivos pequenos como [Link] você não precisa usar fluxos bufferizados. Para arquivos
grandes, porém, use BufferedWriter, por exemplo:

JAVA
String myScore = "My game score is 28000 " +
[Link]() + "\n";
BufferedWrited writer = [Link](path, [Link]);

[Link](myScore)

A aula MyTextFileBufferedFileWriter mostra como escrever a pontuação do jogo usando


BufferedWriter .

[Link] 214/303
22/03/2025, 18:48 Programação Java para crianças

JAVA
package niosamples;

import [Link];
import [Link];
import [Link];
import [Link];
import [Link];
import [Link];
import [Link];
import [Link];

public class MyTextFileBufferedFileWriter {

public static void main(String[] args) {

String myScore = "My game score is 28000 " + [Link]() + "\n";

Path path = [Link]("data/[Link]");

try (BufferedWriter writer =


getBufferedWriter(path)) {

[Link](myScore);

[Link]("The game score was saved at " + [Link]());


} catch (IOException ioe) {
[Link]("Can't write file: " +
[Link]());
}
}

// The factory of BufferedWriter objects


private static BufferedWriter getBufferedWriter(Path path) throws IOException{

if ([Link](path)) {
return [Link](path,
[Link]);
} else {
return [Link](path,
[Link]);
}
}
}

Nesta classe, movi o código que verifica se o arquivo existe para um método separado getBufferedWriter .
Fiz isso para ilustrar o chamado padrão de design factory . Uma factory pode construir objetos diferentes, certo?
O método getBufferedWriter também constrói instâncias diferentes de a BufferedReader dependendo da
existência do arquivo referenciado por path . No jargão dos programadores, os métodos que criam e retornam
instâncias de objetos diferentes, com base em algum parâmetro, são chamados de factories.

[Link] 215/303
22/03/2025, 18:48 Programação Java para crianças

Se você executar o programa, MyTextFileBufferedFileWriter ele produzirá os mesmos resultados que


MyTextFileFileWriter . Se você usar esses programas para escrever textos curtos, não notará a diferença na
velocidade de execução. Mas quando você precisar escrever grandes quantidades de informação,
MyTextFileBufferedFileWriter funcionará mais rápido.

11.4. Argumentos de linha de comando


Até agora, todos os exemplos de código tinham os nomes de arquivo armazenados diretamente no código, ou
como os programadores dizem, codificados no programa. Isso significa que para criar um programa que lê um
arquivo com um nome diferente, você teria que modificar o código e recompilar o programa, o que não é legal.
Você deve criar programas universais que podem receber parâmetros (por exemplo, o nome do arquivo) de uma
linha de comando durante o lançamento do programa.

Na primeira lição deste livro, você executou o programa HelloWorld em uma janela de comando:

JAVA
java HelloWorld

Mas você tem permissão para adicionar argumentos de linha de comando logo após o nome do programa, por
exemplo,

JAVA
java HelloWorld Mary Smith

Neste caso, o programa HelloWorld receberia dois parâmetros de linha de comando: Mary e Smith. Se você se
lembra, sempre escrevemos o método main com um String array como argumento:

JAVA
public static void main(String[] args) {}

A JVM passa o String array para o método principal, e se você iniciar um programa sem nenhum argumento
de linha de comando, esse array permanece vazio. Caso contrário, esse array terá exatamente tantos elementos
quanto o número de argumentos de linha de comando passados ​para o programa.

Vamos ver como podemos usar esses argumentos de linha de comando em uma classe muito simples que irá
apenas imprimi-los:

[Link] 216/303
22/03/2025, 18:48 Programação Java para crianças

JAVA
public class PrintArguments {

public static void main(String[] args) {

// How many arguments we've got?


int numberOfArgs = [Link];

for (int i=0; i<numberOfArgs; i++){


[Link]("I've got " + args[i]);
}
}
}

Este programa faz um loop pelo array args e imprime os argumentos recebidos da linha de comando, se houver.
Execute este programa a partir da janela Command (ou Terminal) como segue:

JAVA
java PrintArguments Mary Smith 123.5

O programa imprimirá o seguinte:

JAVA
I've got Mary
I've got Smith
I've got 123

A JVM colocou Mary no elemento da matriz args[0] , Smith em args[1] e 123 em args[2] .

Argumentos de linha de comando estão sempre sendo passados ​para um programa como strings. É
responsabilidade de um programa converter os dados para o tipo de dados apropriado, por exemplo:

JAVA
int myScore = [Link](args[2]);

É sempre uma boa ideia verificar se a linha de comando contém o número correto de argumentos. Verifique isso
logo no começo do método main . Se o programa não receber os argumentos esperados, ele deve imprimir uma
breve mensagem sobre isso e parar imediatamente usando um método especial exit da classe System :

[Link] 217/303
22/03/2025, 18:48 Programação Java para crianças

JAVA
public static void main(String[] args) {
if ([Link] != 3){
[Link](
"Please provide arguments, for example:");
[Link]("java PrintArguments Mary Smith 123");

// Exit the program


[Link](0);
}
}

Você pode testar seus programas que recebem argumentos de linha de comando sem sair do IntelliJ IDEA. Basta
abrir o menu Run, selecionar Edit Configurations e inserir os valores no campo Program arguments como
mostrado abaixo:

Agora vamos escrever um programa para copiar arquivos. Para fazer esse programa funcionar com quaisquer
arquivos, os nomes dos arquivos originais e de destino precisam ser passados ​para esse programa como
argumentos de linha de comando.

[Link] 218/303
22/03/2025, 18:48 Programação Java para crianças

JAVA
import [Link];
import [Link];
import [Link];
import [Link];

public class FileCopy {

public static void main(String[] args) {


if ([Link] != 2) {
[Link](
"Please provide source and destination file names, for example:");
[Link]("java FIleCopy [Link]");

// Exit the program


[Link](0);
}
Path sourcePath = [Link](args[0]);
Path destinationPath = [Link](args[1]);
try {
[Link](sourcePath, destinationPath);
[Link]("The file " + args[0] + " is copied to " + args[1]);

} catch (IOException ioe) {


[Link]("Can't copy file: " +
[Link]());
}
}
}

A cópia do arquivo é feita chamando o método copy na classe Files . Este programa funcionará bem enquanto
o arquivo de destino não existir. Você pode verificar a existência do arquivo no programa usando o método
exists da classe Files como foi feito na classe MyTextFileReader anteriormente.

11.5. Serialização: Transformando um objeto em bytes


Imagine um prédio que, com o apertar de um botão, pode ser transformado em uma pilha de materiais de
construção. Carregue todos esses materiais no caminhão e dirija para uma cidade diferente. Ao chegar, aperte
outro botão, e o prédio é magicamente recriado em sua forma original. É disso que se trata a serialização Java,
mas em vez de um prédio, usaremos um objeto Java. Ao “clicar no botão serializar”, a JVM transforma uma
instância de um objeto em uma pilha de bytes, e “clicar no botão desserializar” recria o objeto.

Por que você precisaria dessa funcionalidade? Digamos que você esteja trabalhando em um jogo de tabuleiro e
queira salvar o estado atual do jogo para que o jogador possa continuar jogando amanhã, mesmo que o
computador precise ser reiniciado. O programa precisa salvar o estado do jogo em um arquivo e, quando o
jogador iniciar o jogo novamente, o programa deve carregar o estado salvo e recriar a situação no tabuleiro. Criar
uma classe Java com campos como nome do jogador, nível, pontuação e vidas pode ser uma boa maneira de
representar um estado do jogo.

[Link] 219/303
22/03/2025, 18:48 Programação Java para crianças

JAVA
class GameState {
String playerName;
int level;
int score;
int remainingLives;

// other fields go here


}

Quando o usuário seleciona a opção de menu Save Game State , o programa tem que criar uma instância do
objeto GameState , atribuir os valores aos seus campos e salvar esses valores em um arquivo. Mas em qual
formato salvar esses valores? Criar uma String variável e concatenar todos esses valores nela, separando os
valores com vírgulas? É muito trabalho. Além disso, você precisaria lembrar a ordem desses valores
concatenados para que, quando precisar lê-los, saiba a quais campos do objeto GameState atribuí-los.

Felizmente, Java simplifica muito esse processo. Você pode criar uma instância do objeto Java, preenchê-la com
os valores e, então, serializar essa instância em um monte de bytes em um formato especial que lembra a
estrutura da classe GameState . Assim, quando você precisa recriar a instância do GameState para esses bytes,
você pode desserializar o objeto de uma só vez com todos os valores de seus campos.

Um objeto Java pode ser serializado se implementar Serializabe interface. É uma interface muito simples de
implementar, pois não declara nenhum método abstrato. Basta adicionar implements Serializable à
declaração de classe para tornar uma classe serializável. A classe a seguir GameState representará o estado do
jogo.

[Link] 220/303
22/03/2025, 18:48 Programação Java para crianças

JAVA
import [Link];

public class GameState implements Serializable {

String playerName; (1)


int level;
int score;
int remainingLives;

GameState(String playerName, int Level, (2)


int score, int remainingLives){

[Link] = playerName;
[Link]=level;
[Link]=score;
[Link] = remainingLives;
}

public String toString(){ (3)

return "PlayerName: " + playerName + ", level:" + level + ", score: " + score +
", remainingLives: " + remainingLives;
}
}

1. A GameState classe tem quatro campos que descrevem o estado atual do jogo.

2. O construtor da classe preenche esses campos com os valores passados ​como argumentos.

3. Sobrescrevemos o método toString para poder imprimir o conteúdo dos campos. O método toString é
declarado na classe Object - o ancestral de todas as classes Java. Por exemplo, se você escrever
[Link](myObject) , Java encontra e invoca o toString`method on the object
`myObject . Você verá isso em ação na classe GameStateManager abaixo.

Objetos Java são serializados em um fluxo de E/S do tipo ObjectOutputStream . Você precisará criar uma
instância de OutputStream , canalizá-la com ObjectOutputStream e invocar um método writeObject .

Para desserializar (ler de volta) um objeto Java, você precisa criar uma instância de InputStream , canalizá-la
com ObjectInputStream e invocar um método readObject .

Vamos criar uma classe GameStateManager que executará as seguintes ações:

Crie uma instância da classe GameState e preencha seus campos com alguns dados.

Serialize esta instância de GameState no arquivo chamado [Link] .

Deserialize a instância GameState do arquivo [Link] em um novo objeto.

[Link] 221/303
22/03/2025, 18:48 Programação Java para crianças

JAVA
import [Link];
import [Link];
import [Link];
import [Link];
import [Link];
import [Link];
import [Link];

public class GameStateManager {

public static void main(String[] args) {

// Create and populate the GameState object


GameState gameState =
new GameState("Mary", 45,28000,3); (1)

// The file for serialization/deserialization


Path path = [Link]("[Link]"); (2)

saveGameState(path, gameState); (3)


[Link]("The GameStateObject is serialized");

GameState deserializedGameState = (4)


loadGameState(path);
[Link]("Deserialized game state; " +
deserializedGameState);
}

// Serialize the gameState into a file


private static void saveGameState(Path path, (5)
GameState gameState) {

try (ObjectOutputStream whereToWrite = (6)


new ObjectOutputStream([Link](
path, [Link]))){

[Link](gameState); (7)

} catch (IOException ioe) {


[Link]("Can't serialize file: " + [Link]());
}
}

// Deserialize the GameState from a file


private static GameState loadGameState(Path path){

GameState loadedGameState = null;

try (ObjectInputStream whereToReadFrom = (8)


new ObjectInputStream([Link](path))){

loadedGameState= (GameState) [Link](); (9)

[Link] 222/303
22/03/2025, 18:48 Programação Java para crianças

} catch (ClassNotFoundException cnfe) {


[Link]("Can't find the declaration of GameState: " + [Link]());
} catch (IOException ioe) {
[Link]("Can't deserialize file: " + [Link]());
}

return loadedGameState;
}
}

1. O programa começa com a criação e o preenchimento do objeto de estado do jogo. Neste exemplo, usei
valores codificados, mas em um jogo real eles devem ser retirados das variáveis ​que refletem o status real do
jogo.

2. O nome do arquivo serializado é [Link] e ele será representado pelo Path objeto.

3. Em seguida, chamamos o método saveGameState que serializará o objeto GameState em um arquivo.

4. Após a serialização ser concluída, nós a desserializamos de volta para outra instância do objeto de estado do
jogo. A variável deserializedGameState aponta para essa nova instância.

5. O método saveGameState é responsável por serializar o objeto. Ele recebe dois parâmetros - o caminho
para o arquivo e a referência ao objeto que deve ser serializado.

6. Agora estamos abrindo o arquivo OutputStream e canalizando-o com o ObjectOutputStream .

7. É necessária apenas uma linha de código para serializar o GameState objeto no arquivo usando o método
write .

8. O método loadGameState desserializa o objeto de um arquivo, e estamos abrindo o InputStream e


canalizando-o com o ObjectInputStream . Os dados do arquivo serão lidos no mesmo formato e ordem
em que foram escritos. Então, se você alterar a declaração da classe GameState entre serialização e
desserialização, Java lançará InvalidClassException .

9. Leva apenas uma linha de código para desserializar o arquivo em um GameState objeto usando o método
read . Neste exemplo, o mesmo programa serializa e desserializa o estado do jogo, mas pode não ser o
caso. Você pode enviar o objeto serializado para outro computador na rede, e outro programa pode
desserializar o GameState . Portanto, é importante que a declaração do GameState esteja disponível em
ambos os computadores. A exceção ClassNotFoundException será lançada se a declaração da classe
GameState não estiver disponível.

Execute o programa GameStateManager e você verá que ele cria um novo arquivo [Link] . Abra
esse arquivo em um editor de texto e você verá algumas coisas sem sentido. O Java serializa objetos em seu
formato interno, que não é para ser lido por pessoas. A saída do console ficará assim:

[Link] 223/303
22/03/2025, 18:48 Programação Java para crianças

JAVA
The GameStateObject is serialized
Deserialized the game state
Deserialized game state object; PlayerName: Mary, level:0, score: 28000, remainingLives: 3

Se você colocar o ponto de interrupção logo após a invocação do loadGameState método, poderá ver duas
instâncias diferentes do GameState objeto, conforme mostrado abaixo:

Observe como o IDEA mostra convenientemente os valores das variáveis ​não apenas na visualização do
depurador na parte inferior, mas no código-fonte do programa em fonte acinzentada.

11.6. Projeto: Salvando as pontuações do jogo


Neste projeto, você escreverá um programa que pode manter o histórico das pontuações do jogo em um arquivo
usando serialização Java. Este programa deve ser capaz de desserializar e classificar as pontuações salvas,
mostrando as pontuações mais altas no topo.

Para concluir este projeto, você precisa entender como comparar objetos. Embora comparar dois números seja
fácil, objetos Java podem incluir vários campos e você precisa decidir quais campos do objeto devem ser
comparados para colocar os objetos em uma determinada ordem. Nesta tarefa, você ordenará os objetos
Score para que os objetos com maior valor do campo score venham primeiro. Em outras palavras, você
precisará classificar os objetos Score na ordem decrescente do campo score .

1. Crie uma classe serializável Score para representar uma pontuação de jogo.

[Link] 224/303
22/03/2025, 18:48 Programação Java para crianças

JAVA
import [Link];
import [Link];

class Score implements Serializable {


String name;
int score;
LocalDateTime dateTime;

Score(String name, int score, LocalDateTime dateTime){


[Link]=name;
[Link]=score;
[Link]=dateTime;
}

public String toString(){


return name + " scored " + score + " on " + dateTime;
}
}

2. Create a class ScoreManager with the method main . Inside main declare and instantiate a collection of
scores: List<Score> scores . Create the Path object to point at the file [Link] .
JAVA
List<Score> scores = new ArrayList<>();

Path path = [Link]("[Link]");

The class ArrayList is one of the Java collections that implements the List interface, so declaring this
variable of type List is valid.

3. Add the methods saveScores and loadScores to the class ScoreManager :


JAVA
private static void saveScores(Path path, List<Score> gameScores) {}

private static List<Score> loadScores(Path path){}

4. Write the code in the method saveScore to serialize the collection scores into a file [Link] . Use
the code from the class GameStateManager as an example, but this time you’ll need to serialize not one
object instance, but a collection of objects, for example:

JAVA
try (ObjectOutputStream whereToWrite = new ObjectOutputStream(
[Link](path, [Link]))){

[Link](gameScores);

} catch (IOException ioe) {


[Link]("Can't serialize scores: " + [Link]());
}

[Link] 225/303
22/03/2025, 18:48 Programação Java para crianças

5. Write the code in the method loadScores to deserialize the data from the file [Link] :

JAVA
List<Score> loadedScores= null;

try (ObjectInputStream whereToReadFrom =


new ObjectInputStream([Link](path))){

loadedScores=
(List<Score>) [Link]();

} catch (ClassNotFoundException cnfe) {


[Link]("Can't find the declaration of Score: " + [Link]());
} catch (IOException ioe) {
[Link]("Can't deserialize file: " + [Link]());
}

return loadedScores;

6. Starting from this step all coding should be done in the main method of ScoreManager . If the file
[Link] already exists, load the collection of score. If [Link] doesn’t exist, create a new collection.
JAVA
if ([Link](path)) {
scores = loadScores(path);

} else {
scores = new ArrayList<>();
}

7. Create an instance of the Score class, populate its fields name , score , and dateTime . Assign a
random number generated by the class [Link] to the score field. Assign the current date
and time to the field dateTime Use the method nextInt to generate a number between 0 and 50000.
Add the hew score to the scores collection.

JAVA
Random numberGenerator = new Random();

Score myScore = new Score("Mary", [Link](50000), [Link]());

[Link](myScore);

8. Print all the scores and invoke the method saveScore to serialize all scores into the file.

JAVA
[Link]("All scores:");
[Link](s -> [Link](s));

saveScores(path, scores);

[Link] 226/303
22/03/2025, 18:48 Programação Java para crianças

9. Sort and print the collection to show the highest score on top. Use the class Comarator to specify that
sorting should be done by the field score . For sorting in the descendant order invoke the method
reverseOrder . Use the Stream API.

JAVA
[Link]("Sorted scores (highest on top):");
Comparator<Score> byScoreDescending =
[Link]([Link](s -> [Link]));

[Link]()
.sorted(byScoreDescending)
.forEach(s -> [Link](s));

10. Run the program ScoreManager and observe that all scores are printed in descending order. :toc-
placement!: :imagesdir: .

[Link] 227/303
22/03/2025, 18:48 Programação Java para crianças

12. Networking: Downloading Files From the Internet


People can talk to each other if they speak and understand the same language. Computers connected to a
network can communicate with each other if they use the same protocol. For example, your Web browser uses
HTTP protocol to send requests and receive responses from a remote server. Such a communication is possible if
the program running on the server also understands HTTP. Any network protocol defines the rules of how a
program should send or receive data.

Say, you want to find a book about Harry Potter in the online bookstore. Usually you’d need to enter Harry
Potter in the search field of that bookstore Web site and press the button to start the search, but the browser sends
a request with a lot more data than a dozen of characters you’ve entered. According to HTTP protocol, every
request should include a request header, which defines the method of sending data, identifies the browser that
sends it, requests to keep the connection open (or not), and has other attributes.

Similarly, a server should run a program that receives and understands the HTTP request, finds all books that
have Harry Potter in the title, and sends a response back to you, adding a response header to the data. Both
request and response headers can add several hundred bytes to the actual data being sent.

Some other popular networking protocols are TCP/IP, FTP, WebSocket. In this chapter you’ll learn how to write
Java programs that can connect to remote servers and download data using HTTP protocol.

12.1. How Computers Find Each Other on the Web


If you want to visit a person, you need to know his or her exact address - the street, the building and apartment
number. In the World Wide Web (WWW), to visit a Web site you need to know its Uniform Resource Locator (a
URL). Let’s see which parts a URL consists of by using an example from Nickelodeon’s Web site:

This URL tells me that the host (the server) [Link] has the file called [Link] located
in the folder games. The port number plays the same role as an apartment number in a building.

The server [Link] can run many programs, which serve users' requests, but we want to enter this server
through "the door" number 80. As a matter of fact, the port number 80 is a default port number for all Web
servers that use HTTP. That’s why if you skip the port number, your Web browser will try to connect to the Web
server via the port 80.

[Link] 228/303
22/03/2025, 18:48 Programação Java para crianças

If a URL starts with https, the s stands for "secure". All requests and responses are automatically encrypted by
the browser and the server for additional security. If the user enters a URL that starts with https and has no port
number, the Web browser sends an HTTPS request to the server’s port 443.

Now let’s dissect another URL from Nickelodeon.

There is no file name here. What does video stand for in this URL? It’s not a file, and it’s not a folder on the host
either. It’s just an ID that represents some resources at [Link]. There is a program running at [Link] that
understands what this ID means and redirects the request to the application that serves the Web page with videos
that may look like this:

Often the content that corresponds to a resource ID is not stored in a file, but is generated on the fly by a server-
side program and can change daily, hourly, every minute or every second. Most likely by the time you enter
[Link] in your browser the content will be different.

[Link] 229/303
22/03/2025, 18:48 Programação Java para crianças

12.2. Domain Names and IP Addresses


The name of the server (the host name) must be unique, and when a person or an organization registers a Web
site, a unique number is assigned to this physical server. This number is called an IP address. The IP address is
either a group of four numbers (e.g. [Link]) or up to eight hexadecimal numbers (e.g.
2001:cdba:0000:0000:0000:0000:3257:9652). Remembering these long numbers would be difficult for people
hence why we’re using domain names that are easier to remember (e.g. [Link] or [Link]).

When you’re entering a domain name in the browser, your Internet service provider uses special software to find
the IP address that corresponds to the entered domain name. If found, your browser receives the requested Web
page, which is a document in HTML format. If not found, you’ll get an error message that your search didn’t
match any documents.

You can say,"But entering [Link] shows a lot of content even without providing any document name!" This
happens because Web sites creators configure their servers to serve a certain HTML file if the user doesn’t
specify any. Often they name the file with the home page content [Link], but it can be any other file too.

Most people connected to the Internet are getting dynamic (temporary) IP addresses assigned to their computers,
which can change without notice.

12.3. Downloading Files From the Web


In Chapter 11 you’ve learned how to read a local file if you know its location. You’d open a stream pointing to
this file and read it. The same holds true for reading remote files. The only difference is that you need open the
stream over the network. Java offers a variety of classes for reading (or writing) remote files. All these classes
are located in the package [Link] ([Link] In this
chapter we’ll use the classes that can exchange data between your computer and remote hosts using HTTP.

In particular, Java has a class [Link] that helps your program to connect to a remote computer on the
Internet and get access to a resource there, provided that it’s not protected from public access.

Let’s see how you can start writing a program that creates an instance of the URL object that points at some
remote resource, e.g. [Link]:

JAVA
try{
URL myUrl = new URL("[Link]

// More code will go here


}
catch(MalformedURLException ex){
[Link]();
}

[Link] 230/303
22/03/2025, 18:48 Programação Java para crianças

The MalformedURLException is thrown if you made a typo in the code, e.g. you’ve typed htp instead of http
or some spaces sneaked into the URL. If the MalformedURLException is thrown, it does not indicate that the
remote server is down; just check "the spelling" of your URL.

Creation of the URL object does not establish a connection with the remote computer. If your program needs to
read a remote file, you still need to open a stream on that file. Usually a program performs the following steps to
read a file from the Internet via HTTP connection:

1. Create an instance of the class URL .

2. Create an instance of the URLConnection to open a connection using the URL object from Step 1.

3. Get a reference to the input stream of this object by calling the method getInputStream from
URLConnection .

4. Read the data from the stream.

While writing code for reading streams over the network, you’ll have to handle possible I/O exceptions the same
way you did while reading the local files in Chapter 11. The following program WebSiteReader reads and
prints the code of [Link] page.

[Link] 231/303
22/03/2025, 18:48 Programação Java para crianças

JAVA
import [Link];
import [Link];
import [Link];
import [Link];
import [Link];
import [Link];

public class WebSiteReader {


public static void main(String args[]){

URL url = null;


URLConnection urlConn = null;

try
{
url = new URL("[Link] ); (1)

urlConn = [Link](); (2)

} catch( IOException e){


[Link]("Can't connect to the provided URL:" + [Link]() );
}

try( InputStreamReader inStream = (3)


new InputStreamReader ([Link](), "UTF8");
BufferedReader buff = new BufferedReader(inStream);){

String currentLine;

// Read and print the code of the Google's home page


while ((currentLine = [Link]())!= null ){ (4)

[Link](currentLine);
}
} catch(MalformedURLException ex){
[Link] ("Check the spelling of the URL" + [Link]());
}
catch(IOException ioe){
[Link]("Can't read from the Internet: "+
[Link]());
}
}
}

1. The WebSiteReader creates an instance of the class URL .

2. Then it gets a reference to an instance of the URLConnection object to open a connection with the stream.

3. After that WebSiteReader opens InputStreamReader , which is piped with BufferedReader .

4. The while loop reads the line from BufferedReader and if it’s not null , it prints the line on the
console.

[Link] 232/303
22/03/2025, 18:48 Programação Java para crianças

Make sure your computer is connected to the Internet before you run the WebSiteReader program. Actually, I
was writing this program while sitting on the plane without the Internet connection. This is what the program
printed up in the sky:

HTML
Can't read from the Internet: [Link]: [Link]

When my computer got the Internet connection the output was different. Here’s a fragment of what you can
expect to see on the console after running WebSiteReader :

JAVASCRIPT
<!doctype html><html itemscope="" itemtype="[Link] lang="fr"><head><meta
content="/logos/doodles/2015/110th-anniversary-of-first-publication-of-becassine-
[Link]" itemprop="image"><title>Google</title><script>(function()
{[Link]=
{kEI:'5OzPVMyJM4ukygPRz4CoBQ',kEXPI:'4011559,4013606,4020347,4020562,4021598,4022545,4023678,40
24599,4024626,4025090,4027899,4027921,4028062,4028128,4028367,4028508,4028634,4028706,4028717,8
300111,8500393,8500852,8501081,8501084,10200083,10200903,10200904',authuser:0,kSID:'5OzPVMyJM4u
kygPRz4CoBQ'};[Link]='us';})();(function(){[Link]=
[];[Link]=0;[Link]=function(a){for(var b;a&&(![Link]||!
(b=[Link]("eid")));)a=[Link];return b

This is a mix of HTML and JavaScript code. The class WebSiteReader explicitly creates the object
URLConnection . Strictly speaking, you could achieve the same result by using only the class URL :

JAVA
URL url = new URL("[Link]
InputStream in = [Link]();
BufferedReader buff= new BufferedReader(new InputStreamReader(in));

The reason you may want use the URLConnection class is that it could give you some additional control over
the I/O process. For example, by calling its method setDoOutput with the argument true you enable
WebSiteReader to write to the remote URL . In this case you’d need to get a reference to an OutputStream
object by calling getOutputStream method on the URLConnection object. If you wanted to write a program
that can send data to the server, you’d need to learn server-side programming, which this book doesn’t cover.

12.3.1. Downloading Any File From the Internet


In Chapter 11 you’ve learned how to create a file and write into it. The WebSiteReader program just prints the
remote data on the console, but you could have saved the data in the local file as well. It’s time to add the code
that writes into a file. The goal is to write a program that can download any unprotected file (such as images,
music, and binary files) available on the Web.

[Link] 233/303
22/03/2025, 18:48 Programação Java para crianças

A classe a seguir FileDownload cria o URLConnection objeto e obtém seu InputStream . Esta classe
também cria um OutputStream para o arquivo local. A URL e o nome do arquivo local são fornecidos ao
FileDownload programa como argumentos de linha de comando (explicados no Capítulo 11). O
FileDownload conecta-se à URL fornecida, baixa seu conteúdo e o salva no arquivo local.

[Link] 234/303
22/03/2025, 18:48 Programação Java para crianças

JAVA
import [Link];
import [Link];
import [Link];
import [Link];
import [Link];
import [Link];
import [Link];

class FileDownload{

public static void main(String args[]){


if ([Link] != 2){ (1)
[Link](
"Proper Usage: java FileDownload FileURL DestinationFileName");
[Link](
"For example: java FileDownload [Link] [Link]");
[Link](-1);
}

URLConnection fileStream=null;

try{
URL remoteFile=new URL(args[0]); (2)

fileStream=[Link](); (3)

} catch (IOException ioe){


[Link]();
}

Path path = [Link](args[1]); (4)

try(OutputStream fOut=[Link](path); (5)

InputStream in = [Link]();){ (6)

[Link]("Downloading from " + args[0] + ". Please wait...");

// Read a remote file and save it in the local one

int data;

while((data=[Link]())!=-1){ (7)
[Link](data); (8)
}

[Link]("Finished downloading the file. It's located at


"+[Link]());
} catch (Exception e){
[Link]();
}
}
}

[Link] 235/303
22/03/2025, 18:48 Programação Java para crianças

1. Este programa começa verificando se dois argumentos de linha de comando foram fornecidos. Se não, ele
imprime a mensagem mostrando a maneira correta de iniciar FileDownload e sai do programa invocando
o método exit no System objeto.

2. Em seguida, o programa cria uma instância do URL objeto usando a URL fornecida como o primeiro
argumento da linha de comando.

3. Estabelecendo uma conexão com o arquivo remoto.

4. Criar um Path objeto apontando para um arquivo local onde os dados baixados serão salvos.

5. Obtendo o OutputStream arquivo local para gravação.

6. Obtendo o InputStream arquivo remoto para leitura.

7. Lendo um byte do InputStream .

8. Escrevendo um byte para o OutputStream .

Preparei uma imagem para você que está localizada em [Link] . É uma foto que tirei na
cidade de Nova York há algum tempo. Execute este programa com os dois argumentos de linha de comando a
seguir:

HTML
[Link] [Link]

No meu computador, a saída do console ficou assim:

JAVA
Downloading from [Link] Please wait...
Finished downloading the file. It's located at
/Users/yfain11/IdeaProjects/jfk/Chapter12/[Link]

O FileDowload programa baixou a foto e a salvou no arquivo [Link] . Este programa não tem conhecimento
de que tipo de dados ele baixou - ele estava simplesmente lendo e gravando os dados byte após byte. Neste caso,
era uma imagem, mas o mesmo programa pode ser usado para baixar áudio e outros arquivos que tenham acesso
aberto ao público.

Se você abrir o arquivo baixado com um programa que possa mostrar imagens, verá a seguinte foto:

[Link] 236/303
22/03/2025, 18:48 Programação Java para crianças

[Link] 237/303
22/03/2025, 18:48 Programação Java para crianças

Neste capítulo, mostrei como baixar um arquivo usando HTTP. Desenvolvedores Java profissionais usam várias
técnicas, tecnologias e protocolos para trabalhar com conteúdo remoto. Se você estiver interessado em explorar
esses tópicos avançados por conta própria, o Tutorial Java EE ([Link] é um bom
começo. Talvez um dia eu escreva um livro sobre programação do lado do servidor para crianças.

12.4. Projeto: Baixando Música


Neste projeto você verá como nosso FileDownload programa verifica se consegue baixar um arquivo MP3
também.

1. Visite o site: [Link] e escolha um MP3 que você goste. No


momento em que este texto foi escrito, a página da Web da [Link] tinha a seguinte aparência:

[Link] 238/303
22/03/2025, 18:48 Programação Java para crianças

2. Clique com o botão direito no botão azul "Free MP3", e você verá um menu pop-up do navegador.
Selecione o item de menu que permite copiar o endereço do link. O link será copiado na área de
transferência do seu computador. Selecionei um link para um arquivo de música que se parecia com este:

HTML
[Link]

3. No IDEA, selecione o menu Run | Edit Configuration e cole este link no campo Program arguments para o
FileDownload programa. Este link será o primeiro argumento da linha de comando.

4. Mova o cursor para o final do campo Program arguments e adicione um espaço seguido pelo nome do
arquivo local, onde você quer salvar a música. Eu digitei song1.mp3 . Então pressione o botão OK.

5. Execute o programa FileDownload . O arquivo MP3 será baixado para o arquivo local song1.mp3. Aqui
está a saída do console que obtive:
HTML
Downloading from
[Link] Please
wait...
Finished downloading the file. It's located at
/Users/yfain11/IdeaProjects/jfk/Chapter12/song1.mp3

6. Abra este arquivo no seu MP3 player e curta a música!

[Link] 239/303
22/03/2025, 18:48 Programação Java para crianças

7. Feche o IDEA e repita o mesmo exercício na linha de comando. Você precisará abrir uma janela de
Comando (ou Terminal), alterar o diretório para onde o arquivo [Link] está localizado. Por
padrão, o IDEA armazena classes compiladas no diretório out/production . Meu projeto IDEA foi nomeado
Chapter12, e é aqui que suas classes compiladas estavam localizadas no meu computador:
HTML
/Users/yfain11/IdeaProjects/jfk/Chapter12/out/production/Chapter12

8. Execute o FileDownload programa fornecendo a URL e o nome do arquivo local como argumentos de
linha de comando. Ele deve baixar o arquivo da mesma forma que fez no IDEA IDE.

[Link] 240/303
22/03/2025, 18:48 Programação Java para crianças

13. Criando um jogo de pingue-pongue


Nos capítulos 6, 7 e 10, você aprendeu como criar GUI simples com JavaFX usando componentes como botões,
rótulos e campos de texto. Neste capítulo, usaremos JavaFX novamente, mas dessa vez você desenhará e
animará formas.

O JavaFX inclui o pacote [Link]


([Link] , que inclui classes como Circle ,
Rectangle , Line e mais. Todas essas classes são herdadas da classe Shape .

Ping-Pong é o jogo perfeito para ilustrar as capacidades de desenho e animação do JavaFX. Neste jogo, você terá
outra chance de trabalhar com manipuladores de eventos e aprenderá como mover (animar) formas pelo palco.

13.1. A Estratégia
Vamos criar algumas regras para o nosso jogo de pingue-pongue:

1. Este jogo terá dois jogadores chamados Kid e Computer. A mesa deve ser pintada de verde, e a raquete
esquerda deve ser pintada de azul - ela será controlada pelo Computer. A raquete direita deve ser amarela -
ela será controlada pelo Kid. Inicialmente a bola vermelha deve estar localizada no centro da mesa.

2. Um novo jogo começa quando um jogador pressiona a tecla N no teclado, pressionar Q encerrará o jogo e a
tecla S sacará a bola. Somente a criança pode sacar a bola.

3. Os movimentos da pá do Kid devem ser controlados pelas teclas de seta para cima e para baixo. Pressionar a
tecla uma vez deve mover a pá verticalmente pelo número predefinido de pixels para cima ou para baixo. A
pá não deve cruzar as bordas da mesa.

4. O Kid pode mover a raquete direita e pressionar a tecla S. Isso deve sacar a bola da posição onde a raquete
direita está localizada. A bola pode se mover em um ângulo, o que significa que suas coordenadas x e y
devem mudar durante o movimento. Se a bola cruzar as bordas superior ou inferior da mesa, o Kid perde um
ponto.

5. Enquanto a bola se move para a esquerda, o computador deve mover a raquete esquerda na direção do
movimento da bola.

6. Se a bola tocar a raquete esquerda, ela deve quicar e começar a se mover para a direita. Quando o
Computador quica a bola, ela pode se mover apenas horizontalmente para a direita.

7. Se a bola tocar na raquete do Kid na metade superior da mesa, a bola deve estar se movendo na direção para
cima e para a esquerda. Se a bola estiver localizada na parte inferior da mesa, ela deve se mover na direção
para baixo e para a esquerda. O jogo dura até que um dos jogadores atinja a pontuação de 21. Como o
computador não pode sacar a bola, o Kid deve marcar um ponto se a bola cruzar a borda esquerda da mesa.

[Link] 241/303
22/03/2025, 18:48 Programação Java para crianças

Se a bola cruzar as bordas superior ou inferior da mesa, o ponto é dado ao computador. O computador
também pode ganhar o ponto se quicar a bola e ela cruzar a borda direita da mesa. Essas regras não são as
mesmas de um jogo de pingue-pongue real, mas são boas o suficiente para o nosso jogo.
8. O placar do jogo deve ser exibido no canto inferior esquerdo da tabela.
A princípio, parece ser uma tarefa muito desafiadora. Na programação, muitas vezes temos que dividir o
problema complicado em um conjunto de tarefas menores e mais simples. A capacidade de fazer isso é chamada
de pensamento analítico , e ajuda não apenas na programação, mas em todos os lugares da sua vida. Não fique
frustrado se não conseguir atingir uma grande meta, divida-a em um conjunto de tarefas menores e alcance-as
uma de cada vez!

Vamos começar a quebrar nossa tarefa complexa. Tente visualizar uma mesa de pingue-pongue. Você consegue
escrever um programa que desenhe um retângulo verde? Esse é nosso primeiro objetivo a atingir. Então
adicionaremos a raquete. Então veremos como desenhar a bola. Aprender a mover a bola será a próxima tarefa.
Escrever os manipuladores de eventos do teclado não deve ser muito difícil.

Agora vamos implementar cada passo da estratégia do jogo, um passo de cada vez.

13.2. Etapa 1: Criando a tabela


Nesta seção, nosso objetivo é desenhar uma mesa de pingue-pongue 2D, que deve se parecer com um retângulo
verde.

Vamos começar criando um novo projeto JavaFX no IntelliJ IDEA. Selecione JavaFX como um tipo de projeto.
Pressione Next e insira PingPong como um nome de projeto na próxima janela pop-up. Pressione o botão Finish
e o IDEA gerará um novo projeto para você. Renomeie (clique com o botão direito do mouse | Refactor |
Rename) o arquivo [Link] para [Link] , a Main classe para PingPong , e Controller para
PingPongController . Altere o nome do pacote de sample para pong da mesma forma.

[Link] 242/303
22/03/2025, 18:48 Programação Java para crianças

Agora vamos desenhar a mesa de pingue-pongue no Scene Builder. Clique com o botão direito no arquivo
[Link] e abra-o no Scene Builder. Como você viu no Capítulo 7, o FXML gerado usa o
<GridBag> como um contêiner padrão. Você verá um vazio GridBag no painel Hierarchy. O lado esquerdo
dos painéis do Scene Builder terá a seguinte aparência:

[Link] 243/303
22/03/2025, 18:48 Programação Java para crianças

Não vou usar nenhum layout no jogo PingPong. O jogo consistirá em uma série de formas que manterei no
Group contêiner. Ainda não o usamos - ele Group é usado apenas para manter vários componentes filhos
juntos. Agrupar componentes em um contêiner pode ser útil se você precisar atribuir um manipulador de eventos
a todos os componentes filhos ou redimensioná-los automaticamente como um grupo.

No Scene Builder, exclua o GridBag contêiner e arraste/solte o Group da seção Miscellaneous para o painel
Hierarchy. Em seguida, arraste/solte a Rectangle do painel Shapes para o Group . Redimensione-o e escolha
uma cor verde agradável na propriedade Fill no lado direito. Você escolherá uma cor de uma paleta suspensa, e o
código de cor correspondente será inserido automaticamente como uma fill propriedade do Rectangle . Seu
Scene Builder deve ficar assim:

Abra o arquivo [Link] e você verá a tag <Rectangle> dentro do <Group> gerado pelo Scene Builder.
Defina a largura do Rectangle para 400, e a altura para 250. Deve ficar assim:

[Link] 244/303
22/03/2025, 18:48 Programação Java para crianças

XML
<?xml version="1.0" encoding="UTF-8"?>

<?import [Link].*?>
<?import [Link].*?>
<?import [Link].*?>
<?import [Link].*?>
<?import [Link]?>
<?import [Link]?>
<?import [Link]?>
<?import [Link]?>

<Group xmlns="[Link] xmlns:fx="[Link]


<children>
<Rectangle arcHeight="5.0" arcWidth="5.0" fill="#31b287" height="250" stroke="BLACK"
strokeType="INSIDE" width="400" />
</children>
</Group>

O archHeight e arcWidth foram gerados automaticamente caso você precise criar cantos arredondados no
retângulo. As propriedades stroke e strokeType definem a aparência e o posicionamento da borda do
retângulo. Cada retângulo tem as propriedades x e y que definem as coordenadas do seu canto superior
esquerdo dentro do contêiner. Por padrão, os valores de x e y são zeros, então este retângulo será desenhado a
partir do canto superior esquerdo do Group contêiner.

Se você estiver interessado em aprender como diferentes propriedades alteram a aparência do retângulo, visite a
documentação online ([Link] para esta classe.
Tenha em mente que algumas das propriedades são definidas na classe Shape , a ancestral da Rectangle .

A execução da classe gerada automaticamente PingPong mostrará a seguinte janela:

[Link] 245/303
22/03/2025, 18:48 Programação Java para crianças

Há algumas coisas que não gosto aqui. Primeiro, os cantos do retângulo são arredondados só um pouquinho. Isso
é causado pelas propriedades archHeight e arcWidth , que são diâmetros verticais e horizontais dos arcos de
canto. Vou excluí-los da tabela retângulo em [Link] .

Segundo, a janela tem um título Hello World definido pelo código gerado automaticamente no IntelliJ IDEA. É
fácil mudar na classe PingPong , mas eu nem quero ver uma barra de título!

Esta também é uma correção fácil no JavaFX. Definir o estilo do palco para UNDECORATED removerá o título e
as bordas padrão da janela. Mas se eu remover a barra de título, perderei a capacidade de fechar a janela clicando
no círculo (ou uma pequena cruz no Windows). Um pouco mais tarde, escreveremos o código para fechar a
janela pressionando a tecla Q no teclado. Neste ponto, o código da PingPong classe se parece com isto:

[Link] 246/303
22/03/2025, 18:48 Programação Java para crianças

JAVA
package pong;

import [Link];
import [Link];
import [Link];
import [Link];
import [Link];
import [Link];

public class PingPong extends Application {

@Override
public void start(Stage primaryStage) throws Exception{

Parent root = [Link](getClass().getResource("[Link]"));

[Link](new Scene(root, 400, 250));


[Link]([Link]);
[Link]();
}

public static void main(String[] args) {


launch(args);
}
}

This class was generated by IDEA, but I’ve removed the Hello World title, set the size of the scene to 400 by
250 pixels, and added the line [Link]([Link]); . Running the
PingPong class will display the following green rectangle:

[Link] 247/303
22/03/2025, 18:48 Programação Java para crianças

Now let’s open [Link] in Scene Builder again and add the paddles and the ball on top of the table. For
paddles, I’ll drag/drop two Rectangle objects from the Shapes section onto the Group container. Our paddles
will have a size of 10 by 50 pixels. The left paddle will be blue, and the right one will be yellow. Then I
drag/drop, resize and color the Circle to set its radius to 9 pixels, and then will paint it red. My Scene Builder
will look like this:

[Link] 248/303
22/03/2025, 18:48 Programação Java para crianças

Now back to IDEA. Since our shapes will need to communicate with the controller class, we need to assign an
fx:id to each of them. Let’s assign the fx:id="theGroup" to the Group container. Our green Rectangle
will get fx:id="table" .

The computer will play with the left paddle, and I’ll give it fx:id="compPaddle" . The Kid will play with the
right paddle that will go by fx:id="kidPaddle" . The ball will get fx:id="ball" . Now The Group
container in my file [Link] will look like this:

XML
<Group fx:id="theGroup" xmlns="[Link] xmlns:fx="[Link]
<children>
<Rectangle fx:id="table" fill="#31b287" height="250" stroke="BLACK" strokeType="INSIDE"
width="400" />
<Rectangle fx:id="compPaddle" arcHeight="5.0" arcWidth="5.0" fill="DODGERBLUE"
height="50.0" layoutX="24.0" layoutY="98.0" stroke="BLACK" strokeType="INSIDE" width="10.0" />
<Rectangle fx:id="kidPaddle" arcHeight="5.0" arcWidth="5.0" fill="#f0ff1f" height="50.0"
layoutX="365.0" layoutY="98.0" stroke="BLACK" strokeType="INSIDE" width="10.0" />
<Circle fx:id="ball" fill="#ff1f35" layoutX="191.0" layoutY="123.0" radius="9.0"
stroke="BLACK" strokeType="INSIDE" />
</children>
</Group>

Running the PingPong program will display the following ping-pong table:

[Link] 249/303
22/03/2025, 18:48 Programação Java para crianças

The GUI drawing is complete, now we need to take care of the user interactions, which will be done in the class
PingPongController . In [Link] we need to assign this class as the fx:controller to the Group
(see Chapter 8 for a refresher):

XML
<Group fx:id="theGroup" fx:controller="[Link]"
xmlns="[Link] xmlns:fx="[Link]

Dear Scene Builder and FXML, you’ve been very helpful. Now I’m happily going back to Java programming.

13.3. Step 2: Handling Keyboard Events


We need to add the event handler methods to the class PingPongController to process keyboard events.
Every key on the keyboard has a special code assigned, and our first goal is to figure out which key the player
pressed.

For processing keyboard events JavaFX components have special event handler properties onKeyPressed ,
onKeyReleased , and onKeyTyped . The first two properties allow you to program different actions for the
downward and upward key motions, if needed.

The onKeyTyped is used to assign a handler to the event when the key code is sent to the system output. This
event is not generated ([Link] for the keys that
don’t produce character output. We’ll use onKeyReleased - this is when the the user lifts his finger up.

[Link] 250/303
22/03/2025, 18:48 Programação Java para crianças

IDEA can help you find out which event handlers can be used with a particular component.
NOTE Just click CTRL-Space inside this component’s FXML tag and start typing with the letters
on and you’ll see all applicable event handlers.

When the user releases a key, the onKeyReleased method handler receives the KeyEvent object as an
argument. The method getCode from the class KeyEvent returns the KeyCode object that represents the key
pressed. For example, if you press the button Q, the getCode will return Q . If you press the arrow up, the
getCode will return UP .

But the same key can result in displaying more than one character (e.g. Q or q) The method getText of
KeyEvent returns a String that represents the character typed by the user.

To enable our GUI to react on keyboard events right after the program starts, we need to set the focus on the
GUI. This was not required when we clicked on the GUI components with the mouse, but now we won’t even
touch the screen.

To set the focus to the Group container we’ll need to do two things:

1. Enable the Group to receive the focus by useing the attribute focusTraversable="true" in
[Link].

2. Right after the stage is displayed in the PingPong class, we’ll call the method requestFocus on the
Group container. The method start in PingPong will look like this (I’ve added just the last line to the
code generated by IDEA):

JAVA
public void start(Stage primaryStage) throws Exception{

Parent root = [Link](getClass().getResource("[Link]"));

[Link](new Scene(root, 400, 250));


[Link]([Link]);

[Link]();
[Link]();
}

13.3.1. Processing Keyboard Events in the Controller


In the code that comes with this chapter the final version of the controller is called PingPongController . I’ve
also included multiple versions of the controller that gradually implement the steps listed in the game strategy.
Each "intermediate" controller class name starts with PingPongController followed by a different suffix
with a version number (e.g. PingPongController_v1 , PingPongController_v2 etc.) The starting

[Link] 251/303
22/03/2025, 18:48 Programação Java para crianças

comment in each class briefly describes what was added in this version of the controller. To see any of these
controllers in action, just specify its name as fx:controller in the file [Link] and run the
PingPong program.

In InelliJ IDEA you can easily compare two files to see the difference. Press CTRL or CMD
button and click on the names of two files you’d like to compare (e.g.
NOTE PingPongController_v1 and PingPongController_v2 ). Then select the menu View |
Compare Two Files, and you’ll see the source code of these files next to each other with
highlighted differences.

Let’s add to the PingPongControler a method handler for the key-released events. The first very simple
version of the PingPongControler is shown next. The goal is to see that the controller receives the keyboard
events and can recognize the keys pressed by the player.

JAVA
package pong;

import [Link];
import [Link];

public class PingPongController {

public void keyReleasedHandler(KeyEvent event){

KeyCode keyCode = [Link]();


[Link]("You pressed " + keyCode);
}
}

The event handler method just extracts the key code from the KeyEvent object provided by the Java runtime
and prints it. For example, after running the PingPong class and pressing the up and down arrows, n, q, and s
keys, the console output should look like this:

HTML
You pressed UP
You pressed DOWN
You pressed N
You pressed Q
You pressed S

The KeyCode in PingPongController is not a class or an interface, but a special Java construct called
enum described next.

13.3.2. The enum Type

[Link] 252/303
22/03/2025, 18:48 Programação Java para crianças

Our controller class declares a variable of type KeyCode , which is neither a class nor an interface. It’s a special
Java data type enum used for declaring a bunch of pre-defined constants that never change. For example, you
can declare a new enum type day-of-the-week:

JAVA
public enum Day {
SUNDAY, MONDAY, TUESDAY, WEDNESDAY,
THURSDAY, FRIDAY, SATURDAY
}

The following class GreetTheDay illustrates the use of the enum Day :

JAVA
public class GreetTheDay {

public static void main(String[] args) {

greet([Link]);
}

static void greet(Day day){


switch (day) {
case MONDAY:
[Link]("The week begins");
break;
case SATURDAY:
case SUNDAY:
[Link]("Hello Weekend!");
break;
default:
[Link]("Hello Midweek");
break;
}
}
}

The method greet expects to receive one of the Day values as an argument. Our main method wants to greet
Saturday, and if you run the program GreetTheDay it’ll print Hello Weekend!.

If you’ll open the online documentation ([Link] for


KeyCode you’ll find there the declarations of all possible keyboard keys.

13.3.3. Preparing to Process the Keys S, Q, and N


Now we’ll add a switch statement to the controller to invoke the method that corresponds to the pressed key.
Let’s not worry about implementing the application logic just yet. We want to make sure that the program
invokes the correct method for each key.

[Link] 253/303
22/03/2025, 18:48 Programação Java para crianças

JAVA
package pong;

import [Link];
import [Link];
import [Link];

public class PingPongController {

public void keyReleasedHandler(KeyEvent event){

KeyCode keyCode = [Link]();

switch (keyCode){
case UP:
process_key_Up();
break;
case DOWN:
process_key_Down();
break;
case N:
process_key_N();
break;
case Q:
[Link](); // Terminate the app
break;
case S:
process_key_S();
break;
}
}

private void process_key_Up() {


[Link]("Processing the Up key");
}

private void process_key_Down() {


[Link]("Processing the Down key");
}

private void process_key_N() {


[Link]("Processing the N key");
}

private void process_key_S() {


[Link]("Processing the S key");
}
}

The switch statement checks the value of enum KeyCode and calls the corresponding method which just
prints a hard-coded message. We’ll implement them shortly, but the Q-key in the above PingPongController
is fully functional. When the user presses the Q-key, the program invokes the method exit on the class

[Link] 254/303
22/03/2025, 18:48 Programação Java para crianças

Platform , which terminates the program.

13.4. Step 3: Moving the Paddle


Now let’s teach the keys Up and Down to move the Kid’s paddle vertically. Pressing the Up-arrow should move
the Kid’s paddle several pixels up according to the predefined moving increment. Pressing the Down-arrow
should move the paddle down. We’ll declare an movement increment as a final variable in
PingPongController :

JAVA
final int PADDLE_MOVEMENT_INCREMENT = 6;

Pressing the key once will change the vertical position of the paddle by 7 pixels. Seven is not a magical number,
and you can use any other integer here.

The new version of the controller will use the @FXML annotations to inject the references to the GUI
components. To update the position of the kid’s paddle on the GUI we’ll use data binding explained in Chapter
8. We’ll also add the method initialize that is invoked by the Java runtime once when the controller object
is created. Finally, we’ll write the code in the methods process_key_Down and process_key_Up to move
the kid’s paddle vertically.

In JavaFX the x and y coordinates of the top left corner of the stage have zero values. x-coordinate increases
from left to right, and the y-coordinate increases from top to bottom. The following image shows how x and y
coordinates change if a ping-pong table has the width of 400 pixels and the height of 250:

[Link] 255/303
22/03/2025, 18:48 Programação Java para crianças

No nosso jogo, as pás podem se mover apenas para cima ou para baixo, então, dependendo da tecla pressionada,
mudaremos o valor da propriedade layoutY da pá direita, o que a moverá no palco de acordo. Veja como ela
PingPongController ficará agora:

[Link] 256/303
22/03/2025, 18:48 Programação Java para crianças

JAVA
package pong;

import [Link];
import [Link];
import [Link];
import [Link];
import [Link];
import [Link];
import [Link];
import [Link];

public class PingPongController {

final int PADDLE_MOVEMENT_INCREMENT = 6;

DoubleProperty currentKidPaddleY =
new SimpleDoubleProperty(); (1)

double allowedPaddleTopY; (2)


double allowedPaddleBottomY;

@FXML Rectangle table; (3)


@FXML Rectangle compPaddle;
@FXML Rectangle kidPaddle;
@FXML Circle ball;

public void initialize() {

[Link]([Link]()); (4)
[Link]().bind(currentKidPaddleY);

allowedPaddleTopY = PADDLE_MOVEMENT_INCREMENT; (5)


allowedPaddleBottomY = [Link]() - [Link]() -
PADDLE_MOVEMENT_INCREMENT;

public void keyReleasedHandler(KeyEvent event){

KeyCode keyCode = [Link]();

switch (keyCode){
case UP:
process_key_Up();
break;
case DOWN:
process_key_Down();
break;
case N:
process_key_N();
break;
case Q:
[Link](); // Terminate the application

[Link] 257/303
22/03/2025, 18:48 Programação Java para crianças

break;
case S:
process_key_S();
break;
}
}

private void process_key_Up() { (6)

if ([Link]() > allowedPaddleTopY) {


[Link]([Link]() - PADDLE_MOVEMENT_INCREMENT);
}
}

private void process_key_Down() { (7)

if ([Link]()< allowedPaddleBottomY) {
[Link]([Link]() + PADDLE_MOVEMENT_INCREMENT);
}
}

private void process_key_N() {


[Link]("Processing the N key");
}

private void process_key_S() {


[Link]("Processing the S key");
}
}

1. Declarando a propriedade currentKidPaddleY que será vinculada à propriedade layoutY do remo da


criança.

2. O Kid estará movendo a raquete para cima e para baixo, mas não queremos permitir que a raquete saia dos
limites da mesa. A variável allowedPaddleTopY armazenará a coordenada y máxima permitida para o
topo da raquete, e allowedPaddleBottomY terá a coordenada y máxima permitida para a parte inferior da
raquete.

3. Usando a @FXML tag, injetamos as referências aos componentes da GUI definidos em [Link] nas
variáveis ​do controlador.

4. O método initialize no controlador é chamado apenas uma vez e é o lugar certo para inicializar
variáveis ​importantes. Primeiro, inicializamos a propriedade currentKidPaddleY , com o valor da
layoutY propriedade da raquete direita (o componente kidPaddle tem um atributo layoutY="98.0" no
arquivo [Link] ). Então, vinculamos currentKidPaddleY à layoutY propriedade do componente
GUI kidPaddle.

5. Aqui definimos os limites para os movimentos da raquete. Definimos a variável


allowedPaddleTopY=PADDLE_MOVEMENT_INCREMENT para garantir que, se a Criança continuar
pressionando a seta para cima, a raquete nunca cruzará a borda superior da mesa. A restrição inferior

[Link] 258/303
22/03/2025, 18:48 Programação Java para crianças

allowedPaddleBottomY é calculada subtraindo a altura da raquete e PADDLE_MOVEMENT_INCREMENT da


altura da mesa.
6. O método process_key_Up obtém a coordenada y atual da borda superior da raquete e, se estiver longe o
suficiente do topo da mesa, o código diminui o valor da propriedade currentKidPaddleY em
PADDLE_MOVEMENT_INCREMENT . Como currentKidPaddleY está vinculado à layoutY propriedade do
componente GUI kidPaddle , este último sobe no palco. O movimento para se o
currentKidPaddleY valor for maior que allowedPaddleTopY . Lembre-se, a coordenada y aumenta de
cima para baixo, então as coordenadas y mais altas significam que está fisicamente mais baixo no palco.

7. O método process_key_Down funciona de forma semelhante, process_key_Up mas garante que a


raquete não cruzará a borda inferior da mesa.
Agora nosso controlador sabe como mover a raquete do Kid. O próximo desafio é aprender como mover a bola.

13.5. Passo 4. Movendo a bola


Vamos começar a implementar o passo 4 da estratégia do jogo calculando a posição inicial e pintando a bola
dependendo da localização da raquete direita. Quando o usuário pressiona a tecla S, precisamos sacar a bola da
posição onde a raquete direita está localizada no momento. Inicialmente, ela está localizada no meio da mesa,
mas o usuário pode movê-la para cima ou para baixo antes de sacar a bola.

A bola é representada pela forma Circle . Da matemática escolar, você deve lembrar que um círculo é
representado pelas coordenadas do centro e do raio. No JavaFX, as propriedades correspondentes da classe
Circle são chamadas centerX , centerY , e radius . Quando o Circle é colocado em um layout, seu
centro obtém as propriedades correspondentes layoutX e layoutY . Ao alterar as coordenadas do centro,
podemos mover a bola pelo palco. Nossa bola é definida no arquivo [Link] assim:

XML
<Circle fx:id="ball" fill="#ff1f35" layoutX="191.0" layoutY="123.0" radius="9.0" stroke="BLACK"
strokeType="INSIDE" />

Mas por que a tag acima não <Circle> inclui centerX and centerY ? Na verdade, podemos e iremos
substituir os atributos layoutX and layoutY por centerX and centerY porque usamos o Group contêiner
que não faz parte de nenhum outro layout (por exemplo, BorderPane or GridPane ). O JavaFX permite que
você crie cenas complexas que podem alterar dinamicamente os tamanhos e reposicionar seus componentes
filhos. Portanto, as coordenadas x e y de um componente em relação a um layout podem não ser as mesmas que
as coordenadas na cena. Por exemplo, a coordenada x real de um componente pode ser calculada adicionando a
coordenada x de um contêiner dentro de uma cena e a coordenada x do componente dentro de um contêiner.

Vamos modificar os atributos da tag <Circle> para que fique assim:

XML
<Circle fx:id="ball" fill="#ff1f35" centerX="191.0" centerY="123.0" radius="9.0" stroke="BLACK"
strokeType="INSIDE" />

[Link] 259/303
22/03/2025, 18:48 Programação Java para crianças

13.5.1. Movendo a bola para a raquete direita


Como a bola estará em movimento, monitoraremos seu centro nas novas propriedades ballCenterX e
ballCenterY :

JAVA
DoubleProperty ballCenterX = new SimpleDoubleProperty();
DoubleProperty ballCenterY = new SimpleDoubleProperty();

No método, initialize definiremos os valores iniciais dessas propriedades para as coordenadas centrais da
bola. Também vincularemos as propriedades acima ao centro do Circle , então alterar ballCenterX e
ballCenterY mudará automaticamente a localização da bola na cena:

JAVA
[Link]([Link]());
[Link]([Link]());

[Link]().bind(ballCenterX);
[Link]().bind(ballCenterY);

Vamos colocar a bola na posição atual da raquete da criança. No método, process_key_S ajustaremos a
centerY coordenada da bola. Nosso controlador tem a variável currentKidPaddleY que lembra a
coordenada y atual do topo da raquete da criança. Então, se adicionarmos à currentKidPaddleY metade da
altura da raquete, obteremos a coordenada y do centro da raquete. A centerX coordenada será a mesma da
layoutX raquete da criança. A nova versão do método process_key_S ficará assim:

JAVA
private void process_key_S() {

[Link]([Link]() + [Link]()/2);
[Link]([Link]());
}

Executei o PingPong aplicativo, movi a raquete para cima clicando na tecla de seta várias vezes e, em seguida,
pressionei a tecla S. A bola obedientemente se moveu para a posição atual da raquete direita:

[Link] 260/303
22/03/2025, 18:48 Programação Java para crianças

13.5.2. Servindo a bola horizontalmente


The ball is ready to start moving now. To make the movement smooth, we’ll use the class
[Link] that allows us to change the values of the GUI component’s properties over a
time interval. Similarly to a movie, the animation is a set of frames that are displayed over a specific period of
time. Each frame is a snapshot of a GUI component at a certain state. For the ball movement we’ll declare the
variable timeline of the type TimeLine , which we’ll use to display a set of snapshots of a ball at different
positions along its trajectory.

Each frame is represented by a class KeyFrame . Each snapshot is represented by the class KeyValue . Let’s
write a method moveTheBall that will move the ball horizontally all the way to the left until the centerX will
become equal to zero. If we change only the centerX property of the Circle , it’ll be moving horizontally.

[Link] 261/303
22/03/2025, 18:48 Programação Java para crianças

JAVA
Timeline timeline;

private void moveTheBall(){

timeline = new Timeline(); (1)


[Link](1);

KeyValue keyValue = new KeyValue(ballCenterX, 0); (2)


KeyFrame keyFrame = new KeyFrame(new Duration(1000), keyValue); (3)

[Link]().add(keyFrame); (4)

[Link](); // (5)
}

1. First we create an instance of the Timeline object and invoke the setCycleCount requesting that the
animation will be done only once. In this example we could have declared the variable timeline inside
the method, but keeping this variable on the class level will allow me to programatically stop the animation
that I’ll demonstrate in the next version of the method moveTheBall .

2. Then we’ll create the KeyValue object to specify which changing value to display in frames. In this case
we want the animation to change the x-coordinate of the ball center from its current value ballCenterX to
zero.

3. We want the KeyFrame to reach the target (change the centerX specified in KeyValue from the current
value to zero) over a period of 1000 milliseconds. The smaller the number, the faster the ball will move. The
number of frames will be automatically calculated based on the duration and the target position of the ball.

4. Adding the our KeyFrame object to the timeline completes the preparations.

5. The method play will play the timeline .

Now if you’ll invoke the method moveTheBall from process_key_S the ball will move to the left and stop
there. Here’s what I’ve got after starting the game and pressing the S-key:

[Link] 262/303
22/03/2025, 18:48 Programação Java para crianças

Our ball is not smart enough to notice that there was a left paddle on its way and went right through it. We’ll take
care of the GUI component collisions a bit later.

Depending on the provided duration, the Timeline object will calculate how many snapshots (key frames) to
create while the KeyValue is changing to reach the target. The Timeline class has several overloaded
constructors ([Link] and one of
them allows you to specify the frames per second for the animation.

A KeyFrame classe também tem vários construtores sobrecarregados


([Link] , e um deles permite que
você especifique a duração, o manipulador de eventos para o ActionEvent e valores de chave opcionais. O
manipulador para o ActionEvent pode ser implementado como uma expressão lambda.

Na versão a seguir do método, moveTheBall escreveremos o código para avançar a bola nos incrementos
especificados. Também usaremos construtores diferentes de TimeLine e KeyFrame :

[Link] 263/303
22/03/2025, 18:48 Programação Java para crianças

JAVA
final int BALL_MOVEMENT_INCREMENT = 5;

private void moveTheBall(){

KeyFrame keyFrame = new KeyFrame(new Duration(10), (1)


event -> {

if ([Link]() > BALL_MOVEMENT_INCREMENT) { (2)

[Link]([Link]() - BALL_MOVEMENT_INCREMENT); (3)

} else {
[Link](); (4)
}
}
);

timeline = new Timeline(keyFrame); (5)


[Link]([Link]);
[Link]();

1. O primeiro argumento do construtor é o Duration objeto, mas dessa vez ele tem um significado diferente
do que na versão anterior do moveTheBall . O valor 10 significa executar o código do manipulador de
eventos (a expressão lambda) a cada 10 milissegundos.

2. A expressão lambda começa com a verificação se o valor atual da coordenada x do centro da bola é maior
que o valor em BALL_MOVEMENT_INCREMENT para garantir que a bola não cruzará a borda esquerda e
permanecerá nas coordenadas 0. Para tornar nosso jogo mais realista, deixaremos a bola sair da mesa na
próxima versão do moveTheBall .

3. Decrementa o valor de ballCenterX by BALL_MOVEMENT_INCREMENT . Devido à vinculação, isso


moverá a bola na GUI.

4. Pare a animação se a bola cair da mesa no próximo movimento.

5. Crie o Timeline usando nosso KeyFrame e reproduza. Neste caso, solicitei reproduzir a animação
indefinidamente porque não quero calcular quantos movimentos seriam necessários para atingir a posição
alvo. Vou parar a animação manualmente de qualquer maneira, conforme explicado na etapa 4.

13.5.3. Servindo a bola em direções aleatórias


O jogo que serve a bola horizontalmente é bem chato, então vamos mudar não só a coordenada x, mas também a
y enquanto a bola está se movendo. Para adicionar um pouco de diversão, vamos mudar a coordenada y de
forma aleatória, para que cada saque envie a bola em uma direção diferente. Vamos criar uma máquina de saque
de bola.

[Link] 264/303
22/03/2025, 18:48 Programação Java para crianças

Se o usuário moveu a raquete para a metade superior da mesa, a bola deve estar se movendo horizontalmente ou
para baixo. Se a bola for sacada da metade inferior, a bola pode se mover horizontalmente ou para cima. Para
saber a coordenada y do centro da mesa, declararemos a double variável centerTableY e definiremos seu
valor no método initialize assim:

JAVA
centerTableY = [Link]()/2;

Conforme a bola se move, o valor modificado da coordenada y do centro da bola será atribuído à propriedade
ballCenterY . A versão a seguir do método moveTheBall implementa os serviços aleatórios de bola.

JAVA
private void moveTheBall(){

Random randomYGenerator = new Random();


double randomYincrement = [Link](BALL_MOVEMENT_INCREMENT);
(1)

final boolean isServingFromTop = ([Link]() <= centerTableY)?true:false;


(2)

KeyFrame keyFrame = new KeyFrame(new Duration(10), event -> {

if ([Link]() >= -20) { (3)

[Link]([Link]() - BALL_MOVEMENT_INCREMENT);

if (isServingFromTop) { (4)
[Link]([Link]() + randomYincrement);

} else {
[Link]([Link]() + randomYincrement);
}

} else {
[Link]();

});

timeline = new Timeline(keyFrame);


[Link]([Link]);

[Link]();

[Link] 265/303
22/03/2025, 18:48 Programação Java para crianças

1. Criamos uma instância da classe [Link] . Esta classe tem métodos para gerar números
aleatórios de diferentes tipos. Invocar o método nextInt gera um número inteiro aleatório no intervalo
entre zero e o valor do argumento do método. Decidi usar o valor de BALL_MOVEMENT_INCREMENT como
um limite superior. Este número aleatório será usado como um incremento para a coordenada y da bola em
movimento.

2. Usando o operador condicional (conforme explicado no Capítulo 4), definimos a variável


isServingFromTop como true se a raquete direita estiver localizada na metade superior da mesa, ou como
false se a raquete estiver na metade inferior.

3. Na versão anterior do método moveTheBall , mantínhamos a bola na mesa quando ela atingia a borda
esquerda da mesa. Agora, deixaremos a bola cair da mesa. Este -20 é apenas um número arbitrário -
paramos o movimento da bola depois que ela se moveu 20 pixels além da borda esquerda da mesa. Na
versão final do jogo, habilitaremos o movimento para a raquete esquerda e, às vezes, ela fará a bola quicar
de volta.

4. Se isServingFromTop for verdade, estamos aumentando a coordenada y do centro da bola em


randomYincrement , caso contrário, estamos diminuindo na mesma quantidade. Agora, a bola será sacada
de forma imprevisível e frequentemente cairá da mesa cruzando a borda superior ou inferior da mesa. Eu
tirei a seguinte captura de tela quando a bola em movimento estava prestes a cruzar a borda inferior da
mesa.

[Link] 266/303
22/03/2025, 18:48 Programação Java para crianças

13.6. Etapa 5: Movendo o Paddle do Computador


Quando a bola é sacada, o Computador precisa mover sua raquete na direção certa para quicar a bola. Esta é uma
tarefa bem fácil, já que o computador sabe que se a raquete do Garoto sacar de cima, a bola se moverá para
baixo, e se a bola for sacada de baixo, ela se moverá para cima. Então, no momento em que a bola for sacada, a
raquete do computador também deve começar a se mover.

Primeiro, declararemos a propriedade currentComputerPaddleY para manter o controle da coordenada y da


raquete do Computador. Também precisaremos armazenar a coordenada y inicial da raquete do Computador,
porque em cada bola sacando essa raquete deve estar no meio do lado esquerdo da mesa:

JAVA
DoubleProperty currentComputerPaddleY = new SimpleDoubleProperty();

double initialComputerPaddleY;

No método, initialize vincularemos currentComputerPaddleY a layoutY propriedade do


Rectangle que representa a raquete do computador:

JAVA
initialComputerPaddleY = [Link]();

[Link](initialComputerPaddleY);
[Link]().bind(currentComputerPaddleY);

A nova versão do método moveTheBall iniciará o movimento da raquete do Computador na direção correta
assim que a bola for sacada.

[Link] 267/303
22/03/2025, 18:48 Programação Java para crianças

JAVA
private void moveTheBall(){

Random randomYGenerator = new Random();


double randomYincrement = [Link](BALL_MOVEMENT_INCREMENT);

final boolean isServingFromTop = ([Link]() <= centerTableY)?true:false;

KeyFrame keyFrame = new KeyFrame(new Duration(10), event -> {

if ([Link]() >= -20) {

[Link]([Link]() - BALL_MOVEMENT_INCREMENT);

if (isServingFromTop) {
[Link]([Link]() + randomYincrement);

[Link]( [Link]() + 1); (1)

} else {
[Link]([Link]() - randomYincrement);

[Link]([Link]() - 1); (2)


}

} else {
[Link]();

[Link](initialComputerPaddleY); (3)
}
});

timeline = new Timeline(keyFrame);


[Link]([Link]);

[Link]();
}

1. Se a bola foi sacada de cima, mova a raquete do computador um pixel para baixo em cada quadro.

2. Se a bola foi sacada da metade inferior da mesa, mova a raquete do computador um pixel para cima em cada
quadro.

3. Quando a bola parar de se mover, retorne a raquete do computador para a posição inicial no meio do lado
esquerdo da mesa.

13.7. Etapa 6: quicando a bola


Não há garantia de que a raquete do Computador avançará para uma posição para quicar a bola. Nosso jogo de
Ping-Pong não implementa o algoritmo que ajusta o movimento da raquete do Computador com base na
trajetória do movimento da bola. Mas se a bola acidentalmente entrar em contato com a raquete, precisamos
quicar a bola e enviá-la da esquerda para a direita.

[Link] 268/303
22/03/2025, 18:48 Programação Java para crianças

Cada componente JavaFX GUI é uma subclasse de a Node , que tem uma propriedade especial
boundsInParent . É um retângulo invisível que encapsula o componente quando ele é colocado dentro de um
layout. Então nossa bola e pás estão dentro desses retângulos invisíveis também. Quando a bola ou pás estão
sendo movidas, as coordenadas de suas boundsInParent propriedades estão sendo recalculadas. Se esses
retângulos invisíveis da bola e da pá se cruzam, podemos dizer que houve um contato. O método
checkForBallPaddleContact retorna true se houve um contato, e false se não.

JAVA
private boolean checkForBallPaddleContact(){

if ([Link]([Link]())){
return true;
} else {
return false;
}
}

Devemos chamar esse método de cada quadro na linha do tempo que iniciamos no método moveTheBall .
Após essa verificação de contato com o método, moveTheBall ele ficará assim:

[Link] 269/303
22/03/2025, 18:48 Programação Java para crianças

JAVA
private void moveTheBall(){

Random randomYGenerator = new Random();


double randomYincrement = [Link](BALL_MOVEMENT_INCREMENT);

final boolean isServingFromTop = ([Link]() <= centerTableY)?true:false;

KeyFrame keyFrame = new KeyFrame(new Duration(10), event -> {


if ([Link]() >= -20) {

[Link]([Link]() - BALL_MOVEMENT_INCREMENT);

if (isServingFromTop) {
[Link]([Link]() + randomYincrement);

[Link]( [Link]() + 1);

} else {
[Link]([Link]() - randomYincrement);

[Link]([Link]() - 1);
}

if (checkForBallPaddleContact()){

[Link](); (1)
[Link](initialComputerPaddleY);

bounceTheBall(); (2)
};

} else {
[Link]();
[Link](initialComputerPaddleY);
}
});

timeline = new Timeline(keyFrame);


[Link]([Link]);

[Link]();
}

1. Se houver contato entre a bola e a raquete, precisamos parar de jogar a raquete atual timeline e colocar a
raquete do computador na posição inicial.

2. Então precisaremos chamar o método bounceTheBall , que escreveremos a seguir.

De acordo com o passo 6 da nossa estratégia de jogo, o computador só pode sacar a bola horizontalmente, então
escrever o bounceTheBall método parece algo bem simples de se fazer. Já escrevemos uma versão do
moveTheBall método que envia a bola horizontalmente da direita para a esquerda, então reverter a direção do

[Link] 270/303
22/03/2025, 18:48 Programação Java para crianças

movimento da bola deve ser fácil.


Mas e se o Kid mover sua raquete para rebater a bola de volta? OK, então precisamos verificar se a bola também
entra em contato com a raquete do Kid. Podemos reutilizar o método checkForBallPaddleContact para
isso? Não em sua forma atual, porque ele foi escrito especificamente para a raquete do computador. Certamente
podemos escrever um método semelhante para a raquete do Kid e ter dois métodos quase idênticos, mas é
melhor reescrever checkForBallPaddleContact para funcionar para ambas as raquetes.

No jargão do programador, reescrever um código existente e funcional é chamado de refatoração . Então, vamos
refatorar o método checkForBallPaddleContact fornecendo o paddle como um argumento. Aqui está a
versão refatorada que pode ser usada para ambos os paddles:

JAVA
private boolean checkForBallPaddleContact(Rectangle paddle){

if ([Link]([Link]())){
return true;
} else {
return false;
}
}

Assim, o método moveTheBall verificaria o contato com a pá do computador da seguinte forma:

JAVA
checkForBallPaddleContact(compPaddle);

Para verificar o contato da bola com a raquete da criança, você escreveria esta linha:

JAVA
checkForBallPaddleContact(kidPaddle);

Agora vamos escrever o método bounceTheBall , que deve ser muito semelhante a moveTheBall . A bola
deve se mover da esquerda para a direita, se você estiver diminuindo a coordenada x em moveTheBall ,
precisará diminuí-la agora. Se você estiver parando o jogo onde a coordenada da bola era menor que -20, agora
ela precisa ser maior que a largura da mesa mais 20. Eu poderia refatorar o método moveTheBall para
introduzir esses valores como argumentos de métodos, mas vamos mantê-lo como um pequeno projeto para
você. Contanto que você entenda como o código funciona, você deve ser capaz de fazê-lo sozinho. Aqui está o
código do método bounceTheBall :

[Link] 271/303
22/03/2025, 18:48 Programação Java para crianças

JAVA
private void bounceTheBall() {

double theBallOffTheTableX = [Link]() + 20; (1)

KeyFrame keyFrame = new KeyFrame(new Duration(10), event -> {

[Link](ballCenterX);
if ([Link]() < theBallOffTheTableX) {

[Link]([Link]() + BALL_MOVEMENT_INCREMENT); (2)

if (checkForBallPaddleContact(kidPaddle)){ (3)
[Link]();
moveTheBall();
};

} else {
[Link]();
}

});

timeline = new Timeline(keyFrame);


[Link]([Link]);

[Link]();

1. A bola deve parar seu movimento quando sua coordenada x estiver 20 pixels à direita da mesa.

2. Avance a bola para a direita até que sua coordenada x atinja o valor de theBallOffTheTableX .

3. Enquanto o Computador quica a bola, a Criança pode pressionar as teclas de seta para cima e para baixo
para parar a bola. Se a bola entrar em contato com a raquete da Criança, chamamos o
moveTheBall método para iniciar o movimento aleatório para a esquerda novamente.

A funcionalidade básica do jogo é implementada além de exibir a pontuação do jogo e começar o novo jogo
quando um dos jogadores obtém 21 pontos. Vou deixar essa parte para você implementar por conta própria.

Tenho mostrado e explicado vários fragmentos de código do PingPongController enquanto implementamos


a estratégia do jogo, um passo de cada vez. Agora, vou apenas mostrar como o código da
PingPongConroller classe se parece, sem nenhuma explicação adicional. Você deve conseguir ler e entender
o código.

[Link] 272/303
22/03/2025, 18:48 Programação Java para crianças

JAVA
package pong;

import [Link];
import [Link];
import [Link];
import [Link];
import [Link];
import [Link];
import [Link];
import [Link];
import [Link];
import [Link];
import [Link];

import [Link];

// This code implements 6 steps of the Game strategy

public class PingPongController {

final int PADDLE_MOVEMENT_INCREMENT = 7;


final int BALL_MOVEMENT_INCREMENT = 3;

double centerTableY;

DoubleProperty currentKidPaddleY = new SimpleDoubleProperty();


DoubleProperty currentComputerPaddleY = new SimpleDoubleProperty();
double initialComputerPaddleY;

DoubleProperty ballCenterX = new SimpleDoubleProperty();


DoubleProperty ballCenterY = new SimpleDoubleProperty();

double allowedPaddleTopY;
double allowedPaddleBottomY;

Timeline timeline;

@FXML
Rectangle table;
@FXML Rectangle compPaddle;
@FXML Rectangle kidPaddle;
@FXML Circle ball;

public void initialize()


{

[Link]([Link]());
[Link]().bind(currentKidPaddleY);

[Link]([Link]());
[Link]([Link]());

[Link] 273/303
22/03/2025, 18:48 Programação Java para crianças

[Link]().bind(ballCenterX);
[Link]().bind(ballCenterY);

initialComputerPaddleY = [Link]();
[Link](initialComputerPaddleY);
[Link]().bind(currentComputerPaddleY);

allowedPaddleTopY = PADDLE_MOVEMENT_INCREMENT;
allowedPaddleBottomY = [Link]() - [Link]() -
PADDLE_MOVEMENT_INCREMENT;

centerTableY = [Link]()/2;
}
public void keyReleasedHandler(KeyEvent event){

KeyCode keyCode = [Link]();

switch (keyCode){
case UP:
process_key_Up();
break;
case DOWN:
process_key_Down();
break;
case N:
process_key_N();
break;
case Q:
[Link](); // Terminate the application
break;
case S:
process_key_S();
break;
}
}

private void process_key_Up() {

if ([Link]() > allowedPaddleTopY) {


[Link]([Link]() - PADDLE_MOVEMENT_INCREMENT);
}
}

private void process_key_Down() {

if ([Link]()< allowedPaddleBottomY) {
[Link]([Link]() + PADDLE_MOVEMENT_INCREMENT);
}
}

private void process_key_N() {


[Link]("Processing the N key");
}

[Link] 274/303
22/03/2025, 18:48 Programação Java para crianças

private void process_key_S() {

[Link]([Link]() + [Link]()/2);
[Link]([Link]());

moveTheBall();
}

private void moveTheBall(){

Random randomYGenerator = new Random();


double randomYincrement = [Link](BALL_MOVEMENT_INCREMENT);

final boolean isServingFromTop = ([Link]() <= centerTableY)?true:false;

KeyFrame keyFrame = new KeyFrame(new Duration(10), event -> {

if ([Link]() >= -20) {

[Link]([Link]() - BALL_MOVEMENT_INCREMENT);

if (isServingFromTop) {
[Link]([Link]() + randomYincrement);

[Link]( [Link]() + 1);

} else {
[Link]([Link]() - randomYincrement);

[Link]([Link]() - 1);
}

if (checkForBallPaddleContact(compPaddle)){
[Link]();
[Link](initialComputerPaddleY);
bounceTheBall();
};

} else {
[Link]();

[Link](initialComputerPaddleY);
}
});

timeline = new Timeline(keyFrame);


[Link]([Link]);

[Link]();
}

private boolean checkForBallPaddleContact(Rectangle paddle){

if ([Link]([Link]())){

[Link] 275/303
22/03/2025, 18:48 Programação Java para crianças

return true;
} else {
return false;
}
}

private void bounceTheBall() {

double theBallOffTheTableX = [Link]() + 20;

KeyFrame keyFrame = new KeyFrame(new Duration(10), event -> {

if ([Link]() < theBallOffTheTableX) {

[Link]([Link]() + BALL_MOVEMENT_INCREMENT);

if (checkForBallPaddleContact(kidPaddle)){
[Link]();
moveTheBall();
};

} else {
[Link]();
}

});

timeline = new Timeline(keyFrame);


[Link]([Link]);

[Link]();
}
}

13.8. Projeto: Exibindo a pontuação do jogo


O objetivo deste projeto é manter o controle e exibir a pontuação do jogo. Vou apenas mostrar como imprimir a
pontuação no console do sistema, mas você precisará pesquisar como exibir o texto diretamente na mesa de
pingue-pongue.

Se o Kid sacasse a bola horizontalmente, ele ou ela marcaria um ponto quando a bola saísse da mesa e sua
coordenada x fosse menor que zero. Mas como a bola é sacada em uma direção aleatória, ela pode sair da mesa
cruzando as bordas superior ou inferior da mesa. Nesse caso, o Kid perde o ponto. Quando o método
moveTheBall para de reproduzir a linha do tempo, a coordenada x da bola é definitivamente menor que zero,
então você precisa verificar a coordenada y da bola.

Se a coordenada y da bola tiver um valor entre zero e a altura da mesa, você pode assumir que a bola cruzou a
borda esquerda da mesa e o Kid marcou um ponto. Caso contrário, a bola cruzou as bordas superior ou inferior
da mesa e o Kid deve perder o ponto.

[Link] 276/303
22/03/2025, 18:48 Programação Java para crianças

O computador marca um ponto se quicar a bola e ela cruzar a borda direita da mesa.

Você precisa declarar duas variáveis ​de classe para acompanhar as pontuações do computador e da criança:

JAVA
int computerScore;
int kidScore;

Você também precisará escrever um método updateScore e invocá-lo toda vez que a linha do tempo parar de
tocar (em ambos os métodos: moveTheBall e bounceTheBall ). O método updateScore pode se parecer
com isto:

JAVA
private void updateScore(){

if ([Link]() > [Link]()){


// Computer bounced the ball and the Kid didn't hit it back
computerScore ++;
} else if ([Link]() > 0 && [Link]() <= [Link]()){
// The Kid served the ball and Computer didn't hit it back
kidScore++;
} else{
// The Kid served the ball off the table
computerScore++;
}

[Link]("Computer: " + computerScore + ", Kid: " + kidScore);


}

O código que vem com o livro tem esta versão do método updateScore implementada. Seu objetivo é exibir a
pontuação em uma fonte agradável no canto inferior esquerdo da tabela. Você pode aprender como trabalhar com
as Text classes Font e estudando o tutorial da Oracle "Working with Text in JavaFX Applications"
([Link] .

Não se esqueça de implementar a funcionalidade Start New Game. Você precisará escrever um método
newGame , onde você deve zerar as pontuações e colocar as raquetes e a bola nas posições iniciais. :toc-
placement!: :imagesdir: .

[Link] 277/303
22/03/2025, 18:48 Programação Java para crianças

14. Git para crianças


Então você escreveu um ótimo aplicativo, e ele funcionou como esperado. Algum tempo depois, você tem uma
ideia de como torná-lo ainda melhor. Depois de várias horas fazendo alterações no seu código, você notou que o
aplicativo tem novos bugs no código que estava funcionando bem ontem. Mas onde está aquela versão anterior
do código que estava funcionando bem? Você pode desfazer ( reverter ) as últimas alterações que quebraram o
código de trabalho?

Muitos anos atrás, os programadores simplesmente criavam cópias de backup de seus códigos de vez em
quando. Depois de algum tempo, seus discos rígidos teriam várias pastas nomeadas como TicTacToe_Feb_1 ,
TicTacToe_Feb_5 , TicTacToe_Feb_20 e assim por diante. Mas os programadores geralmente trabalham em
equipes, e se Joe e Mary estiverem trabalhando no mesmo aplicativo? Como você pode ter certeza de que os
computadores de Joe e Mary têm a cópia de trabalho do aplicativo com a capacidade de manter o histórico de
alterações de código e retornar a uma versão de trabalho se necessário?

Os programadores usam um software especial chamado Version Control Systems (VCS) que permite manter o
controle de diferentes versões do código-fonte armazenado em repositórios de código-fonte comuns localizados
nos servidores da empresa. Há também instalações especiais de hospedagem na web, onde Joe e Mary podem
manter com segurança o código do aplicativo.

Os desenvolvedores de software fazem alterações em suas cópias locais do código do aplicativo e as testam.
Quando a versão local do aplicativo funciona bem, eles confirmam (salvam) as últimas alterações de código no
repositório de código-fonte. Se Mary tiver confirmado suas alterações, Joe pode verificar o código mais recente
do repositório compartilhado em seu computador. As alterações de Mary serão mescladas com as de Joe em seu
computador.

Agora Joe tem o código mais recente de Mary, mas ela não tem as últimas alterações de código de Joe. Quando
Joe decide fazer commit do seu código mais recente no repositório compartilhado, Mary pode fazer o check-out
deles no computador dela.

Neste capítulo, apresentarei a você um VCS popular chamado Git e ao recurso de hospedagem de código
chamado GitHub. VCS são usados ​por programadores que escrevem código em qualquer linguagem, não apenas
em Java. Na verdade, você pode controlar qualquer arquivo usando o Git e armazená-lo no GitHub ou em outros
hosts. Se seu computador for perdido ou roubado, você sempre poderá recuperar o código puxando -o do
GitHub.

Eu estava usando o Git como um VCS e o GitHub como um repositório compartilhado dos rascunhos de todos
os capítulos deste livro, e você pode encontrá-los no GitHub em [Link]
([Link] .

[Link] 278/303
22/03/2025, 18:48 Programação Java para crianças

Entender como um VCS funciona é muito importante - é por isso que incluí este pequeno tutorial do Git no livro
sobre Java.

14.1. Dois tipos de sistemas de controle de versão


Existem dois tipos de VCS: centralizado e distribuído. Com sistemas centralizados, o repositório de código-fonte
é armazenado em um servidor, que é o único lugar que tem a versão mais recente do aplicativo, bem como todos
os arquivos históricos comprometidos pelos desenvolvedores no passado.

Se Pete, o novo programador, se juntar à equipe, ele precisaria verificar o código mais recente do repositório
central e começar a fazer suas modificações de código em seu computador. Existem muitos VCS centralizados, e
alguns dos mais populares são CVS, SVN e Perforce.

VCS distribuídos armazenam a versão mais recente do código, bem como todos os arquivos históricos no
computador de cada programador. VCS distribuídos populares são Git, Mercurial e Bazaar. Tecnicamente, se
você trabalha sozinho, pode instalar o Git no seu computador e ter seu VCS privado sem usar nenhum servidor
remoto como um repositório compartilhado. Mas, novamente, ter uma cópia extra dos arquivos do seu projeto
em um servidor remoto é sempre uma boa ideia.

Os programadores geralmente trabalham em equipes, então o diagrama a seguir mostra três computadores: um
repositório compartilhado à direita e dois repositórios locais (de Mary e Joe) à esquerda.

[Link] 279/303
22/03/2025, 18:48 Programação Java para crianças

A qualquer momento, cada repositório local armazena o histórico de todas as atualizações feitas por seu
proprietário, bem como atualizações históricas que o proprietário extraiu do repositório compartilhado. Vamos
ver como criar um repositório de código-fonte do seu computador que é gerenciado pelo Git.

14.2. Introdução ao Git


Git é um VCS distribuído gratuito, que você pode baixar e instalar em [Link] ([Link] . Há
uma chance de que seu computador já tenha o Git instalado, e você pode verificar abrindo uma janela de
Comando ou Terminal e digitando o comando git . Se ele imprimir uma lista de comandos Git disponíveis, você
já tem o Git instalado. Mas ainda assim, eu sugeriria instalar a versão mais recente do Git seguindo estas
instruções ([Link] para seu sistema operacional.

Existem várias ferramentas GUI ([Link] para trabalhar com repositórios Git, mas
usaremos uma janela Command ou Terminal para executar todos os comandos. Após a instalação ser concluída,
insira o comando git --version e você verá qual versão do Git usará.

14.2.1. Apresentando-se ao Git


O próximo passo é se apresentar ao Git, fornecendo seu nome e endereço de e-mail. Normalmente, você
executará o programa git seguido pelo nome do comando, que pode ter várias opções que começam com -- ou - .
Para se apresentar ao Git, use o comando config com a opção --global . Foi assim que eu fiz:

[Link] 280/303
22/03/2025, 18:48 Programação Java para crianças

HTML
git config --global [Link] ”Yakov Fain"
git config --global [Link] "yakovfain@[Link]"

Se você quiser usar diferentes nomes de usuário e e-mails para diferentes projetos,
OBSERVAÇÃO
execute os comandos acima no diretório do projeto sem a opção --global .

Mais tarde, quando você abrir uma conta no GitHub, precisará usar o mesmo e-mail que usou com o comando
config acima. O Git está pronto para gerenciar seus projetos. Agora, vamos criar um repositório Git para um
projeto simples e aprender como trabalhar com ele.

14.3. Criando um novo repositório Git


Para fins de ilustração, criarei uma nova pasta chamada gitIntro e copiarei para lá os arquivos [Link] ,
[Link] e [Link] do Capítulo 3. Então, abrirei a janela Terminal no meu MacBook (usuários do
Windows abrem a janela Command) e criarei um novo repositório Git digitando o comando git init . O conteúdo
da minha pasta gitIntro se parece com o seguinte:

O comando git init criou um diretório oculto chamado .git , que é um repositório Git para meu projeto gitIntro .
Este diretório contém um banco de dados Git (também conhecido como index) que armazenará todas as
alterações que farei em minhas classes Java durante a vida deste projeto.

Você pode começar a usar o Git com seus projetos antigos quando quiser. Basta abrir o diretório de qualquer
projeto existente e executar o comando git init para criar um novo repositório local. Claro, ele não saberá sobre
suas modificações de código anteriores, mas a partir de agora você pode começar a rastreá-las.

14.4. Comandos Git selecionados


O Git tem algumas dezenas de comandos, mas conhecer apenas meia dúzia deles pode ser o suficiente para todas
as atividades do seu projeto. Vou mostrar vários comandos que uso diariamente. Cada comando pode ser emitido
com várias opções. Vou mostrar apenas os comandos básicos para você começar rapidamente com o Git. Para
uma cobertura mais detalhada de todos os recursos e comandos do Git, você precisará estudar a documentação
online ([Link] .

Normalmente, meu trabalho com projetos controlados pelo Git consiste nas seguintes atividades:

[Link] 281/303
22/03/2025, 18:48 Programação Java para crianças

1. Faça alterações em alguns arquivos do projeto.

2. Verifique o status dos arquivos no meu projeto.

3. Altere o status de todos ou alguns dos arquivos modificados para rastreáveis ​executando o comando add .

4. Envie todos os arquivos modificados ou alguns selecionados para o repositório Git local.

5. Envie as alterações para um repositório de código remoto compartilhado.

6. Repita.

14.4.1. O comando status


Eu sempre começo a trabalhar com o Git abrindo meu diretório de projeto e digitando git status para ver quais
arquivos eu modifiquei desde a última vez que fiz commit das alterações no repositório do Git. Vamos fazer isso
no diretório gitIntro . Eu ainda não fiz commit de nenhum arquivo no meu novo repositório de código, e o Git
responderá com o seguinte status:

Observe que a primeira declaração indica que eu trabalho com o branch de código chamado master . Explicarei
como e por que você pode precisar criar branches de código separados um pouco mais tarde, mas por enquanto
não tenho outros branches. Os arquivos não rastreados são exibidos em vermelho, o que significa que eles são
novos no Git ou foram modificados após o último commit no repositório. As alterações feitas nos arquivos não
rastreados não são armazenadas no banco de dados do Git.

14.4.2. O comando add


Adicionar arquivos a um repositório Git é feito pelo comando add , que é tão fácil quanto entender o processo de
adicionar brinquedos a um carrinho de compras em uma loja de brinquedos. Há muitos brinquedos nas
prateleiras, mas você escolhe apenas os selecionados colocando-os em seu carrinho.

[Link] 282/303
22/03/2025, 18:48 Programação Java para crianças

Da mesma forma, você tem muitos arquivos nas pastas do seu projeto, mas pode querer adicionar apenas os
selecionados ao repositório git, por exemplo git add [Link] . Chamamos os arquivos modificados que devem
ser salvos no banco de dados Git trackable . Os arquivos modificados que serão ignorados pelo Git são
chamados untracked .

Se você quiser saber quais opções existem para qualquer comando do Git, basta
OBSERVAÇÃO digitar git --help seguido de um nome de comando, por exemplo, git --help add . Para
sair do modo de ajuda, basta digitar a letra q na janela Command.

Você também pode adicionar todos os arquivos novos ou modificados de uma só vez executando o comando git
add --all . Após executar esse comando, você obterá a seguinte saída:

[Link] 283/303
22/03/2025, 18:48 Programação Java para crianças

Agora todos os meus arquivos Java são exibidos em verde, o que significa que esses arquivos se tornaram
rastreáveis ​e estão prontos para serem confirmados no banco de dados Git.

OBSERVAÇÃO
Você não deve armazenar classes Java compiladas ou JARs nos repositórios de código-fonte. Você pode
informar ao Git quais arquivos ignorar criando um arquivo de texto chamado .gitignore no diretório do
seu projeto. Em seguida, abra-o com um editor de texto simples e adicione os tipos de arquivos que o Git
deve ignorar. Por exemplo, se você adicionar as duas linhas a seguir ao seu arquivo .gitigore , as classes
compiladas e os JARS não serão incluídos no seu banco de dados Git:

HTML
*.class
*.jar

14.4.3. O comando commit


Se continuarmos usando a analogia com a loja de brinquedos, fazer commit é similar a pagar pelos brinquedos
que você colocou no seu carrinho de compras. Mas quando você paga no caixa, você recebe um recibo, certo?
Na mesma nota, quando você emite um comando commit , você precisa escrever um comentário sobre o que
você está fazendo commit. Os programadores fazem múltiplos commits ao longo da vida de cada projeto, e tais
comentários permitem que você acompanhe as mudanças no código. Por exemplo, você pode emitir o seguinte
comando:

HTML
git commit -m "initial commit of the classes Fish, Pet, and PetMaster".

[Link] 284/303
22/03/2025, 18:48 Programação Java para crianças

A opção -m permite escrever uma mensagem curta entre aspas duplas descrevendo o commit.

As "63 inserções" significam que um total de 63 linhas foram inseridas no banco de dados Git.

Se você executar o comando git commit sem nenhuma opção, o Git abrirá um editor de texto onde você deve
digitar uma descrição detalhada das alterações que estão sendo confirmadas. Salvar esse arquivo armazenará
essa descrição no banco de dados do Git.

Digite o comando git status novamente, e você verá a mensagem "nada para confirmar". Não é de se espantar,
acabei de confirmar três arquivos e ainda não os modifiquei novamente.

Agora, deixe-me fazer uma pequena alteração no arquivo [Link] . Atualmente, ele tem o seguinte
conteúdo:

JAVA
public class PetMaster {

public static void main(String[] args) {

String petReaction;
Pet myPet = new Pet();
[Link]();

petReaction = [Link]("Tweet!! Tweet!!");

[Link](petReaction);
[Link]();
}
}

Vou apenas modificar o comentário no topo deste arquivo. Vou mudar o texto para "Criado por Yakov em
28/03/15." Executar o comando git status novamente produzirá uma saída diferente:

[Link] 285/303
22/03/2025, 18:48 Programação Java para crianças

O Git notou que o arquivo [Link] foi alterado, mas até que eu emita o comando add para este arquivo
(ou todos os arquivos), o Git não rastreará as alterações em [Link] . Na configuração da loja de
brinquedos, é uma situação em que um brinquedo é exibido na prateleira, você notou, mas ainda não o adicionou
ao seu carrinho de compras. Os dois comandos a seguir salvarão minha última alteração no banco de dados do
Git:

HTML
git add [Link]
git commit -m "Modified the opening comment in [Link]"

Depois de confirmar todas as alterações, o git status nos informará novamente que não há nada para confirmar e
que o diretório de trabalho está limpo.

Para resumir, temos três classes Java localizadas no diretório de trabalho gitIntro , e o histórico de modificações
e commits é armazenado no diretório .git . Gostaria de lembrar que todo o trabalho que fizemos até agora foi
salvo apenas no repositório de código local.

14.4.4. O comando reset


Aqui está outro cenário a considerar. Acabei de fazer commit das alterações no arquivo [Link] e... fiquei
arrepiado. De repente, percebi que era um erro e queria desfazer o último commit. O arquivo [Link] tem
uma declaração de abertura "Criado por Yakov em 28/03/15.", mas mudei de ideia e não quero revelar meu
nome. Felizmente, o Git armazena todas as alterações de código confirmadas (os deltas) em seu banco de dados.

Vou mostrar como desfazer o último commit e remover as alterações de código em [Link] . Quando
você estiver tentando repetir todos esses comandos, abra o arquivo [Link] e observe o texto do
comentário de abertura, porque ele vai mudar logo após o comando reset :

HTML
git reset HEAD

O comando reset desfará o último commit e abrirá um editor de texto contendo a descrição deste commit
revertido, que pode ter a seguinte aparência:

[Link] 286/303
22/03/2025, 18:48 Programação Java para crianças

HTML
Revert "modified the opening comment in [Link]"

This reverts commit 6e18f1c5f437650c1a115c9875403fb9d081f15d.

# Please enter the commit message for your changes. Lines starting
# with '#' will be ignored, and an empty message aborts the commit.
# On branch master
# Changes to be committed:
# modified: [Link]
#

Você pode alterar este texto para descrever melhor o que foi feito por este comando reset . O Git armazenará a
mensagem salva em seus arquivos de histórico. A sequência de dígitos e letras de 40 caracteres é um código
exclusivo associado a cada commit.

OBSERVAÇÃO Se você quiser ver o histórico de todos os commits, use o comando git log .

Até agora, trabalhamos com o branch padrão chamado master , e agora explicarei para que servem os branches.

14.4.5. Ramificação de código


E se Mary quiser adicionar um novo recurso ao aplicativo, mas ela tem medo de que seu novo código possa
introduzir bugs no aplicativo? Ela não quer modificar o código no qual outros programadores podem confiar. Joe
trabalha para adicionar outro recurso e também quer manter seu código separadamente. Há uma solução para
isso - tanto Mary quanto Joe podem criar seus próprios branches para manter o novo código sendo desenvolvido
separadamente do branch master , que tem um código testado e funcional.

Vamos ver como Mary pode criar um branch de código separado e adicionar um novo método surface à classe
Fish , que atualmente se parece com isto:

JAVA
public class Fish extends Pet {

int currentDepth=0;

public int dive(int howDeep){

currentDepth=currentDepth + howDeep;
[Link]("Diving for " +
howDeep + " feet");
[Link]("I'm at " + currentDepth +
" feet below sea level");

return currentDepth;
}
}

[Link] 287/303
22/03/2025, 18:48 Programação Java para crianças

Mary executará todos os comandos de ramificação no mesmo diretório gitIntro . Primeiro, ela criará sua própria
ramificação chamada mary :

HTML
git branch mary

A nova ramificação mary será criada no banco de dados Git, mas Mary permanecerá na ramificação master até
que ela mude para a nova ramificação executando o comando checkout :

HTML
git checkout mary

O comando git status é nosso amigo. Mary o usa frequentemente para garantir que ela esteja trabalhando no
branch apropriado:

Você também pode imprimir os nomes de todos os branches que existem no seu repositório Git executando o
comando git branch . O branch atual será mostrado em verde e marcado com um asterisco.

Agora Mary adiciona o seguinte método à classe Fish :

JAVA
public void surface(){
[Link]("Going up " + currentDepth + " feet.");
}

Usando a sequência usual de comandos status , add e commit Mary confirma as alterações no branch mary :

[Link] 288/303
22/03/2025, 18:48 Programação Java para crianças

A qualquer momento, o diretório de trabalho terá apenas uma cópia de cada arquivo com o conteúdo que
corresponde ao branch atual. Portanto, a classe Fish do branch mary tem o método surface . Agora Mary
volta para o branch master executando git checkout master e abre o arquivo [Link] - o método surface não
está lá! O Git moveu perfeitamente a versão mais antiga do [Link] de seu banco de dados de volta para o
diretório de trabalho. Aconteceu muito rápido, porque no VCS distribuído o repositório de código completo está
localizado no computador do programador e não há necessidade de fazer nenhuma comunicação pela rede.

Mary testou a nova versão da classe Fish e está pronta para incluí-la no branch master . Usando a terminologia
VCS, ela quer mesclar o código localizado no branch mary no código no branch master . Do branch master ,
Mary executa o seguinte comando merge :

HTML
git merge mary

Veja como pode ficar na janela do Terminal:

[Link] 289/303
22/03/2025, 18:48 Programação Java para crianças

Neste caso, o Git conseguiu mesclar automaticamente duas versões do arquivo [Link] . Mas às vezes as
alterações entram em conflito umas com as outras e é necessária uma edição manual para resolver os conflitos.

14.4.6. Resolução de conflitos


Como Mary era a única programadora trabalhando com o arquivo [Link] , o Git apenas mantinha o controle
de todas as inserções, exclusões e alterações e as reaplicava à versão mais antiga do arquivo durante a
mesclagem. Mas quando mais de um programador trabalha no mesmo arquivo, eles podem modificar
acidentalmente o mesmo pedaço de código em diferentes ramificações. Isso pode causar conflitos de mesclagem,
e o Git marcará os fragmentos de código que precisam ser mesclados manualmente.

Vou ilustrar isso criando mudanças conflitantes de propósito. Primeiro, vou adicionar três pontos de exclamação
no método surface no branch master :

JAVA
[Link]("Diving for " + howDeep + " feet!!!");

Vou submeter as alterações para o branch master , depois mudar para o branch mary e adicionar os pontos de
interrogação lá no mesmo lugar onde as exclamações foram colocadas em master . Então no branch mary essa
linha ficará assim:

JAVA
[Link]("Diving for " + howDeep + " feet???");

Agora, vou voltar para o branch master e tentar fazer uma mesclagem. Claramente, o Git não pode assumir a
responsabilidade de escolher uma versão em vez da outra. Temos um conflito:

Se você abrir o arquivo [Link] , encontrará algum código duplicado marcado com tags especiais:

JAVA
public void surface(){
[Link]("Going up " +
<<<<<<< HEAD
currentDepth + " feet!!!");
=======
currentDepth + " feet???");
>>>>>>> mary
}

[Link] 290/303
22/03/2025, 18:48 Programação Java para crianças

A seção de código conflitante marcada como HEAD corresponde à versão no branch master , e a outra é de mary
. Agora você precisa editar manualmente o arquivo [Link] para manter a versão da linha de código conflitante
que você gosta. Confirme as alterações no branch master e o conflito será resolvido.

Você pode encontrar explicações mais detalhadas de todos os recursos do Git no livro
OBSERVAÇÃO
gratuito intitulado Pro Git ([Link] publicado pela Apress.

14.5. Publicando seu código no GitHub


Se você tiver um repositório Git compartilhado em um computador remoto, precisará sincronizar com ele o
conteúdo do seu repositório Git local. Geralmente eu faço isso várias vezes ao dia. Mesmo se você trabalhar no
projeto sozinho, pode ser que você queira ter uma cópia atual do seu repositório Git no computador remoto.

O GitHub ([Link] é um serviço de hospedagem de repositório Git baseado na Web, onde você pode
criar um repositório de código compartilhado gratuitamente, desde que não se importe em manter seu código
aberto ao público. Pessoas ou organizações que desejam criar repositórios privados no GitHub podem comprar
uma conta paga. Mas não temos nada a esconder. Além disso, os programadores que têm seu código publicado
no GitHub são tratados com respeito adicional.

O GitHub não é o único serviço de hospedagem para repositórios Git na Web. O


OBSERVAÇÃO Bitbucket ([Link] é outro lugar popular para armazenar repositórios Git
públicos e privados.

14.5.1. Criando um repositório GitHub


Para poder publicar seu repositório Git no GitHub, você precisa criar uma conta lá. Visite o site
[Link] ([Link] e inscreva-se. Você precisará escolher um nome de usuário para si mesmo e
digitar um endereço de e-mail, que deve ser o mesmo que você usou com o comando git config (veja a seção
Apresentando-se ao Git). O GitHub enviará um e-mail de verificação para esse endereço, e você precisará
respondê-lo. Para fins ilustrativos, criei uma nova conta no GitHub com o ID de usuário java4kids .

Após criar uma conta gratuita, você verá um botão verde intitulado "+ Novo repositório". Clique nele e insira o
nome e a descrição do seu projeto. Como nosso objetivo é publicar os arquivos do diretório local gitIntro , usarei
o mesmo nome para meu repositório GitHub. A captura de tela a seguir mostra como inseri o nome do
repositório e sua descrição:

[Link] 291/303
22/03/2025, 18:48 Programação Java para crianças

Pressione o botão intitulado "Criar Repositório" e um repositório vazio estará pronto. O GitHub mostrará a
seguinte página com instruções curtas sobre como fazer upload do seu código lá.

[Link] 292/303
22/03/2025, 18:48 Programação Java para crianças

Observe a URL HTTPS deste repositório no topo. Ela é usada para clonagem, que é descrita mais adiante.

14.5.2. Enviando o repositório local para o GitHub


Como já temos um repositório existente no diretório local gitIntro , precisaremos ir até lá na janela de Comando
ou Terminal e digitar os comandos sugeridos:

HTML
git remote add origin [Link] (1)
git push -u origin master (2)

1. Quando um repositório remoto é criado, ele recebe um nome, que por padrão é origin . Então o primeiro
comando adiciona uma URL da origin recém-criada à configuração do seu projeto Git. O nome origin serve
como um nome de alias para essa longa URL do GitHub.

2. O comando push do Git carrega o código local para o repositório remoto. Então você confirma as alterações
para um repositório Git local e as envia para o remoto. Consequentemente, o segundo comando carregou
meu repositório gerenciado pelo Git para o GitHub. A opção -u significa upstream. Você a usará com o
primeiro push para vincular seu repositório local ao remoto. Os comandos push subsequentes serão emitidos
sem a opção -u .

[Link] 293/303
22/03/2025, 18:48 Programação Java para crianças

Após executar esses comandos, o código e o banco de dados Git do meu diretório local gitIntro são publicados
no GitHub. Agora, se você ou qualquer outra pessoa visitar a URL [Link]
([Link] , eles verão uma página da Web semelhante a esta:

14.5.3. Puxando a versão mais recente do GitHub


O comando pull baixa e mescla o código mais recente do GitHub no seu computador.

[Link] 294/303
22/03/2025, 18:48 Programação Java para crianças

Se você trabalhar sozinho no projeto, não usará tanto o comando pull , porque ninguém mais está enviando as
alterações de código para lá. Você estará executando repetidamente a seguinte sequência de comandos git:

adicionar - para tornar os arquivos rastreáveis

commit - para confirmar alterações no repositório Git local

push - para enviar arquivos para o repositório compartilhado

Mas assim que outra pessoa entrar no projeto, você precisará executar o comando pull periodicamente para
garantir que você tenha a versão mais recente do código que inclui todas as alterações feitas por outros membros
da equipe, que são chamados de colaboradores , por exemplo, nossos amigos Mary e Joe são colaboradores.

Para adicionar um colaborador ao seu projeto do GitHub, você precisa visitar seu repositório de projeto
compartilhado no GitHub (por exemplo, [Link] ), clicar no ícone Setting à direita e
usar o link Collaborators na próxima página da Web. Claro, esse novo colaborador deve estar registrado no
GitHub e ter um ID. Esse processo é descrito passo a passo na documentação do GitHub
([Link] .

14.5.4. Clonagem

[Link] 295/303
22/03/2025, 18:48 Programação Java para crianças

Digamos que Peter se junte ao projeto existente e Joe e Mary querem que ele instale o código mais recente. Peter
também usará Git e GitHub, então ele precisa instalar o Git em seu computador, mas Peter não precisa criar uma
nova pasta e executar o comando git init lá. O Git tem um comando clone que pode pegar o código existente de
um repositório compartilhado e criar sua cópia no computador de Peter. O comando clone baixa o código do
projeto mais recente, incluindo todo o banco de dados Git com todo o histórico de alterações feitas por Joe e
Mary no passado. Você pode fazer a clonagem clicando no botão "Clonar na área de trabalho" no GitHub ou
executando git clone na janela de comando.

Enquanto escrevia este livro, armazenei todos os seus exemplos de código no GitHub em
[Link] ([Link] . Você pode clonar meu
repositório Git do GitHub e começar a usar, melhorar ou adicionar novos exemplos de código. Basta visitar a
página da Web acima e copiar a URL da caixa HTTPS clone URL no lado direito:

Você pode ver apenas uma parte desta URL, mas quando você copiá-la para a área de transferência, ela ficará
assim:

HTML
[Link]

Agora abra a janela de comando (ou terminal) e execute o comando clone usando a URL acima como parâmetro:

[Link] 296/303
22/03/2025, 18:48 Programação Java para crianças

HTML
git clone [Link]

Em alguns segundos você encontrará no seu computador o diretório Java4Kids_code com todos os exemplos de
código e a pasta .git dentro. Foi assim que eu fiz no meu computador Mac:

Na verdade, você pode clonar qualquer repositório de código aberto do GitHub no seu computador e trabalhar
com o código sem nem mesmo notificar o autor do código. Mas criar um clone não significa que você pode
enviar suas alterações de código de volta para o repositório do GitHub do autor sem sua aprovação. O GitHub
tem procedimentos especiais para isso, chamados Forking e Pull Requests.

14.5.5. Bifurcação e solicitações de pull


Se a clonagem cria uma cópia do repositório remoto de alguém no seu computador, o forking cria um novo
repositório GitHub a partir do existente. Se você bifurcar um projeto no GitHub, você pode clonar este projeto
da sua própria conta GitHub, e trabalhar com ele como se fosse seu. Então se você quiser contatar o autor
oferecendo sua versão do código, você precisa enviar um pull request para o autor. Ao criar um pull request você
está dizendo ao autor, "Eu acabei de melhorar seu código e o confirmei no meu repositório. Por favor, olhe para
ele e puxe-o do meu repositório se você gostar".

Digamos que você queira ser um colaborador dos meus exemplos de código para este livro. Em vez da clonagem
explicada na seção anterior, basta ir para a página do GitHub do meu projeto e clicar no botão Fork no topo da
página:

[Link] 297/303
22/03/2025, 18:48 Programação Java para crianças

Isso criará um novo repositório na sua conta do GitHub e copiará meu código para lá. Então você pode clonar
este projeto do seu repositório e trabalhar com ele. Quando você tiver melhorado meu código ou corrigido um
bug, envie-o para seu projeto bifurcado. Então visite minha página do GitHub e pressione o botão Pull Request
lá:

Você poderá criar um pull request e descrever a alteração de código que você já implementou e confirmou no
repositório bifurcado. Na verdade, eu tenho um pull request no momento em que escrevo isso. Vamos clicar
neste pequeno círculo com o dígito 1 e ver o que está lá:

[Link] 298/303
22/03/2025, 18:48 Programação Java para crianças

O usuário com o ID wbrehaut encontrou um erro de digitação no meu arquivo [Link] .


Depois de olhar o código neste arquivo, vi que é um erro de digitação de fato, e pressionar o botão verde "Merge
pull request" irá automaticamente mesclar a linha correta no meu código.

O diagrama a seguir ilustra os processos de bifurcação e solicitação de pull:

[Link] 299/303
22/03/2025, 18:48 Programação Java para crianças

Nem todo pull request pode ser mesclado automaticamente, especialmente se várias alterações de código foram
feitas. Nesse caso, você precisaria fazer um merge manual diretamente no GitHub. Eu sempre deixo um
comentário de agradecimento para as pessoas que ajudaram a melhorar meu código.

14.5.6. Clonagem do IntelliJ IDEA


Todos os IDEs Java populares suportam trabalhar com Git. No IDEA, abra o menu VCS e selecione o item de
menu Checkout from Version Control e depois GitHub, conforme mostrado abaixo.

[Link] 300/303
22/03/2025, 18:48 Programação Java para crianças

O IDEA pedirá que você faça login no GitHub. Use o e-mail e a senha que você usou ao criar sua conta no
GitHub. Então o IDEA pedirá seu próprio banco de dados de senhas - deixe em branco. Agora o IDEA está
pronto para clonar qualquer repositório público, desde que você saiba a URL do clone, que é
[Link] no nosso caso. Você deve digitar essa URL na próxima janela que
pode ser semelhante a esta:

O campo com o nome do diretório do projeto será preenchido automaticamente, mas você pode alterá-lo se
quiser. Pressione o botão Clone e o IDEA clonará todos os projetos no diretório especificado e perguntará se
você deseja abrir um projeto. Selecionar Yes abrirá um dos projetos do IDEA (por exemplo, Chapter7). Você
também verá um aviso sobre raiz VCS não registrada, que você pode ignorar, pois não estará enviando
diretamente nenhuma alteração de código para meu repositório GitHub.

Se você abrir o diretório do projeto com o File Manager (ou Finder), verá que há outras pastas que contêm
amostras de código para todos os capítulos. Você pode abrir qualquer um desses projetos no IDEA selecionando
o menu File | Open. Observe que esse diretório do projeto tem uma pasta chamada .git , que contém o banco de
dados Git com o histórico de todos os commits que fiz enquanto escrevia amostras de código para este livro.

[Link] 301/303
22/03/2025, 18:48 Programação Java para crianças

Se você observar algum erro de compilação, abra o menu Arquivo | Estrutura do Projeto e certifique-se de que o
nível de linguagem do projeto esteja definido como "8 - Lambdas, anotações de tipo etc."

O IntelliJ IDEA oferece suporte total ao Git, então você pode executar todos os comandos do Git sem precisar
usar a janela Command. Você pode encontrar a descrição do suporte ao Git na documentação do IDEA
([Link] .

[Link] 302/303
22/03/2025, 18:48 Programação Java para crianças

Epílogo
Este livro acabou. Espero que você tenha gostado de lê-lo tanto quanto eu gostei de escrevê-lo. Seu processo de
estudo de Java está longe de terminar. Se você gostou deste livro e quer continuar sua jornada, considere ler meu
outro livro de Java para adultos, chamado "Java 24-Hour Trainer", 2ª edição, Wiley. Esse livro vem com vídeos
que ilustram os materiais abordados em cada capítulo. Eu também explico a programação do lado do servidor
em Java lá. Talvez um dia eu escreva um livro de Java mais avançado para crianças também. Obrigado por ler
meu livro e boa sorte!

Última atualização 2016-02-05 02:34:19 EST

[Link] 303/303

Você também pode gostar