Buscar

java6-to-java8

Prévia do material em texto

Guia Prático para Certificação
Atualize sua certificação Java 6 para Java 8
Rinaldo Pitzer Jr., Rodrigo Moutinho
Version v1.0.3, 2020-04-14
Índice
Licença . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .  1
Contribuidores . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .  2
Começando. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .  3
Introdução . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .  3
Objetivos. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .  3
Language Enhancements . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .  4
Objetos Strings . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .  4
Try com recursos . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .  10
Múltiplas Exception no mesmo catch . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .  18
Métodos static e default em Interfaces. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .  21
Localization . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .  29
Localização (Locale) . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .  29
Pacote de Recursos (Resource Bundle) . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .  35
Data e Hora . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .  45
Formatação de Números e Datas . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .  66
Fusos Horários . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .  82
Lambda . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .  88
Interfaces Funcionais (Functional Interfaces) . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .  88
Expressões Lambda (Lambda Expression) . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .  93
Interfaces Funcionais Pré-Construídas (Built-in Interfaces) . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .  101
Referências a Métodos (Method Reference) . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .  113
Java Streams . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .  120
Utilizando Streams . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .  120
Streams Paralelos. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .  140
Concurrency . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .  147
Pacote Concurrent . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .  147
Locks . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .  152
Executando tarefas com ExecutorService . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .  160
Framework Fork/Join . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .  177
Java File I/O (NIO.2) . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .  182
Paths . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .  182
Files . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .  192
DirectoryStream e FileVisitor . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .  208
Files com Streams . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .  216
WatchService . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .  222
Java Collections. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .  228
Diamond Operator (Operador Diamante) . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .  228
Collections e lambda . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .  229
Buscar por dados . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .  231
Fazendo cálculos e coletando resultados de Streams . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .  232
Melhorias de Java 8 em Coleções . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .  235
Maps e Streams . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .  237
Assume the following . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .  240
Apêndice A: Dicas para ter sucesso na prova!. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .  241
Cenário 1 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .  241
Cenário 2 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .  242
Cenário 3 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .  242
Apêndice B: Teste seu conhecimento! . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .  244
Gratuito . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .. . . . . . . . . . . . . . . . . . . . . . . . . . . .  244
Pagos . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .  244
Apêndice C: Referências . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .  245
Material Complementar . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .  245
Licença
MIT License
Copyright (c) 2019 Rinaldo Pitzer Jr. e Rodrigo Moutinho
Permission is hereby granted, free of charge, to any person obtaining a copy of this software and
associated documentation files (the "Software"), to deal in the Software without restriction,
including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense,
and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do
so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all copies or substantial
portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED,
INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A
PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
1
Contribuidores
Por ser um livro de código aberto, recebemos várias mudanças de conteúdo e erratas ao longo de
seu desenvolvimento. Aqui estão todas as pessoas que contribuíram para a versão em português do
livro como um projeto de código aberto. Obrigado a todos por ajudarem a tornar este livro melhor
para todos.
Rinaldo Pitzer Júnior
Rodrigo Moutinho
semantic-release-bot
Esse texto é praticamente o mesmo utilizado no Pro Git 2. Acesse o texto original aqui.
2
https://raw.githubusercontent.com/progit/progit2/master/book/contributors.asc
Começando
Introdução
Este projeto serve como material de apoio na realização do exame 1Z0-813 que atualiza qualquer
profissional com certificação Java 6 ou inferior, para a versão 8. No momento desta documentação,
o voucher do exame custa R$ 597,00 no Brasil.
Objetivos
Como guia para criação deste livro foi utilizado todos os objetivos citados na seção "Review Exam
Topics", de acordo com o site da certificação.
A missão deste livro é criar o maior número de exemplos práticos possíveis para ajudar você a
colocar a mão na massa. Quanto maior for seu contato com os códigos da versão 8 do Java, mais
confiante estará na hora do exame, e também para lidar com projetos em Java 8 no mercado de
trabalho.
3
https://education.oracle.com/upgrade-to-java-se-8-ocp/pexam_1Z0-813
https://education.oracle.com/upgrade-to-java-se-8-ocp/pexam_1Z0-813
Language Enhancements
Objetos Strings
Objetivo
Develop code that uses String objects in the switch statement, binary literals, and
numeric literals, including underscores in literals.
-
Desenvolver código que utilize objetos String em instruções Switch, binários literais,
e numéricos literais, incluindo underscore (_) em literais.
String em instruções Switch
É esperado que o candidato saiba compreender e analisar o uso de Strings em instruções switch,
como no seguinte exemplo.
src/org/j6toj8/languageenhancements/stringinswitch/StringInSwitch_Complete.java
public static void main(String[] args) {
  String mes = "jan";
  switch (mes) {
  case "jan":
  System.out.println("Janeiro");
  break;
  case "fev":
  System.out.println("Fevereiro");
  break;
  case "mar":
  System.out.println("Março");
  break;
  default:
  break;
  }
}
Apesar da certificação ter foco nas atualizações trazidas pelo Java 7 e 8, é esperado que o candidato
entenda também conceitos de versões anteriores do Java. Por isso, serão apresentadas algumas
regras que talvez você já conheça sobre switch, mas utilizando String no switch.
1. Todo case deve ser único, não pode se repetir.
2. O default pode aparecer em qualquer posição no switch.
4
src/org/j6toj8/languageenhancements/stringinswitch/StringInSwitch_Default.java
public static void main(String[] args) {
  String mes = "jan";
  switch (mes) {
  case "jan":
  System.out.println("Janeiro");
  break;
  default: // COMPILA - O default pode estar em qualquer posição
  break;
  case "jan": // NÃO COMPILA - Já existe o case "jan"
  System.out.println("Janeiro2");
  break;
  case "mar":
  System.out.println("Março");
  break;
  }
}
3. Tipos suportados em switch.
◦ int e Integer
◦ byte e Byte
◦ short e Short
◦ char e Character
◦ String
◦ valores de Enums
4. Tipos não suportados em switch.
5
src/org/j6toj8/languageenhancements/stringinswitch/StringInSwitch_Type.java
public static void main(String[] args) {
  Long mes = 1L;
  switch (mes) { // NÃO COMPILA - Long não é um tipo suportado
  case 1L:
  System.out.println("Janeiro");
  break;
  case 2L:
  System.out.println("Fevereiro");
  break;
  default:
  break;
  }
}
5. A execução se inicia em um case e somente para ao encontrar um break.
src/org/j6toj8/languageenhancements/stringinswitch/StringInSwitch_Break.java
public static void main(String[] args) {
  String mes = "jan";
  switch (mes) {
  case "jan":
  System.out.println("Janeiro");
  default:
  System.out.println("Não é um mês");
  case "fev":
  System.out.println("Fevereiro");
  break;
  case "mar":
  System.out.println("Março");
  break;
  }
}
saída no console
Janeiro
Não é um mês
Fevereiro
Nesse caso a execução inicia no case "jan", passar pelo default e pelo case "fev" até parar no
break, por isso as 3 strings aparecem no console.
6
6. Um switch vazio é válido, mesmo que não tenha utilidade.
src/org/j6toj8/languageenhancements/stringinswitch/StringInSwitch_Empty.java
public static void main(String[] args) {
  String mes = "jan";
  switch (mes) {} // COMPILA - switch pode estar vazio, mesmo que seja inútil
}
7. Todos os valores de case precisam ser constantes, ou seja, variáveis finais em tempo de
compilação. Se o valor do case puder mudar em tempo de execução, o código não compila.
src/org/j6toj8/languageenhancements/stringinswitch/StringInSwitch_ConstantOnly.java
private static final String FEV = "fev";
private static String jan = "jan";
public static void getNomeMes(final String mai) {
  String mes = "jan";
  final String mar = "mar";
  String abr = "abr";
  switch (mes) {
  case jan: // NÃO COMPILA - jan é um atributo comum, pode mudar em tempo de
execução
  System.out.println("Janeiro");
  break;
  case FEV: // COMPILA - FEV é uma constante em tempo de compilação, seu valor
nunca muda
  System.out.println("Fevereiro");
  break;
  case mar: // COMPILA - mar é uma constante em tempo de compilação, seu valor
nunca muda
  System.out.println("Março");
  break;
  case abr: // NÃO COMPILA - abr é uma variável comum, pode mudar em tempo de
execução
  System.out.println("Abril");
  break;
  case mai: // NÃO COMPILA - mai é final, mas não é constante, pode mudar em tempo
de execução
  System.out.println("Maio");
  break;
  }
}
7
Pronto, essas são as regras de switch. Você provavelmente já conheçe algumas referentes à versões
anteriores do Java, mas agora você as viu em switch que utilizam Strings. Isso não era possível
antes do Java 7.
Literais Binários e Numéricos, incluindo underscore( _ )
É esperado que o candidato saiba compreender e analisar o uso de literais binários e numéricos,
como no seguinte exemplo.
src/org/j6toj8/languageenhancements/literals/Literals_Complete.java
int i1 = 1; // int
int i2 = 1_000_000; // int com underscore
int i3 = 0567; // octadecimal
int i4 = 0xFA1; // hexadecimal
int i5 = 0b0101; // binário
long l1 = 1L; //long com L
long l2 = 1l; // long com l
long l3 = 12_345_6_7890_123456_789L; // long com underscore
long l4 = 0xFA1L; // long hexadecimal
double d1 = 1.00; // double
double d2 = 100_000.01; // double com underscore
double d3 = 1D; // double com D
double d4 = 3.1E2; // notação científica = 3.1 * 10^2 = 3.1 * 100 = 310.0
float f1 = 1.00F; // float
Apesar da certificação ter foco nas atualizações trazidas pelo Java 7 e 8, é esperado que o candidato
entenda também conceitos de versões anteriores do Java. Por isso, serão apresentadas algumas
regras que talvez você já conheça sobre literais.
1. No Java, Literal é qualquer número escrito diretamente no código, como todos do exemplo
acima.
2. Por padrão, o Java interpreta literais como int. Ou seja, se não houver um sufixo no número
para mudar seu tipo, ele é um int.
src/org/j6toj8/languageenhancements/literals/Literals_Suffix.java
int i1 = 1; // por padrão é int
long l1 = 1L; // com um L no final, é um long
double d1 = 1.0;
double d2 = 1.0D; // com ou sem D no final, se tiver casa decimal é um double por
padrão
float f1 = 1.0F; // com um F no final, é um float
3. Por padrão, o Java interpreta literais como sendo decimais. Existem prefixos que mudam o
sistema numérico do literal.
8
src/org/j6toj8/languageenhancements/literals/Literals_Prefix.java
int i1 = 0567; // octadecimal - base 8 - começa com 0
int i2 = 0xFA1; // hexadecimal - base 16 - começa com 0x
int i3 = 0b0101; // binário - base 2 - começa com 0b
long l1 = 0xABCL; // long também pode ser hexadecimal - começa com 0x e termina com
L
4. A partir do Java 7, é possível utilizar underscore (_) para separar visualmente um número. Isso
não muda o valor do número, e serve apenas para tornar o código mais legível.
src/org/j6toj8/languageenhancements/literals/Literals_Underscore.java
int i1 = 1_000_000; // int com underscore - é o mesmo que escrever 1000000
int i2 = 10_00_00_0; // o underscore pode estar em qualquer posição entre 2 números
int i3 = _1000; // NÃO COMPILA - o underscore não pode estar no início
int i4 = 1000_; // NÃO COMPILA - o underscore não pode estar no final
int i5 = 1___000; // COMPILA - vários underscore é permitido, desde que estejam
entre 2 números
int i6 = 0x_100; // NÃO COMPILA - entre marcador de base não é permitido
int i7 = 0xF_F; // COMPILA - apesar de serem letras, representam valores numéricos
dessa base
long l1 = 12_345_6_7890_123456_789L; // long com underscore
long l2 = 12_345_6_789_L; // NÃO COMPILA - não pode ficar ao lado de um marcador de
tipo
double d1 = 100_000.01; // double com underscore
double d2 = 10_.01; // NÃO COMPILA - o underscore deve estar entre números
double d3 = 10._01; // NÃO COMPILA - o underscore deve estar entre números
Referências
Strings em Switch
• Boyarsky, Jeanne; Selikoff, Scott. OCP: Oracle Certified Professional Java SE 8 Programmer
II Study Guide (p. 598). Wiley. Edição do Kindle.
• Strings in switch Statements. Java Documentation.
• New Java 7 Feature: String in Switch support. DZone.
Literais
• Boyarsky, Jeanne; Selikoff, Scott. OCP: Oracle Certified Professional Java SE 8 Programmer
II Study Guide (p. 597). Wiley. Edição do Kindle.
• Java/Literais. Wikibooks.
9
https://docs.oracle.com/javase/8/docs/technotes/guides/language/strings-switch.html
https://dzone.com/articles/new-java-7-feature-string
https://pt.wikibooks.org/wiki/Java/Literais
Try com recursos
Objetivo
Develop code that uses try-with-resources statements, including using classes that
implement the AutoCloseable interface.
-
Desenvolver código que utilize instruções try-with-resources, incluindo o uso de
classes que implementam a interface AutoCloseable.
É esperado que o candidato saiba compreender e analisar o uso da instrução try-with-resources,
incluindo classes que implementam a interface AutoClosable.
Antes de continuar, com base no exemplo a seguir, entenda a execução do método main e o que é
apresentado no console após sua execução.
src/org/j6toj8/languageenhancements/trywithresources/TryWithResouces_Complete.java
public static void main(String[] args) throws IOException {
  // criação de 2 arquivos
  File file = new File("arquivo.txt");
  File file2 = new File("arquivo2.txt");
  // Exemplo try-with-resources com PrintWriter
  try (PrintWriter writer = new PrintWriter(file)) {
  // escreve no arquivo.txt
  writer.println("Olá Mundo!");
  }
  // Exemplo try-with-resources com BufferedReader
  try (BufferedReader reader = Files.newBufferedReader(file.toPath())) {
  // imprime no console uma linha do arquivo.txt
  System.out.println(reader.readLine());
  }
  // Exemplo try-with-resources com BufferedReader e BufferedWriter
  try (BufferedReader reader = Files.newBufferedReader(file.toPath());
  BufferedWriter writer = Files.newBufferedWriter(file2.toPath())) {
  // lê a linha do arquivo.txt e escreve no arquivo2.txt
  writer.write(reader.readLine() + "2");
  }
  // Exemplo try-with-resources com BufferedReader
  try (BufferedReader reader = Files.newBufferedReader(file2.toPath())) {
  // imprime no console uma linha do arquivo2.txt
  System.out.println(reader.readLine());
  }
  // todos os Reader e Writer já foram fechados.
}
10
O código acima utiliza dois arquivos, e faz leitura e escrita neles. A grande novidade desse código é
a declaração de variáveis dentro de parênteses após a instrução try. Isso é a sintaxe chamada try-
with-resources, e ela chama automaticamente o método close() dos recursos que estão sendo
utilizados. Até o Java 6, seria necessário chamar o close() manualmente, como no exemplo abaixo.
src/org/j6toj8/languageenhancements/trywithresources/TryWithResouces_Java6.java
public static void main(String[] args) throws FileNotFoundException {
  File file = new File("arquivo.txt");
  PrintWriter writer = null;
  try {
  writer = new PrintWriter(file);
  writer.println("Olá Mundo!");
  } finally {
  if (writer != null) {
  writer.close(); // fechando o writer manualmente
  }
  }
}
1. A instrução try-with-resources fecha automaticamente os recursos que implementam a interface
AutoCloseable.
2. Ela não precisa de catch nem finally explícitos.
src/org/j6toj8/languageenhancements/trywithresources/TryWithResouces_AutoCloseable.java
static class Porta implements AutoCloseable {
  @Override
  public void close() { // chamado automaticamente pelo try-with-resources
  System.out.println("Porta fechada.");
  }
}
public static void main(String[] args) throws FileNotFoundException {
  try (Porta porta = new Porta()) { // Porta instanciada dentro da instrução try-
with-resources
  System.out.println("try");
  }
}
Saída no console
try
Porta fechada.
3. A instrução try-with-resources ainda pode ter catch e finally, apesar de não ser necessário.
Nesse caso, os recursos são fechados depois do try e antes de qualquer catch ou finally.
4. O método close pode lançar uma exceção sendo capturada pelo catch, caso exista.
11
src/org/j6toj8/languageenhancements/trywithresources/TryWithResouces_WithCatchFinally.java
static class Porta implements AutoCloseable {
  @Override
  public void close() throws Exception { // chamado automaticamente pelo try-with-
resources
  System.out.println("Porta fechada.");
  throw new Exception(); // lança Exception
  }
}
public static void main(String[] args) throws FileNotFoundException {
  try (Porta porta = new Porta()) { // Porta instanciada dentro da instrução try-
with-resources
  System.out.println("try");
  } catch (Exception e) {
  System.out.println("catch");
  } finally {
  System.out.println("finally");
  }
}
Saída no console
try
Porta fechada.
catch
finally
Ou seja, primeiro o try é chamado. Logo depois é chamado o método close() que ao final lança
uma exceção. O catch captura essa exceção. E finalmente o finally é chamado.
5. Os recursos declarados na instrução try-with-resources são fechados na ordem inversa da
declaração.
12
src/org/j6toj8/languageenhancements/trywithresources/TryWithResouces_Order.java
static class Porta implementsAutoCloseable {
  @Override
  public void close() { // chamado automaticamente pelo try-with-resources
  System.out.println("Porta fechada.");
  }
}
static class Gaveta implements AutoCloseable {
  @Override
  public void close() { // chamado automaticamente pelo try-with-resources
  System.out.println("Gaveta fechada.");
  }
}
public static void main(String[] args) {
  try (Porta porta = new Porta();
  Gaveta gaveta = new Gaveta()) {
  System.out.println("Olá.");
  }
}
Saída no console
Olá.
Gaveta fechada.
Porta fechada.
Ou seja, como a ordem de declaração dentro do try-with-resources foi Porta e depois Gaveta, a
ordem de chamada do método close é inversa: Gaveta e depois Porta.
6. Os recursos declarados no try-with-resources só estão disponível dentro do bloco try.
13
src/org/j6toj8/languageenhancements/trywithresources/TryWithResouces_ResourceInsideTry.java
static class Porta implements AutoCloseable {
  @Override
  public void close() { // chamado automaticamente pelo try-with-resources
  System.out.println("Porta fechada.");
  }
}
public static void main(String[] args) {
  try (Porta porta = new Porta()) {
  porta.toString();
  } catch (Exception e) {
  porta.toString(); // NÃO COMPILA - variável porta só disponível dentro do bloco
try
  } finally {
  porta.toString(); // NÃO COMPILA - variável porta só disponível dentro do bloco
try
  }
}
7. Somente classes que implementam AutoCloseable podem ser utilizadas dentro do try-with-
resources.
src/org/j6toj8/languageenhancements/trywithresources/TryWithResouces_NoAutoCloseable.java
static class Prateleira {}
public static void main(String[] args) {
  try (Prateleira prateleira = new Prateleira()) { // NÃO COMPILA - Prateleira não
implementa AutoClosable
  System.out.println("Olá");
  }
}
8. Caso o método close() lance uma exceção checada (ou seja, que herda de Exception), o código só
compila se existir um catch que capture aquela exceção, ou o método declare o throws.
14
src/org/j6toj8/languageenhancements/trywithresources/TryWithResouces_CloseException.java
static class Porta implements AutoCloseable {
  @Override
  public void close() throws Exception { // declara throws Exception
obrigatoriamente
  throw new Exception();
  }
}
void try1() {
  try (Porta porta = new Porta()) { // NÃO COMPILA - exceção do close() não é
capturada nem declarada
  System.out.println("Olá 1");
  }
}
void try2() {
  try (Porta porta = new Porta()) {
  System.out.println("Olá 2");
  } catch (Exception e) { // COMPILA - exceção capturada
  }
}
void try3() throws Exception { // COMPILA - exceção declarada no método
  try (Porta porta = new Porta()) {
  System.out.println("Olá 3");
  }
}
9. O Java 5 já possuía uma interface chamada Closeable, porém ela permite lançar apenas
IOException. A nova interface AutoCloseable permite lançar qualquer exceção. Como Closeable
atende a implementação de AutoCloseable, ela agora estende AutoCloseable. Logo, todas as
classes que já implementavam Closeable podem ser utilizadas dentro do try-with-resources. Veja
abaixo como era a interface Closeable antes e a partir do Java 7:
Antes do Java 7
public interface Closeable {
  public void close() throws IOException;
}
A partir do Java 7
public interface Closeable extends AutoCloseable {
  public void close() throws IOException;
}
10. Um comportamento novo são as exceções suprimidas (suppressed). Se ambos o bloco try e o
15
método close lançam exceção, a do close fica suprimida, pois a do try é lançada primeiro.
src/org/j6toj8/languageenhancements/trywithresources/TryWithResouces_Suppressed.java
static class Porta implements AutoCloseable {
  @Override
  public void close() {
  System.out.println("close");
  throw new RuntimeException("erro no close"); // lança RuntimeException, mas só
depois do try
  }
}
public static void main(String[] args) {
  try (Porta porta = new Porta()) {
  System.out.println("try");
  throw new RuntimeException("erro no try"); // lança RuntimeException
  } catch (RuntimeException e) { // captura RuntimeException - qual foi capturada?
  System.out.println(e.getMessage()); // apresenta a mensagem da exceção do try
  System.out.println(e.getSuppressed()[0].getMessage()); // apresenta a mensagem
da exceção suprimida, ou seja, do close
  }
}
Saída no console
try
close
erro no try
erro no close
Ou seja, a exceção que de fato foi capturada foi a do bloco try, pois foi lançada primeiro. A
exceção lançada pelo método close ficou suprimida, e fica disponível em um array no método
getSuppressed() da exceção.
11. E por fim, é necessário lembrar que a instrução try "comum" ainda precisa obrigatoriamente de
um catch ou finally.
16
src/org/j6toj8/languageenhancements/trywithresources/TryWithResouces_CommonTry.java
public static void main(String[] args) {
  try {
  System.out.println("try");
  } // NÃO COMPILA - try "comum" sem catch ou finally
  try {
  System.out.println("try");
  } catch (Exception e) {
  } // COMPILA - try "comum" só com catch
  try {
  System.out.println("try");
  } finally {
  } // COMPILA - try "comum" só com finally
  try {
  System.out.println("try");
  } catch (Exception e) {
  } finally {
  } // COMPILA - try "comum" com catch e finally
}
Alguns tipos que implementam Closeable
• InputStream e suas subclasses (FileInputStream, ObjectInputStream, etc)
• OutputStream e suas subclasses (ByteArrayOutputStream, FileOutputStream, etc)
• Reader e suas subclasses (BufferedReader, CharSequenceReader)
• Writer e suas subclasses (BufferedWriter, PrintWriter, etc)
Referências
• Using Try-With-Resources
Boyarsky, Jeanne; Selikoff, Scott. OCP: Oracle Certified Professional Java SE 8 Programmer
II Study Guide (p. 296). Wiley. Edição do Kindle.
• Java – Try with Resources.
• The try-with-resources Statement. Java Documentation.
• Como funciona o try-with-resources?
17
https://www.baeldung.com/java-try-with-resources
https://docs.oracle.com/javase/tutorial/essential/exceptions/tryResourceClose.html
https://pt.stackoverflow.com/questions/172909/como-funciona-o-try-with-resources/172910#172910
Múltiplas Exception no mesmo catch
Objetivo
Develop code that handles multiple Exception types in a single catch block.
-
Desenvolver código que lide com múltiplos tipos de Exception em um único bloco catch.
É esperado que o candidato saiba compreender e analisar o uso da instrução try-catch com
múltiplos tipos de Exception no mesmo bloco catch.
Antes de continuar, com base no exemplo a seguir, entenda a execução do método main e o que é
apresentado no console após sua execução.
src/org/j6toj8/languageenhancements/multipleexception/MultipleException_Complete.java
public static void main(String[] args) {
  try {
  throw new NullPointerException();
  } catch (NullPointerException | IllegalArgumentException | IllegalStateException e)
{
  System.out.println("Exceção capturada: " + e);
  } catch (Exception e) {
  System.out.println("Exceção capturada: " + e);
  }
}
O código anterior possui um bloco try-catch que você provavelmente já conhece. A novidade neste
código está no primeiro bloco catch, onde várias exceções são declaradas e capturadas ao mesmo
tempo.
Saída no console
Exceção capturada: java.lang.NullPointerException
1. Desde o Java 7, múltiplas exceções podem ser capturadas no mesmo catch.
2. Apenas uma variável é permitida para um bloco catch, e deve estar localizada no final.
18
src/org/j6toj8/languageenhancements/multipleexception/MultipleException_MultipleSameCatch.java
public static void main(String[] args) {
  try {
  throw new NullPointerException();
  } catch (NullPointerException | IllegalArgumentException e) { // COMPILA -
múltiplas exceções no mesmo catch, só uma variável no final
  System.out.println("Exceção capturada: " + e);
  } catch (IllegalStateException ise | UnsupportedOperationException uoe) { // NÃO
COMPILA - mais de uma variável declarada
  System.out.println("Exceção capturada: " + ise);
  } catch (ClassCastExceptioncce | ConcurrentModificationException) { // NÃO
COMPILA - só uma variável, mas no lugar errado
  System.out.println("Exceção capturada: " + cce);
  }
}
3. Não é permitido declarar exceções diferentes, mas que seriam redundantes levando em
consideração a herança.
src/org/j6toj8/languageenhancements/multipleexception/MultipleException_Redundant.java
public static void main(String[] args) {
  try {
  throw new NullPointerException();
  } catch (RuntimeException | IllegalArgumentException e) { // NÃO COMPILA -
IllegalArgumentException herda de RuntimeException, logo seria redundante
  System.out.println("Exceção capturada: " + e);
  }
}
4. Ao fazer catch de múltiplas Exception, não é permitido sobrescrever a variável da exceção. Mas
é possível se for apenas uma Exception no catch.
19
src/org/j6toj8/languageenhancements/multipleexception/MultipleException_OverrideVar.java
public static void main(String[] args) {
  try {
  throw new NullPointerException();
  } catch (NullPointerException | IllegalArgumentException e) {
  e = new IllegalStateException(); // NÃO COMPILA - a variável não pode ser
sobrescrita quando está em um multi-catch
  } catch (Exception e) {
  e = new IllegalStateException(); // COMPILA - ainda é possível sobrescrever a
variável quando não é um multi-catch
  }
}
5. Assim como nas versões anteriores, tipos mais genéricos de Exception devem vir depois, mais
abaixo nos catch’s.
src/org/j6toj8/languageenhancements/multipleexception/MultipleException_GenericsLower.java
public static void main(String[] args) {
  try {
  throw new NullPointerException();
  } catch (Exception e) {
  System.out.println("Exceção capturada: " + e);
  } catch (NullPointerException | IllegalArgumentException e) { // NÃO COMPILA -
NullPointerException é mais específico que Exception, logo deveria ser capturada
antes de Exception
  System.out.println("Exceção capturada: " + e);
  }
}
6. Assim como nas versões anteriores, Exceções repetidas ainda são proibidas.
src/org/j6toj8/languageenhancements/multipleexception/MultipleException_RepeatException.java
public static void main(String[] args) {
  try {
  throw new NullPointerException();
  } catch (NullPointerException | IllegalArgumentException e) {
  System.out.println("Exceção capturada: " + e);
  } catch (IllegalStateException | NullPointerException e) { // NÃO COMPILA -
NullPointerException já foi capturada no catch anterior
  System.out.println("Exceção capturada: " + e);
  }
}
20
7. Assim como nas versões anterior, Exceções checadas (aquelas que herdam de Exception) só
podem estar em um catch caso algo no try lance elas.
src/org/j6toj8/languageenhancements/multipleexception/MultipleException_CheckedException.java
public static void main(String[] args) {
  try {
  throw new NullPointerException();
  } catch (NullPointerException | IOException e) { // NÃO COMPILA - IOException não
é lançada dentro do bloco try
  System.out.println("Exceção capturada: " + e);
  }
}
Referências
• Boyarsky, Jeanne; Selikoff, Scott. OCP: Oracle Certified Professional Java SE 8 Programmer
II Study Guide (p. 291). Wiley. Edição do Kindle.
• Catching Multiple Exception Types and Rethrowing Exceptions with Improved Type
Checking. Java Documentation.
Métodos static e default em Interfaces
Objetivo
Use static and default methods of an interface including inheritance rules for a
default method.
-
Usar métodos static e default de uma interface, incluindo regras de herança para um
método default.
É esperado que o candidato saiba compreender e analisar o uso da dos modificadores static e
default em métodos de interfaces.
Antes de continuar, com base no exemplo a seguir, entenda a execução do método main e o que é
apresentado no console após sua execução.
21
https://docs.oracle.com/javase/8/docs/technotes/guides/language/catch-multiple.html
https://docs.oracle.com/javase/8/docs/technotes/guides/language/catch-multiple.html
src/org/j6toj8/languageenhancements/staticdefaultininterfaces/StaticDefaultInInterfaces_Complete.java
interface Corredor {
  static double calculeVelocidade(int distancia, int tempo) {
  return distancia / tempo;
  }
  default String correr() {
  return "Correndo";
  }
  String correrRapido();
}
static class Pessoa implements Corredor {
  @Override
  public String correrRapido() {
  return "Pessoa Correndo Rápido";
  }
  public static void main(String[] args) throws IOException {
  System.out.println(Corredor.calculeVelocidade(100, 10));
  System.out.println(new Pessoa().correr());
  System.out.println(new Pessoa().correrRapido());
  }
}
Saída no console
10.0
Correndo
Pessoa Correndo Rápido
O código anterior possui dois modificadores novos para interfaces, possíveis desde o Java 8: default
e static. É possível perceber que esses dois métodos possuem corpo, algo que não era possível
antes em uma interface. Então, vamos entender quais são as novas possibilidades.
1. Desde o Java 8, Interfaces podem ter métodos com o modificador static.
2. Métodos com o modificador static em interfaces são chamados iguais aos de uma classe
comum, ou seja, não fazem parte da API da interface. Dessa forma, não são herdados pelas
classes que implementam essa interface.
22
src/org/j6toj8/languageenhancements/staticdefaultininterfaces/StaticDefaultInInterfaces_Static.java
interface Corredor {
  static double calculeVelocidade(int distancia, int tempo) {
  return distancia / tempo;
  }
}
static class Pessoa implements Corredor {
  public static void main(String[] args) throws IOException {
  System.out.println(Corredor.calculeVelocidade(100, 50)); // COMPILA - método
static de uma interface sendo chamado como se fosse de uma classe comum
  System.out.println(Pessoa.calculeVelocidade(100, 50)); // NÃO COMPILA - o
método static não é herdado, nem implementado, pela classe Pessoa
  }
}
3. Desde o Java 8, Interfaces podem ter métodos com o modificador default.
4. Métodos default não precisam, mas podem, ser sobrescritos.
src/org/j6toj8/languageenhancements/staticdefaultininterfaces/StaticDefaultInInterfaces_Default.java
interface Corredor {
  default String correr() {
  return "Correndo";
  }
}
static class Pessoa implements Corredor {
}
static class Cavalo implements Corredor {
  @Override
  public String correr() {
  return "Galopando";
  }
  public static void main(String[] args) throws IOException {
  System.out.println(new Pessoa().correr());
  System.out.println(new Cavalo().correr());
  }
}
Veja que a classe Pessoa não sobrescreve o método correr(), mantendo o comportamento
padrão da implementação feita na interface Corredor.
A classe Cavalo, por outro lado, sobrescreve o método correr() para ter sua própria
implementação.
23
Saída no console
Correndo
Galopando
5. Assim como os outros método de uma interface, os métodos static e default são sempre public,
e não podem ser modificados para private ou protected.
src/org/j6toj8/languageenhancements/staticdefaultininterfaces/StaticDefaultInInterfaces_AccessModifie
rs.java
interface Corredor {
  default String correr() { // COMPILA - não há modificador de acesso declarado, é
automaticamente público
  return "Correndo";
  }
  public default String correrRapido() { // COMPILA - modificador de acesso público
explícito
  return "Correndo Rápido";
  }
  protected default String correrDevagar() { // NÃO COMPILA - o método deve ser
obrigatoriamente público
  return "Correndo Devagar";
  }
  private default String correrExtremo() { // NÃO COMPILA - o método deve ser
obrigatoriamente público
  return "Correndo ao Extremo";
  }
  private static double calculeVelocidade(int d, int t) { // NÃO COMPILA - o método
deve ser obrigatoriamente público
  return d / t;
  }
}
6. Diferente dos outros método de uma interface, os métodos static e default não são abstract, e
também não podem ser. Afinal, eles possuem implementação. Apenas métodos sem
implementação são abstract.
24
src/org/j6toj8/languageenhancements/staticdefaultininterfaces/StaticDefaultInInterfaces_Abstract.javainterface Corredor {
  default String correr() { // COMPILA - método default não é abstract
  return "Correndo";
  }
  abstract default String correrRapido() { // NÃO COMPILA - método default não pode
ser declarado abstract
  return "Correndo Rápido";
  }
  String correrDevagar(); // COMPILA - método comum, é abstract por padrão, mesmo
que de forma implícita
  abstract String correrExtremo(); // COMPILA - método comum, declarado abstract de
forma explícita
  abstract static double calculeVelocidade(int d, int t) { // NÃO COMPILA - método
static não pode ser declarado abstract
  return d / t;
  }
}
7. Se uma classe implementa duas interfaces que possuem métodos default repetidos, ela
obrigatoriamente deve implementar o seu próprio.
25
src/org/j6toj8/languageenhancements/staticdefaultininterfaces/StaticDefaultInInterfaces_RepeatedDefa
ult.java
interface Corredor {
  default String correr() {
  return "Correndo";
  }
}
interface Piloto {
  default String correr() {
  return "Piloto Correndo";
  }
}
static class Pessoa implements Corredor, Piloto { // NÃO COMPILA - implementa duas
interfaces com métodos repetidos e não sobrescreve
}
static class Gigante implements Corredor, Piloto { // COMPILA - implementa duas
interfaces com métodos repetidos, mas sobrescreve e cria sua própria implementação
  @Override
  public String correr() {
  return "Gigante Correndo";
  }
}
8. Ao implementar múltiplas interfaces, é possível acessar a implementação default de uma delas.
26
src/org/j6toj8/languageenhancements/staticdefaultininterfaces/StaticDefaultInInterfaces_RepeatedDefa
ultSuper.java
interface Corredor {
  default String correr() {
  return "Correndo";
  }
}
interface Piloto {
  default String correr() {
  return "Piloto Correndo";
  }
}
static class Pessoa implements Corredor, Piloto { // COMPILA - mantém a
implementação do Corredor no método correr()
  @Override
  public String correr() {
  return Corredor.super.correr();
  }
  public static void main(String[] args) {
  System.out.println(new Pessoa().correr());
  }
}
Saída no console
Correndo
9. Quando uma interface herda de outra interface métodos default, estes podem ser mantidos,
transformados em abstract ou redefinidos.
27
src/org/j6toj8/languageenhancements/staticdefaultininterfaces/StaticDefaultInInterfaces_InterfaceInher
itance.java
interface Corredor {
  default String correr() {
  return "Correndo";
  }
  default String correrRapido() {
  return "Correndo Rápido";
  }
  default String correrDevagar() {
  return "Correndo Devagar";
  }
}
interface Piloto extends Corredor {
  String correrRapido();
  default String correrDevagar() {
  return "Piloto Correndo Devagar";
  }
}
Nesse exemplo, a interface Piloto herda de Corredor e mostra 3 cenários distintos:
◦ Mantém o método correr() inalterado;
◦ Altera o método correrRapido() para que seja abstract, fazendo com que qualquer classe
que implemente a interface Piloto tenha que implementar esse método;
◦ Altera o método correrDevagar() para que tenha sua própria implementação
Referências
• Designing an Interface
Boyarsky, Jeanne; Selikoff, Scott. OCP: Oracle Certified Professional Java SE 8 Programmer
II Study Guide (p. 48). Wiley. Edição do Kindle.
• Static and Default Methods in Interfaces in Java.
• Default Methods. Java Documentation.
28
https://www.baeldung.com/java-static-default-methods
https://docs.oracle.com/javase/tutorial/java/IandI/defaultmethods.html
Localization
Localização (Locale)
Objetivo
Describe the advantages of localizing an application and developing code that defines,
reads, and sets the locale with a Locale object.
-
Descrever as vantagens de localizar uma aplicação e desenvolver código que defina,
leia e aplique a localidade em um objeto Locale.
É esperado que o candidato saiba compreender e analisar aspectos de Internacionalização e
Localização, incluindo o uso da da classe Locale.
Alguns aspectos de uma aplicação podem depender do país e da linguagem. Por exemplo:
• Formatos de escrita de data
◦ O dia 6 de Agosto de 2019 seria representado no Brasil por 06/08/2019, porém nos EUA seria
08/06/2019.
• Formatos de escrita de valores monetários
◦ Dez Reais no Brasil seriam representados por R$ 10, enquanto na França Dez Euros seriam
10 €.
• Formatos de separação de casas decimais ou milhares
◦ No Brasil utiliza-se vírgula para separar decimais e pontos para milhares: 100.245,03. Nos
EUA, utiliza-se o inverso: 100,245.03.
Por isso, para que sua aplicação lide corretamente com esses cenários, é necessário compreender
dois aspectos: Internacionalização (Internationalization) e Localização (Localization).
A Internacionalização, também chamada de i18n, é o ato de projetar sua aplicação para que seja
possível facilmente adaptá-la para utilizar novos formatos e idiomas.
A Localização, também chamada de l10n, é o ato de adaptar sua aplicação para de fato utilizar um
novo formato específico.
Antes de continuar, entenda a execução do método main no exemplo a seguir e o que é apresentado
no console após sua execução.
29
src/org/j6toj8/localization/locale/Locale_Complete.java
public static void main(String[] args) throws IOException {
  System.out.println(" - Constantes - ");
  System.out.println(Locale.CANADA);
  System.out.println(Locale.UK);
  System.out.println(" - Construtor - ");
  System.out.println(new Locale("pt", "BR"));
  System.out.println(new Locale("pt", "PT"));
  System.out.println(new Locale("ca", "ES", "VALENCIA"));
  System.out.println(" - Language Tags - ");
  System.out.println(Locale.forLanguageTag("en-CA"));
  System.out.println(Locale.forLanguageTag("pt-BR"));
  System.out.println(Locale.forLanguageTag("pt-PT"));
  System.out.println(Locale.forLanguageTag("ca-ES"));
  System.out.println(Locale.forLanguageTag("gsw-u-sd-chzh"));
  System.out.println(" - Builder - ");
  Locale locale1 = new Locale.Builder()
  .setLanguage("pt")
  .setRegion("BR")
  .build();
  System.out.println(locale1);
  Locale locale2 = new Locale.Builder()
  .setLanguage("az")
  .setRegion("AZ")
  .setScript("Latn")
  .build();
  System.out.println(locale2);
  Locale locale3 = new Locale.Builder()
  .setLanguage("bs")
  .setRegion("BA")
  .setVariant("POSIX")
  .setScript("Latn")
  .setExtension('c', "cc")
  .build();
  System.out.println(locale3);
}
30
Saída no console
 - Constantes -
en_CA
en_GB
 - Construtor -
pt_BR
pt_PT
ca_ES_VALENCIA
 - Language Tags -
en_CA
pt_BR
pt_PT
ca_ES
gsw__#u-sd-chzh
 - Builder -
pt_BR
az_AZ_#Latn
bs_BA_POSIX_#Latn_c-cc
No Java, a classe Locale no pacote java.util nos ajuda a lidar com esses aspectos.
1. Geralmente, um Locale é representado por um idioma e um país.
◦ pt_BR - Português do Brasil
◦ en_US - Inglês dos EUA
◦ it_CH - Italiano da Suíça
◦ fr_BE - Francês da Bélgica
src/org/j6toj8/localization/locale/Locale_LocaleLanguageCountry.java
new Locale("pt", "BR"); // Português do Brasil
new Locale("en", "US"); // Inglês dos EUA
new Locale("it", "CH"); // Italiano da Suíça
new Locale("fr", "BE"); // Francês da Bélgica
2. Um Locale pode ter ainda uma Variante, um Script e Extensões.
31
src/org/j6toj8/localization/locale/Locale_VarScriptExtension.java
public static void main(String[] args) throws IOException {
  Locale locale2 = new Locale.Builder() // az_AZ_#Latn
  .setLanguage("az")
  .setRegion("AZ")
  .setScript("Latn")
  .build();
  Locale locale3 = new Locale.Builder() // bs_BA_POSIX_#Latn_c-cc
  .setLanguage("bs")
  .setRegion("BA")
  .setVariant("POSIX")
  .setScript("Latn")
  .setExtension('c', "cc")
  .build();
}
 No exame da certificação, a Oracle geralmente só utiliza idioma e país.
3. É possível construir um Locale com o Builder, com construtores, ou por uma Language Tag.
src/org/j6toj8/localization/locale/Locale_LocaleInstantiation.java
public static void main(String[] args) throws IOException {
  new Locale("pt", "BR"); // pt-BR com Construtor
  Locale.forLanguageTag("pt-BR"); // pt-BR comLanguageTag
  Locale localePtBR = new Locale.Builder() // pt-BR com Builder
  .setLanguage("pt")
  .setRegion("BR")
  .build();
}
A diferença entre eles é:
◦ Com os construtores é possível passar apenas o idioma, a região (país) e uma variante.
◦ Com language tags é possível passar uma String no padrão IETF BCP 47.
◦ Com o builder é possível criar da forma mais específica possível: idioma, região, variante,
script e extensões.
4. O Locale aceita letras maiúsculas e minúsculas escritas de forma incorreta.
32
https://en.wikipedia.org/wiki/IETF_language_tag
src/org/j6toj8/localization/locale/Locale_LocaleCase.java
public static void main(String[] args) throws IOException {
  System.out.println(new Locale("PT", "br"));
  System.out.println(Locale.forLanguageTag("PT-br"));
  Locale localePtBR = new Locale.Builder()
  .setLanguage("PT")
  .setRegion("br")
  .build();
  System.out.println(localePtBR);
}
Saída no console
pt_BR
pt_BR
pt_BR
Nesse exemplo, escrevemos de forma incorreta:
◦ O idioma deveria ser minúsculo (pt), mas está maiúsculo (PT).
◦ A região deveria estar maiúscula (BR), está minúscula (br).
Mesmo assim, o Locale é criado corretamente. Veja que isso é um código ruim. O ideal é
sempre escrever respeitando maiúsculas e minúsculas.
5. Existem algumas constantes na classe Locale para as localizações mais populares.
src/org/j6toj8/localization/locale/Locale_LocaleCommons.java
public static void main(String[] args) throws IOException {
  System.out.println(Locale.CANADA);
  System.out.println(Locale.CANADA_FRENCH);
  System.out.println(Locale.CHINA);
  System.out.println(Locale.CHINESE);
  System.out.println(Locale.ENGLISH);
  System.out.println(Locale.ITALY);
  System.out.println(Locale.SIMPLIFIED_CHINESE);
  System.out.println(Locale.TRADITIONAL_CHINESE);
}
33
Saída no console
en_CA
fr_CA
zh_CN
zh
en
it_IT
zh_CN
zh_TW
6. É possível recuperar o Locale padrão ou alterá-lo programaticamente.
src/org/j6toj8/localization/locale/Locale_LocaleDefault.java
public static void main(String[] args) throws IOException {
  System.out.println(Locale.getDefault()); // o padrão inicial muda de acordo com
seu dispositivo
  Locale.setDefault(Locale.KOREA); // altera o Locale default
  System.out.println(Locale.getDefault()); // ko_KR
}
Saída no console
pt_BR
ko_KR
7. É possível verificar os Locale disponíveis, pois eles variam de acordo com a JVM sendo
executada.
src/org/j6toj8/localization/locale/Locale_LocaleAvailable.java
public static void main(String[] args) throws IOException {
  Locale[] availableLocales = Locale.getAvailableLocales();
  // imprime o 10 primeiros Locales disponíveis
  for (int i = 0; i < 10; i++) {
  System.out.println(availableLocales[i]);
  }
}
34
Saída no console
nn
ar_JO
bg
kea
nds
zu
am_ET
fr_DZ
ti_ET
8. Um Locale também pode ser representado somente pelo idioma.
src/org/j6toj8/localization/locale/Locale_LocaleLanguageOnly.java
public static void main(String[] args) throws IOException {
  System.out.println(new Locale("pt")); // português
  System.out.println(new Locale("en")); // inglês
  System.out.println(new Locale("es")); // espanhol
  System.out.println(new Locale("fr")); // francês
}
Saída no console
pt
en
es
fr
Referências
• Adding Internationalization and Localization
Boyarsky, Jeanne; Selikoff, Scott. OCP: Oracle Certified Professional Java SE 8 Programmer
II Study Guide (p. 255). Wiley. Edição do Kindle.
• Internationalization and Localization in Java 8.
• Internationalization. Java Documentation.
• i18n vs l10n — what’s the diff?
• Internationalization: Understanding Locale in the Java Platform.
Pacote de Recursos (Resource Bundle)
35
https://www.baeldung.com/java-8-localization
https://docs.oracle.com/javase/tutorial/i18n/intro/index.html
https://blog.mozilla.org/l10n/2011/12/14/i18n-vs-l10n-whats-the-diff/
http://www.oracle.com/us/technologies/java/locale-140624.html
Objetivo
Build a resource bundle for a locale and call a resource bundle from an application.
-
Construa um resource bundle (conjunto de recursos) para um Locale e invoque um
resource bundle a partir de uma aplicação.
É esperado que o candidato saiba compreender e analisar o uso de resource bundles e sua relação
com a classe Locale.
Ao codificar uma aplicação com internacionalização é comum o uso de resource bundles, ou
"conjunto de recursos" em português. São arquivos, geralmente .properties ou classes Java, que
armazenam Strings. Cada arquivo contém Strings em idiomas, ou Locales, diferentes.
Antes de continuar, entenda a execução do método main no exemplo a seguir e o que é apresentado
no console após sua execução.
src/org/j6toj8/localization/resourcebundle/ResourceBundle_Complete.java
public static void main(String[] args) {
  Locale.setDefault(new Locale("en", "US"));
  System.out.println("\n -- Locale padrão (en_US) -- ");
  ResourceBundle bundleDefault = ResourceBundle.getBundle("Text");
  Set<String> keySetDefault = bundleDefault.keySet();
  for (String string : keySetDefault) {
  System.out.println(string + " - " + bundleDefault.getString(string));
  }
  System.out.println("\n -- Locale es_ES -- ");
  ResourceBundle bundleEsEs = ResourceBundle.getBundle("Text", new Locale("es",
"ES"));
  Set<String> keySetEsEs = bundleEsEs.keySet();
  for (String string : keySetEsEs) {
  System.out.println(string + " - " + bundleEsEs.getString(string));
  }
  System.out.println("\n -- Locale pt_BR -- ");
  ResourceBundle bundlePtBr = ResourceBundle.getBundle("Text", new Locale("pt",
"BR"));
  Set<String> keySetPtBr = bundlePtBr.keySet();
  for (String string : keySetPtBr) {
  System.out.println(string + " - " + bundlePtBr.getString(string));
  }
}
36
../../../resources/Text.properties
phone=phone
tripod tripod
pen:pen
keyboard=keyboard
glass=glass
sticker sticker
paper:paper
rubber rubber
../../../resources/Text_pt.properties
  paper = papel
../../../resources/Text_pt_BR.properties
#arquivo do locale pt_BR
pen=caneta
../../../resources/Text_es.properties
keyboard=tec\
lado
../../../resources/Text_es_ES.properties
!arquivo do locale es_ES
glass=\tvaso
37
Saída no console
 -- Locale padrão (en_US) --
tripod - tripod
keyboard - keyboard
glass - glass
paper - paper
phone - phone
rubber - rubber
sticker - sticker
pen - pen
 -- Locale es_ES --
tripod - tripod
keyboard - teclado
glass - vaso
paper - paper
phone - phone
rubber - rubber
sticker - sticker
pen - pen
 -- Locale pt_BR --
tripod - tripod
keyboard - keyboard
glass - glass
paper - papel
phone - phone
rubber - rubber
pen - caneta
sticker - sticker
1. O nome do Locale é o sufixo do nome do arquivo, e o resource bundle padrão não tem sufixo.
Exemplos:
◦ Text.properties → Locale padrão
◦ Text_pt_BR.properties → Locale pt_BR
◦ Text_pt.properties → Locale pt
◦ Text_es_ES.properties → Locale es_ES
◦ Text_es.properties → Locale es
2. O arquivo .properties pode ser expresso com 3 separadores diferentes: = (igual), : (dois pontos)
ou um espaço em branco.
38
../../../resources/Text.properties
phone=phone
tripod tripod
pen:pen
keyboard=keyboard
glass=glass
sticker sticker
paper:paper
rubber rubber
O mais comum é utilizar o = para separar as propriedades, mas as 3 funcionam da mesma
forma.
3. Em arquivos .properties, linhas que começam com # ou ! são comentários.
../../../resources/Text_pt_BR.properties
#arquivo do locale pt_BR
pen=caneta
../../../resources/Text_es_ES.properties
!arquivo do locale es_ES
glass=\tvaso
4. Em arquivos .properties, apenas espaços no final da linha são considerados.
../../../resources/Text_pt.properties
  paper = papel
Neste exemplo, não é possível ver, mas existem 3 espaços no final da linha. O resultado é o
mesmo que escrever paper=papel{sp}{sp}{sp}.
5. Em arquivos .properties, se você terminar a linha com uma contrabarra, pode quebrar a linha.
../../../resources/Text_es.properties
keyboard=tec\
lado
Neste exemplo, seria o mesmo que escrever em uma única linha: keyboard=teclado.
6. Em arquivos .properties,você também pode usar os caracteres java como \t e \n.
39
../../../resources/Text_es_ES.properties
!arquivo do locale es_ES
glass=\tvaso
Neste exemplo, existe uma tabulação antes da palavra vaso. Você pode perceber no primeiro
exemplo deste capítulo que a palavra vaso foi impressa no console com uma tabulação à
esquerda.
7. Você pode recuperar todas as chaves e valores do resource bundle programaticamente.
src/org/j6toj8/localization/resourcebundle/ResourceBundle_KeysProgrammatically.java
public static void main(String[] args) {
  Locale.setDefault(new Locale("en", "US")); // Coloca o Locale en_US como padrão
  ResourceBundle bundle = ResourceBundle.getBundle("Text", new Locale("pt", "BR"));
// Recupera o bundle 'Text' para o Locale pt_BR
  Set<String> keySet = bundle.keySet(); // Pega um Set com todas as chaves
  for (String key : keySet) {
  System.out.println(key + " - " + bundle.getString(key)); // Imprime "<chave> -
<valor>"
  }
}
Saída no console
tripod - tripod
keyboard - keyboard
glass - glass
paper - papel
phone - phone
rubber - rubber
pen - caneta
sticker - sticker
8. O resource bundle também pode ser uma classe Java.
40
resource/Text_fr_CA.java
import java.util.ListResourceBundle;
public class Text_fr_CA extends ListResourceBundle {
  @Override
  protected Object[][] getContents() {
  return new Object[][] {
  {"pen", "stylo"},
  {"glass", "verre"},
  {"keyboard", "clavier"}
  };
  }
}
src/org/j6toj8/localization/resourcebundle/ResourceBundle_JavaBundle.java
ResourceBundle bundle = ResourceBundle.getBundle("Text", new Locale("fr", "CA"));
System.out.println(bundle.getString("glass"));
Saída no console
verre
9. Ao utilizar classes Java, uma vantagem é poder armazenar valores que não sejam apenas
String.
resource/Text_fr_FR.java
import java.math.BigDecimal;
import java.util.ListResourceBundle;
public class Text_fr_FR extends ListResourceBundle {
  @Override
  protected Object[][] getContents() {
  return new Object[][] {
  {"ten", new BigDecimal("10")}
  };
  }
}
10. A nomenclatura do arquivo é a mesma para classes Java e arquivos .properties, mudando
apenas a extensão.
Veja que os arquivos .properties se chamam Text_xx_XX.properties, e os arquivos .java se
chamam Text_xx_XX.java. Programaticamente, ambos são utilizados da mesma forma.
41
11. Se houver um arquivo .properties e uma classe Java para o mesmo Locale, a classe Java é
utilizada.
resource/Text_fr_CA.java
import java.util.ListResourceBundle;
public class Text_fr_CA extends ListResourceBundle {
  @Override
  protected Object[][] getContents() {
  return new Object[][] {
  {"pen", "stylo"},
  {"glass", "verre"},
  {"keyboard", "clavier"}
  };
  }
}
resource/Text_fr_CA.properties
pen=stylo-in-ignored-properties
glass=stylo-in-ignored-properties
keyboard=stylo-in-ignored-properties
src/org/j6toj8/localization/resourcebundle/ResourceBundle_JavaClassTakesPrecedence.java
/*
 * Recupera o Bundle do arquivo "Text_fr_CA.java",
 * pois tem precedência sobre o arquivo "Text_fr_CA.properties"
 */
ResourceBundle bundle = ResourceBundle.getBundle("Text", new Locale("fr", "CA"));
System.out.println(bundle.getString("pen"));
System.out.println(bundle.getString("glass"));
System.out.println(bundle.getString("keyboard"));
Saída no console
stylo
verre
clavier
Veja que os valores apresentados no console são aqueles definidos no arquivo Text_fr_CA.java,
mostrando que a classe Java tem precedência sobre um arquivo .properties para o mesmo
Locale.
12. Ao buscar por um resource bundle, o Java tenta encontrar um arquivo com o Locale exato. Se
não encontrar, busca na seguinte ordem:
42
a. Um arquivo do mesmo idioma, mas sem o país;
b. Um arquivo do Locale padrão;
c. Um arquivo do Locale padrão, mas sem o país;
d. Um arquivo sem Locale, que é o resource bundle padrão;
e. Lança MissingResourceException caso não encontre.
Por exemplo, ao executar a aplicação com o Locale padrão en_US, e solicitar um Locale pt_BR,
a ordem de busca do resource bundle seria a seguinte:
i. Text_pt_BR → Locale exato
ii. Text_pt → Locale solicitado, sem o país
iii. Text_en_US → Locale padrão
iv. Text_en → Locale padrão, sem o país
v. Text → Resource Bundle padrão
src/org/j6toj8/localization/resourcebundle/ResourceBundle_NotExactLocale.java
Locale.setDefault(new Locale("pt", "BR")); // pt_BR como Locale padrão
ResourceBundle bundle2 = ResourceBundle.getBundle("Text", new Locale("zh",
"CN"));
System.out.println(bundle2.getLocale()); // Bundle localizado para o Locale
"zh_CH" (Chinês simplificado)
ResourceBundle bundle = ResourceBundle.getBundle("Text", new Locale("it",
"CH"));
System.out.println(bundle.getLocale()); // Bundle localizado para o Locale
"it_CH" (Italiano da Suíça)
Saída no console
pt_BR
it
Veja que o Locale padrão é pt_BR. Por isso ele foi utilizado ao solicitar um resource bundle
para zh_CN, pois não existe um bundle para esse Locale.
Por outro lado, ao solicitar um resource bundle para o Locale it_CH, ele encontrou o mais
próximo, que seria o Locale it, mas sem um país específico.
13. Os arquivos mais específicos herdam as chaves e valores de arquivos mais genéricos, caso eles
não as tenham.
43
src/org/j6toj8/localization/resourcebundle/ResourceBundle_Inheritance.java
Locale.setDefault(new Locale("en", "US")); // pt_BR como Locale padrão
ResourceBundle bundle = ResourceBundle.getBundle("Text", new Locale("pt", "BR"));
System.out.println("Locale: " + bundle.getLocale()); // Bundle localizado para o
Locale "pt_BR" (Português do Brasil)
System.out.println(bundle.getObject("pen"));
System.out.println(bundle.getObject("paper"));
System.out.println(bundle.getObject("keyboard"));
../../../resources/Text.properties
phone=phone
tripod tripod
pen:pen
keyboard=keyboard
glass=glass
sticker sticker
paper:paper
rubber rubber
../../../resources/Text_pt.properties
  paper = papel
../../../resources/Text_pt_BR.properties
#arquivo do locale pt_BR
pen=caneta
Saída no console
Locale: pt_BR
caneta
papel
keyboard
Veja que nesse exemplo foi localizado um resource bundle com o Locale exato pt_BR. Porém, nem
todas as chaves foram encontradas nesse arquivo:
◦ caneta foi localizado no arquivo Text_pt_BR.properties
◦ papel foi localizado no arquivo Text_pt.properties
◦ keyboard foi localizado no arquivo Text.properties
44
Referências
• Using a Resource Bundle
Boyarsky, Jeanne; Selikoff, Scott. OCP: Oracle Certified Professional Java SE 8 Programmer
II Study Guide (p. 258). Wiley. Edição do Kindle.
• A Guide to the ResourceBundle.
• Class ResourceBundle. Java Documentation.
• About the ResourceBundle Class. Java Documentation.
Data e Hora
Objetivo
Create and manage date- and time-based events by using LocalDate, LocalTime,
LocalDateTime, Instant, Period, and Duration, including a combination of date and time
in a single object.
-
Crie e gerencie eventos baseados em data e hora utilizando LocalDate, LocalTime,
LocalDateTime, Instant, Period, e Duration, incluindo combinação de data e hora em um
único objeto.
O Java 8 possui uma forma totalmente nova de lidar com data e hora. Várias classes novas foram
introduzidas no pacote java.time.*. Vejamos a seguir alguns exemplos no formado ISO-8601.
• LocalDate → Data sem fuso horário, como 2007-12-03.
• LocalTime → Hora sem fuso horário, como 10:15:30.125.
• LocalDateTime → Uma data com hora sem fuso horário, como 2007-12-03T10:15:30.125.
• ZonedDateTime → Uma data com hora e com fuso horário, como 2007-12-03T10:15:30.125+01:00
Europe/Paris.
• Instant → Um ponto na linha do tempo, um instante.
• Period → Uma quantidade de tempo baseado em data, como "2 anos, 3 meses and 4 dias".
• Duration → Uma quantidade de tempo baseado em hora, como "34,5 segundos".
Essas novas classes foram melhor projetadas para lidar com os conceitos de data, hora e tempo. As
classes antigas, java.util.Date e java.util.Calendar, não caem na prova de certificação.Quase todas essas classes serão apresentadas nessa seção. A única exceção é ZonedDateTime, que será
apresentada na seção de fusos horários e horário de verão.
Todas as novas classes são imutáveis e thread safe. Ou seja, não é necessário se preocupar com
concorrência.
45
https://www.baeldung.com/java-resourcebundle
https://docs.oracle.com/javase/7/docs/api/java/util/ResourceBundle.html
https://docs.oracle.com/javase/tutorial/i18n/resbundle/concept.html
https://pt.wikipedia.org/wiki/Objeto_imut%C3%A1vel
https://pt.wikipedia.org/wiki/Thread_safety
LocalDate
Um LocalDate representa uma data sem fuso horário, como 2007-12-03.
1. A prova geralmente irá utilizar datas no formato americano: mes/dia/ano.
2. É possível criar um LocalDate através do método static chamado now.
src/org/j6toj8/localization/datetime/localdate/LocalDate_Now.java
System.out.println(LocalDate.now());
Saída no console
2019-05-20
A saída no console irá apresentar a data atual.
3. Também é possível criar um LocalDate através do método static chamado of.
4. Você pode utilizar o enum Month ou um int para representar o mês.
5. Diferente das APIs antigas do Java, o mês agora começa no número 1, que é Janeiro.
src/org/j6toj8/localization/datetime/localdate/LocalDate_Of.java
System.out.println(LocalDate.of(2019, 5, 20));
System.out.println(LocalDate.of(2019, Month.MAY, 20));
Saída no console
2019-05-20
2019-05-20
6. Assim como todas a novas classes de data e hora, não é possível criar uma instância de
LocalDate utilizando o construtor.
src/org/j6toj8/localization/datetime/localdate/LocalDate_Constructor.java
LocalDate localDate = new LocalDate(); // NÃO COMPILA! - não possui construtor
padrão
System.out.println(localDate);
7. Será lançada a exceção DateTimeException ao tentar criar uma data inválida.
src/org/j6toj8/localization/datetime/localdate/LocalDate_Invalid.java
System.out.println(LocalDate.of(2019, Month.MAY, 33));
46
Saída no console
Exception in thread "main" java.time.DateTimeException: Invalid value for
DayOfMonth (valid values 1 - 28/31): 33
  at java.time.temporal.ValueRange.checkValidValue(ValueRange.java:311)
  at java.time.temporal.ChronoField.checkValidValue(ChronoField.java:703)
  at java.time.LocalDate.of(LocalDate.java:248)
  at
org.j6toj8.localization.datetime.localdate.LocalDate_Invalid.main(LocalDate_Invalid
.java:10)
8. Existem vários métodos para somar e subtrair de LocalDate.
src/org/j6toj8/localization/datetime/localdate/LocalDate_Manipulate.java
LocalDate localDate = LocalDate.of(2019, Month.MAY, 20);
System.out.println(localDate);
System.out.println("+2 dias: " + localDate.plusDays(2));
System.out.println("+2 semanas: " + localDate.plusWeeks(2));
System.out.println("+2 meses: " + localDate.plusMonths(2));
System.out.println("+2 anos: " + localDate.plusYears(2));
System.out.println("+2 décadas: " + localDate.plus(2, ChronoUnit.DECADES));
System.out.println("-2 dias: " + localDate.minusDays(2));
System.out.println("-2 semanas: " + localDate.minusWeeks(2));
System.out.println("-2 meses: " + localDate.minusMonths(2));
System.out.println("-2 anos: " + localDate.minusYears(2));
System.out.println("-2 décadas: " + localDate.minus(2, ChronoUnit.DECADES));
Saída no console
2019-05-20
+2 dias: 2019-05-22
+2 semanas: 2019-06-03
+2 meses: 2019-07-20
+2 anos: 2021-05-20
+2 décadas: 2039-05-20
-2 dias: 2019-05-18
-2 semanas: 2019-05-06
-2 meses: 2019-03-20
-2 anos: 2017-05-20
-2 décadas: 1999-05-20
9. LocalDate é imutável, então é necessário armazenar o retorno de uma alteração em uma
variável.
47
src/org/j6toj8/localization/datetime/localdate/LocalDate_Immutability.java
LocalDate localDate = LocalDate.of(2019, Month.MAY, 20);
System.out.println(localDate);
localDate.plusDays(1); // chamada perdida - a nova data não foi armazenada em uma
variável
System.out.println(localDate);
localDate = localDate.plusDays(1); // chamada útil - data armazenada na variável
System.out.println(localDate);
Saída no console
2019-05-20
2019-05-20
2019-05-21
10. É comum utilizar o encadeamento de chamadas com esses métodos.
src/org/j6toj8/localization/datetime/localdate/LocalDate_Chaining.java
LocalDate localDate = LocalDate.of(2019, Month.MAY, 20);
System.out.println(localDate);
System.out.println(localDate.plusDays(1).plusMonths(1).plusYears(1));
Saída no console
2019-05-20
2020-06-21
11. Ao manipular a data, o LocalDate irá manipular os meses e anos conforme necessário.
src/org/j6toj8/localization/datetime/localdate/LocalDate_AdjustDifferentUnit.java
LocalDate localDate = LocalDate.of(2019, Month.NOVEMBER, 30);
System.out.println(localDate);
System.out.println(localDate.plusDays(1)); // + 1 dia, vira o mês
System.out.println(localDate.plusDays(32)); // + 32 dias, vira o ano
System.out.println(localDate.plusMonths(2)); // + 2 meses, vira o ano
Saída no console
2019-11-30
2019-12-01
2020-01-01
2020-01-30
48
LocalTime
Um LocalTime representa uma hora sem fuso horário e sem data, como 10:15:30.125.
1. A hora é representada no formato hora:minuto:segundo.nano.
2. É possível criar um LocalTime através do método static chamado now.
src/org/j6toj8/localization/datetime/localtime/LocalTime_Now.java
System.out.println(LocalTime.now());
Saída no console
09:15:23.197
A saída no console irá apresentar a hora atual.
3. Também é possível criar um LocalTime através do método static chamado of.
src/org/j6toj8/localization/datetime/localtime/LocalTime_Of.java
System.out.println(LocalTime.of(9, 20, 1, 135000000));
System.out.println(LocalTime.of(9, 20, 1, 135));
System.out.println(LocalTime.of(9, 20, 1));
System.out.println(LocalTime.of(9, 20));
Saída no console
09:20:01.135
09:20:01.000000135
09:20:01
09:20
4. Assim como todas a novas classes de data e hora, não é possível criar uma instância de
LocalTime utilizando o construtor.
src/org/j6toj8/localization/datetime/localtime/LocalTime_Constructor.java
LocalTime localTime = new LocalTime(); // NÃO COMPILA! - não possui construtor
padrão
System.out.println(localTime);
5. Será lançada a exceção DateTimeException ao tentar criar uma hora inválida.
49
src/org/j6toj8/localization/datetime/localtime/LocalTime_Invalid.java
System.out.println(LocalTime.of(24, 2, 3)); // lança exceção: a hora deve estar
entre 0 e 23
Saída no console
Exception in thread "main" java.time.DateTimeException: Invalid value for HourOfDay
(valid values 0 - 23): 24
  at java.time.temporal.ValueRange.checkValidValue(ValueRange.java:311)
  at java.time.temporal.ChronoField.checkValidValue(ChronoField.java:703)
  at java.time.LocalTime.of(LocalTime.java:317)
  at
org.j6toj8.localization.datetime.localtime.LocalTime_Invalid.main(LocalTime_Invalid
.java:9)
6. Existem vários métodos para somar e subtrair de LocalTime.
src/org/j6toj8/localization/datetime/localtime/LocalTime_Manipulate.java
LocalTime localTime = LocalTime.of(9, 26, 12);
System.out.println(localTime);
System.out.println("+2 horas: " + localTime.plusHours(2));
System.out.println("+2 minutos: " + localTime.plusMinutes(2));
System.out.println("+2 segundos: " + localTime.plusSeconds(2));
System.out.println("+2 nanosegundos: " + localTime.plusNanos(2));
System.out.println("+2 microssegundos: " + localTime.plus(2, ChronoUnit.MICROS));
System.out.println("+2 milissegundos: " + localTime.plus(2, ChronoUnit.MILLIS));
System.out.println("-2 horas: " + localTime.minusHours(2));
System.out.println("-2 minutos: " + localTime.minusMinutes(2));
System.out.println("-2 segundos: " + localTime.minusSeconds(2));
System.out.println("-2 nanosegundos: " + localTime.minusNanos(2));
System.out.println("-2 microssegundos: " + localTime.minus(2, ChronoUnit.MICROS));
System.out.println("-2 milissegundos: " + localTime.minus(2, ChronoUnit.MILLIS));
50
Saída no console
09:26:12
+2 horas: 11:26:12
+2 minutos: 09:28:12
+2 segundos: 09:26:14
+2 nanosegundos: 09:26:12.000000002
+2 microssegundos: 09:26:12.000002
+2 milissegundos: 09:26:12.002
-2 horas: 07:26:12
-2 minutos: 09:24:12
-2 segundos: 09:26:10
-2 nanosegundos:09:26:11.999999998
-2 microssegundos: 09:26:11.999998
-2 milissegundos: 09:26:11.998
7. LocalTime é imutável, então é necessário armazenar o retorno de uma alteração em uma
variável.
src/org/j6toj8/localization/datetime/localtime/LocalTime_Immutability.java
LocalTime localTime = LocalTime.of(9, 31, 5);
System.out.println(localTime);
localTime.plusHours(1); // chamada perdida - a nova hora não foi armazenada em uma
variável
System.out.println(localTime);
localTime = localTime.plusHours(1); // chamada útil - hora armazenada na variável
System.out.println(localTime);
Saída no console
09:31:05
09:31:05
10:31:05
8. É comum utilizar o encadeamento de chamadas com esses métodos.
src/org/j6toj8/localization/datetime/localtime/LocalTime_Chaining.java
LocalTime localTime = LocalTime.of(9, 32, 5);
System.out.println(localTime);
System.out.println(localTime.plusHours(1).plusMinutes(1).plusSeconds(1).plusNanos(1
000000));
Saída no console
09:32:05
10:33:06.001
51
9. Ao manipular a hora, o LocalTime irá manipular as horas, minutos e segundos conforme
necessário.
src/org/j6toj8/localization/datetime/localtime/LocalTime_AdjustDifferentUnit.java
LocalTime localTime = LocalTime.of(9, 59, 59);
System.out.println(localTime);
System.out.println(localTime.plusSeconds(2)); // + 2 segundos, vira o minuto
System.out.println(localTime.plusSeconds(62)); // + 62 segundos, vira a hora
System.out.println(localTime.plusMinutes(2)); // + 2 minutos, vira a hora
System.out.println(localTime.minusNanos(1000000000)); // - 1 segundo (em nanos),
vira o minuto
Saída no console
09:59:59
10:00:01
10:01:01
10:01:59
09:59:58
LocalDateTime
Um LocalDateTime representa uma data com hora, mas sem fuso horário, como 2007-12-
03T10:15:30.125.
As regras para o LocalDateTime são basicamente a junção daquelas para LocalDate e LocalTime.
1. O LocalDateTime é apresentado no formato ano-mes-diaThora:minuto:segundo.nano.
2. É possível criar um LocalDateTime através do método static chamado now.
src/org/j6toj8/localization/datetime/localdatetime/LocalDateTime_Now.java
System.out.println(LocalDateTime.now());
Saída no console
2019-05-24T10:13:58.370
A saída no console irá apresentar a data e hora atual.
3. Também é possível criar um LocalDateTime através do método static chamado of.
52
src/org/j6toj8/localization/datetime/localdatetime/LocalDateTime_Of.java
System.out.println(LocalDateTime.of(LocalDate.of(2019, 5, 20), LocalTime.of(9, 20,
12)));
System.out.println(LocalDateTime.of(2019, 5, 20, 9, 20));
System.out.println(LocalDateTime.of(2019, Month.MAY, 20, 9, 20));
System.out.println(LocalDateTime.of(2019, 5, 20, 9, 20, 12));
System.out.println(LocalDateTime.of(2019, Month.MAY, 20, 9, 20, 12));
System.out.println(LocalDateTime.of(2019, 5, 20, 9, 20, 12, 135));
System.out.println(LocalDateTime.of(2019, Month.MAY, 20, 9, 20, 12, 135));
Saída no console
2019-05-20T09:20:12
2019-05-20T09:20
2019-05-20T09:20
2019-05-20T09:20:12
2019-05-20T09:20:12
2019-05-20T09:20:12.000000135
2019-05-20T09:20:12.000000135
4. Assim como todas a novas classes de data e hora, não é possível criar uma instância de
LocalDateTime utilizando o construtor.
src/org/j6toj8/localization/datetime/localdatetime/LocalDateTime_Constructor.java
LocalDateTime localDateTime = new LocalDateTime(); // NÃO COMPILA! - não possui
construtor padrão
System.out.println(localDateTime);
5. Será lançada a exceção DateTimeException ao tentar criar uma data ou hora inválida.
src/org/j6toj8/localization/datetime/localdatetime/LocalDateTime_Invalid.java
System.out.println(LocalDateTime.of(2019, 4, 31, 9, 20)); // lança exceção: não
existe 31 de abril
Saída no console
Exception in thread "main" java.time.DateTimeException: Invalid date 'APRIL 31'
  at java.time.LocalDate.create(LocalDate.java:431)
  at java.time.LocalDate.of(LocalDate.java:269)
  at java.time.LocalDateTime.of(LocalDateTime.java:311)
  at
org.j6toj8.localization.datetime.localdatetime.LocalDateTime_Invalid.main(LocalDate
Time_Invalid.java:10)
6. Existem vários métodos para somar e subtrair de LocalDateTime. São basicamente todos os
53
disponíveis para LocalDate e LocalTime.
src/org/j6toj8/localization/datetime/localdatetime/LocalDateTime_Manipulate.java
LocalDateTime localDateTime = LocalDateTime.of(2019, 5, 20, 9, 20, 12);
System.out.println(localDateTime);
System.out.println("+2 horas: " + localDateTime.plusHours(2));
System.out.println("+2 minutos: " + localDateTime.plusMinutes(2));
System.out.println("+2 segundos: " + localDateTime.plusSeconds(2));
System.out.println("+2 nanosegundos: " + localDateTime.plusNanos(2));
System.out.println("+2 microssegundos: " + localDateTime.plus(2, ChronoUnit.
MICROS));
System.out.println("+2 milissegundos: " + localDateTime.plus(2, ChronoUnit.
MILLIS));
System.out.println("-2 horas: " + localDateTime.minusHours(2));
System.out.println("-2 minutos: " + localDateTime.minusMinutes(2));
System.out.println("-2 segundos: " + localDateTime.minusSeconds(2));
System.out.println("-2 nanosegundos: " + localDateTime.minusNanos(2));
System.out.println("-2 microssegundos: " + localDateTime.minus(2, ChronoUnit.
MICROS));
System.out.println("-2 milissegundos: " + localDateTime.minus(2, ChronoUnit.
MILLIS));
System.out.println("+2 dias: " + localDateTime.plusDays(2));
System.out.println("+2 semanas: " + localDateTime.plusWeeks(2));
System.out.println("+2 meses: " + localDateTime.plusMonths(2));
System.out.println("+2 anos: " + localDateTime.plusYears(2));
System.out.println("+2 décadas: " + localDateTime.plus(2, ChronoUnit.DECADES));
System.out.println("-2 dias: " + localDateTime.minusDays(2));
System.out.println("-2 semanas: " + localDateTime.minusWeeks(2));
System.out.println("-2 meses: " + localDateTime.minusMonths(2));
System.out.println("-2 anos: " + localDateTime.minusYears(2));
System.out.println("-2 décadas: " + localDateTime.minus(2, ChronoUnit.DECADES));
54
Saída no console
2019-05-20T09:20:12
+2 horas: 2019-05-20T11:20:12
+2 minutos: 2019-05-20T09:22:12
+2 segundos: 2019-05-20T09:20:14
+2 nanosegundos: 2019-05-20T09:20:12.000000002
+2 microssegundos: 2019-05-20T09:20:12.000002
+2 milissegundos: 2019-05-20T09:20:12.002
-2 horas: 2019-05-20T07:20:12
-2 minutos: 2019-05-20T09:18:12
-2 segundos: 2019-05-20T09:20:10
-2 nanosegundos: 2019-05-20T09:20:11.999999998
-2 microssegundos: 2019-05-20T09:20:11.999998
-2 milissegundos: 2019-05-20T09:20:11.998
+2 dias: 2019-05-22T09:20:12
+2 semanas: 2019-06-03T09:20:12
+2 meses: 2019-07-20T09:20:12
+2 anos: 2021-05-20T09:20:12
+2 décadas: 2039-05-20T09:20:12
-2 dias: 2019-05-18T09:20:12
-2 semanas: 2019-05-06T09:20:12
-2 meses: 2019-03-20T09:20:12
-2 anos: 2017-05-20T09:20:12
-2 décadas: 1999-05-20T09:20:12
7. LocalDateTime é imutável, então é necessário armazenar o retorno de uma alteração em uma
variável.
src/org/j6toj8/localization/datetime/localdatetime/LocalDateTime_Immutability.java
LocalDateTime localDateTime = LocalDateTime.of(2019, 5, 20, 9, 20);
System.out.println(localDateTime);
localDateTime.plusHours(1); // chamada perdida - a nova data/hora não foi
armazenada em uma variável
System.out.println(localDateTime);
localDateTime = localDateTime.plusHours(1); // chamada útil - data/hora armazenada
na variável
System.out.println(localDateTime);
Saída no console
2019-05-20T09:20
2019-05-20T09:20
2019-05-20T10:20
8. É comum utilizar o encadeamento de chamadas com esses métodos.
55
src/org/j6toj8/localization/datetime/localdatetime/LocalDateTime_Chaining.java
LocalDateTime localDateTime = LocalDateTime.of(2019, 5, 20, 9, 20);
System.out.println(localDateTime);
System.out.println(localDateTime.plusDays(1).plusHours(1).plusYears(1));
Saída no console
2019-05-20T09:20
2020-05-21T10:20
9. Ao manipular a data ou hora, o LocalDateTime irá manipular os outros campos conforme
necessário.
src/org/j6toj8/localization/datetime/localdatetime/LocalDateTime_AdjustDifferentUnit.java
LocalDateTime localDateTime = LocalDateTime.of(2019, 12, 31, 23, 59, 59);
System.out.println(localDateTime);
System.out.println(localDateTime.plusSeconds(2));

Continue navegando