Java para Iniciantes: 100 Exemplos que Você Pode Compilar e Executar
Java roda no Android, em servidores de empresas e em sistemas bancários. Este artigo ensina a linguagem por meio de 100 programas curtos. Cada programa é compilado com javac 17 e executado, e a saída real aparece logo após o código. Os exemplos começam com impressão de texto e armazenamento de valores e avançam até classes, coleções, exceções, lambdas e streams. Leia a explicação de cada grupo e depois digite você mesmo cada exemplo, porque digitar os programas é a forma mais rápida de aprender.
O que você precisa
Instale o JDK 17 ou mais recente, que oferece o javac (compilador) e o java (executor). Verifique a instalação com javac -version e java -version. Um editor de texto simples basta. Não é preciso experiência em programação, mas o primeiro exemplo supõe que você saiba o que são números e palavras.
Como compilar e executar
javac -encoding UTF-8 -d out src/Ex001HelloWorld.java
java -Dfile.encoding=UTF-8 -cp out Ex001HelloWorld
Ilustração
Tópico 1: Saída, variáveis e tipos
Todo programa Java começa com uma classe e um método main. Estes exemplos mostram como imprimir texto, guardar valores em variáveis e escolher o tipo certo para cada valor.
Estrutura do programa
Um arquivo Java contém uma classe, e essa classe contém public static void main(String[] args). A JVM chama main primeiro. System.out.println imprime uma linha e passa para a seguinte, enquanto System.out.print continua na mesma linha. O nome do arquivo deve ser igual ao nome da classe pública, então Ex001HelloWorld.java contém a classe Ex001HelloWorld.
Tipos primitivos
int guarda inteiros de cerca de -2,1 bilhões a 2,1 bilhões, long guarda inteiros maiores, double guarda decimais com cerca de 15 dígitos significativos, boolean guarda true ou false, e char guarda um caractere Unicode. O Java verifica os tipos na compilação, então int x = 3.5; é um erro de compilação, e não um corte silencioso.
var e blocos de texto
var deixa o compilador deduzir o tipo a partir do valor à direita, como em var n = 10;. O tipo continua sendo int e não pode mudar depois. Blocos de texto, escritos entre três aspas duplas, deixam textos com várias linhas fáceis de ler. Números decimais não são exatos em binário: 0.1 + 0.2 resulta em 0.30000000000000004, então compare decimais com uma pequena tolerância.
Exemplo 1: Olá, mundo
Imprima a primeira mensagem com System.out.println.
public class Ex001HelloWorld {
public static void main(String[] args) {
System.out.println("Hello, World!");
}
}
Saída:
Hello, World!
Exemplo 2: Imprimindo linhas
print, println e caracteres de escape como tabulação e aspas.
public class Ex002PrintLines {
public static void main(String[] args) {
System.out.println("First line");
System.out.print("Same line, ");
System.out.println("continued");
System.out.println("Tab:\tafter tab");
System.out.println("Quote: \"hello\"");
}
}
Saída:
First line
Same line, continued
Tab: after tab
Quote: "hello"
Exemplo 3: Variáveis
Guarde valores em variáveis e altere-os.
public class Ex003Variables {
public static void main(String[] args) {
int apples = 5;
int bought = 3;
apples = apples + bought;
System.out.println("Apples now: " + apples);
}
}
Saída:
Apples now: 8
Exemplo 4: Tipos inteiros
byte, int e long, e o que acontece quando um int estoura.
public class Ex004IntegerTypes {
public static void main(String[] args) {
byte small = 100;
int medium = 2_000_000_000;
long big = 9_000_000_000L;
System.out.println("byte: " + small);
System.out.println("int: " + medium);
System.out.println("long: " + big);
int overflow = Integer.MAX_VALUE;
overflow = overflow + 1;
System.out.println("overflow: " + overflow);
}
}
Saída:
byte: 100
int: 2000000000
long: 9000000000
overflow: -2147483648
Exemplo 5: Números decimais
double e float, e por que 0.1 + 0.2 não é exatamente 0.3.
public class Ex005Floating {
public static void main(String[] args) {
double a = 0.1 + 0.2;
System.out.println("0.1 + 0.2 = " + a);
float f = 1.5f;
System.out.println("float: " + f);
System.out.println("rounded: " + Math.round(a * 100) / 100.0);
}
}
Saída:
0.1 + 0.2 = 0.30000000000000004
float: 1.5
rounded: 0.3
Exemplo 6: Valores booleanos
true e false, e como imprimir o resultado de um boolean.
public class Ex006Booleans {
public static void main(String[] args) {
boolean isJavaFun = true;
boolean isRaining = false;
System.out.println("Java is fun: " + isJavaFun);
System.out.println("Raining: " + isRaining);
System.out.println("Not raining: " + !isRaining);
}
}
Saída:
Java is fun: true
Raining: false
Not raining: true
Exemplo 7: Caracteres
Um char guarda um caractere, e seu código Unicode pode ser lido.
public class Ex007Chars {
public static void main(String[] args) {
char letter = 'A';
char next = (char) (letter + 1);
System.out.println("letter: " + letter);
System.out.println("next: " + next);
System.out.println("code of A: " + (int) letter);
char accented = 'é';
System.out.println("unicode char: " + accented);
}
}
Saída:
letter: A
next: B
code of A: 65
unicode char: é
Exemplo 8: Constantes
final cria um valor que não pode mudar depois de receber um valor.
public class Ex008Constants {
static final double PI_APPROX = 3.14159;
public static void main(String[] args) {
final int MAX_USERS = 100;
System.out.println("Max users: " + MAX_USERS);
System.out.println("Pi: " + PI_APPROX);
}
}
Saída:
Max users: 100
Pi: 3.14159
Exemplo 9: A palavra-chave var
Java deduz o tipo a partir do valor à direita.
import java.util.ArrayList;
import java.util.List;
public class Ex009VarKeyword {
public static void main(String[] args) {
var name = "Budi";
var age = 25;
List<String> tags = new ArrayList<>();
tags.add("java");
System.out.println(name + " is " + age);
System.out.println("tags: " + tags);
}
}
Saída:
Budi is 25
tags: [java]
Exemplo 10: Bloco de texto
Uma string com várias linhas escrita entre três aspas.
public class Ex010TextBlocks {
public static void main(String[] args) {
String html = """
<html>
<body>Hello</body>
</html>
""";
System.out.print(html);
}
}
Saída:
<html>
<body>Hello</body>
</html>
Tópico 2: Operadores e conversão de tipos
Operadores combinam valores. Este grupo inclui aritmética, comparação, lógica, operações de bits e conversão entre tipos.
Aritmética e divisão inteira
+, -, *, / e % funcionam como esperado, mas dividir um int por outro int descarta a parte decimal: 7 / 2 resulta em 3. Escreva 7.0 / 2 ou converta um dos operandos para double para manter a parte decimal. O operador % dá o resto da divisão, e ++ e -- alteram a variável em uma unidade.
Operadores de comparação e lógicos
==, !=, <, >, <= e >= produzem um boolean. && e || usam curto-circuito, então o lado direito só é executado quando necessário. Um erro comum é usar == para comparar strings. Isso compara a identidade do objeto, então use equals para texto.
Operações de bits, deslocamento e cast
&, |, ^ e ~ atuam sobre bits individuais. << e >> deslocam os bits para a esquerda e para a direita, o que multiplica ou divide por potências de dois. Um cast como (int) 9.99 resulta em 9, porque a parte decimal é cortada, e não arredondada.
Exemplo 11: Operadores aritméticos
+, -, *, / e % com inteiros.
public class Ex011Arithmetic {
public static void main(String[] args) {
int a = 17, b = 5;
System.out.println("a + b = " + (a + b));
System.out.println("a - b = " + (a - b));
System.out.println("a * b = " + (a * b));
System.out.println("a / b = " + (a / b));
System.out.println("a % b = " + (a % b));
}
}
Saída:
a + b = 22
a - b = 12
a * b = 85
a / b = 3
a % b = 2
Exemplo 12: Divisão inteira
Dividir dois ints descarta a parte decimal; use double para mantê-la.
public class Ex012IntegerDivision {
public static void main(String[] args) {
System.out.println("7 / 2 = " + (7 / 2));
System.out.println("7.0 / 2 = " + (7.0 / 2));
System.out.println("(double) 7 / 2 = " + ((double) 7 / 2));
System.out.println("-7 % 3 = " + (-7 % 3));
}
}
Saída:
7 / 2 = 3
7.0 / 2 = 3.5
(double) 7 / 2 = 3.5
-7 % 3 = -1
Exemplo 13: Incremento e decremento
++ e -- antes e depois do valor dão resultados diferentes.
public class Ex013IncrementDecrement {
public static void main(String[] args) {
int x = 5;
System.out.println("x++ gives " + x++ + ", now " + x);
System.out.println("++x gives " + ++x + ", now " + x);
System.out.println("x-- gives " + x-- + ", now " + x);
}
}
Saída:
x++ gives 5, now 6
++x gives 7, now 7
x-- gives 7, now 6
Exemplo 14: Atribuição composta
+=, -=, *= e /= atualizam a variável em um único passo.
public class Ex014CompoundAssignment {
public static void main(String[] args) {
int score = 10;
score += 5;
System.out.println("after += 5: " + score);
score *= 2;
System.out.println("after *= 2: " + score);
score -= 4;
System.out.println("after -= 4: " + score);
score /= 3;
System.out.println("after /= 3: " + score);
}
}
Saída:
after += 5: 15
after *= 2: 30
after -= 4: 26
after /= 3: 8
Exemplo 15: Operadores de comparação
==, !=, < e >= comparam valores e dão true ou false.
public class Ex015Comparison {
public static void main(String[] args) {
int a = 10, b = 20;
System.out.println("a == b: " + (a == b));
System.out.println("a != b: " + (a != b));
System.out.println("a < b: " + (a < b));
System.out.println("a >= b: " + (a >= b));
}
}
Saída:
a == b: false
a != b: true
a < b: true
a >= b: false
Exemplo 16: Operadores lógicos
&& (e), || (ou) e ! (não) combinam condições.
public class Ex016Logical {
public static void main(String[] args) {
boolean hasTicket = true;
boolean isAdult = false;
System.out.println("AND: " + (hasTicket && isAdult));
System.out.println("OR: " + (hasTicket || isAdult));
System.out.println("NOT: " + !hasTicket);
}
}
Saída:
AND: false
OR: true
NOT: false
Exemplo 17: Operadores bit a bit
&, |, ^ e ~ atuam sobre os bits de um inteiro.
public class Ex017Bitwise {
public static void main(String[] args) {
int a = 12; // 1100
int b = 10; // 1010
System.out.println("a & b = " + (a & b));
System.out.println("a | b = " + (a | b));
System.out.println("a ^ b = " + (a ^ b));
System.out.println("~a = " + (~a));
}
}
Saída:
a & b = 8
a | b = 14
a ^ b = 6
~a = -13
Exemplo 18: Operadores de deslocamento
<< e >> movem os bits; >>> preenche a esquerda com zeros.
public class Ex018Shifts {
public static void main(String[] args) {
int n = 5;
System.out.println("5 << 2 = " + (n << 2));
System.out.println("5 >> 1 = " + (n >> 1));
System.out.println("-8 >>> 28 = " + (-8 >>> 28));
}
}
Saída:
5 << 2 = 20
5 >> 1 = 2
-8 >>> 28 = 15
Exemplo 19: Conversão de tipos
Converta entre tipos com (int) e (double).
public class Ex019Casting {
public static void main(String[] args) {
double price = 19.99;
int whole = (int) price;
System.out.println("(int) 19.99 = " + whole);
long big = 100000L;
int small = (int) big;
System.out.println("long to int: " + small);
System.out.println("int to double: " + (double) 7 / 2);
}
}
Saída:
(int) 19.99 = 19
long to int: 100000
int to double: 3.5
Exemplo 20: Operador ternário
Escolha um de dois valores em uma linha com ?:.
public class Ex020Ternary {
public static void main(String[] args) {
int age = 17;
String status = age >= 18 ? "adult" : "minor";
System.out.println("Status: " + status);
int max = Math.max(3, 9);
System.out.println("Max: " + max);
}
}
Saída:
Status: minor
Max: 9
Tópico 3: Decisões com if e switch
Programas escolhem um caminho com if e switch. A partir do Java 14, também existem expressões switch, que devolvem um valor.
if, else if e else
As condições são testadas de cima para baixo, e a primeira ramificação verdadeira é executada. Coloque as verificações mais específicas primeiro. Se uma verificação ampla vier antes, ela captura o valor antes que a específica possa vê-lo.
Comando switch e expressão switch
O switch clássico precisa de break, senão a execução continua no case seguinte. Uma expressão switch com -> não passa para outros cases, e devolve um valor, então é mais segura e mais fácil de ler.
Operador ternário
condição ? a : b escolhe um dentre dois valores. É adequado para escolhas simples. Ternários aninhados são difíceis de ler, então use if quando houver mais de duas opções.
Exemplo 21: if, else if e else
Escolha uma ramificação de acordo com o valor.
public class Ex021IfElse {
public static void main(String[] args) {
int score = 72;
if (score >= 80) {
System.out.println("Grade A");
} else if (score >= 70) {
System.out.println("Grade B");
} else {
System.out.println("Grade C or lower");
}
}
}
Saída:
Grade B
Exemplo 22: Comando switch
Execute o código do case correspondente; break interrompe a continuação para o próximo case.
public class Ex022SwitchStatement {
public static void main(String[] args) {
int day = 3;
switch (day) {
case 1: System.out.println("Monday"); break;
case 2: System.out.println("Tuesday"); break;
case 3: System.out.println("Wednesday"); break;
default: System.out.println("Other day");
}
}
}
Saída:
Wednesday
Exemplo 23: Expressão switch
Devolva um valor do switch com a sintaxe de seta.
public class Ex023SwitchExpression {
public static void main(String[] args) {
String fruit = "apple";
int price = switch (fruit) {
case "apple" -> 10;
case "banana" -> 5;
default -> 0;
};
System.out.println(fruit + " costs " + price);
}
}
Saída:
apple costs 10
Tópico 4: Laços e instruções de desvio
Laços repetem um bloco de código. Escolha o laço adequado a cada tarefa: for quando a quantidade é conhecida, while para uma condição e for aprimorado para cada item de uma coleção.
for, while e do-while
for é adequado quando o número de voltas é conhecido. while verifica a condição antes de cada volta, então pode não executar nenhuma vez. do-while executa o corpo pelo menos uma vez e só depois verifica a condição.
for aprimorado
for (String s : list) visita cada item sem uma variável de índice. Não adicione nem remova itens de uma lista dentro desse laço, senão o Java lança ConcurrentModificationException.
break, continue e rótulos
break sai do laço imediatamente. continue pula para a próxima volta. Um rótulo como outer: permite que break saia de laços aninhados, o que um break comum não consegue fazer.
Exemplo 24: Laço while
Repita o corpo enquanto a condição for verdadeira.
public class Ex024WhileLoop {
public static void main(String[] args) {
int count = 1;
while (count <= 5) {
System.out.println("count = " + count);
count++;
}
}
}
Saída:
count = 1
count = 2
count = 3
count = 4
count = 5
Exemplo 25: Laço do-while
Execute o corpo pelo menos uma vez e depois verifique a condição.
public class Ex025DoWhileLoop {
public static void main(String[] args) {
int n = 10;
do {
System.out.println("runs once even though n = " + n);
n++;
} while (n < 5);
}
}
Saída:
runs once even though n = 10
Exemplo 26: Laço for
Conte com um índice; este exemplo soma os números de 1 a 10.
public class Ex026ForLoop {
public static void main(String[] args) {
int total = 0;
for (int i = 1; i <= 10; i++) {
total += i;
}
System.out.println("Sum 1..10 = " + total);
}
}
Saída:
Sum 1..10 = 55
Exemplo 27: for aprimorado
Visite cada item de um array sem usar índice.
public class Ex027EnhancedFor {
public static void main(String[] args) {
String[] colours = {"red", "green", "blue"};
for (String c : colours) {
System.out.println("colour: " + c);
}
}
}
Saída:
colour: red
colour: green
colour: blue
Exemplo 28: break
Saia do laço mais cedo quando uma condição for atendida.
public class Ex028BreakLoop {
public static void main(String[] args) {
for (int i = 1; i <= 10; i++) {
if (i == 4) {
System.out.println("Stop at " + i);
break;
}
System.out.println("i = " + i);
}
}
}
Saída:
i = 1
i = 2
i = 3
Stop at 4
Exemplo 29: continue
Pule o restante da volta atual e siga para a próxima.
public class Ex029ContinueLoop {
public static void main(String[] args) {
for (int i = 1; i <= 6; i++) {
if (i % 2 == 0) {
continue;
}
System.out.println("odd: " + i);
}
}
}
Saída:
odd: 1
odd: 3
odd: 5
Exemplo 30: break com rótulo
Saia de dois laços aninhados de uma só vez.
public class Ex030LabeledBreak {
public static void main(String[] args) {
outer:
for (int i = 1; i <= 3; i++) {
for (int j = 1; j <= 3; j++) {
if (i * j == 4) {
System.out.println("Found 4 at i=" + i + ", j=" + j);
break outer;
}
}
}
System.out.println("Done");
}
}
Saída:
Found 4 at i=2, j=2
Done
Tópico 5: Algoritmos com números
Programas pequenos que resolvem problemas clássicos mostram como laços, condições e aritmética trabalham juntos.
Contar e somar
Defina a variável de total como 0 antes do laço e some a ela dentro do laço. Para somar os dígitos, n % 10 dá o último dígito e n / 10 o remove. Repita até n virar 0.
Números primos, fatorial e Fibonacci
O teste de primalidade só precisa dividir até a raiz quadrada de n. Fatoriais e a sequência de Fibonacci crescem depressa, e o int estoura em 13! e depois do 46º número de Fibonacci, então use long, ou BigInteger para valores maiores.
Máximo divisor comum e palíndromo
O algoritmo de Euclides troca (a, b) por (b, a % b) até b virar zero, e então a é a resposta. A verificação de palíndromo inverte os dígitos e compara o resultado com o número original.
Exemplo 31: Tabuada
Laços aninhados imprimem uma pequena tabela de produtos.
public class Ex031MultiplicationTable {
public static void main(String[] args) {
for (int i = 1; i <= 3; i++) {
StringBuilder row = new StringBuilder();
for (int j = 1; j <= 5; j++) {
row.append(i * j).append('\t');
}
System.out.println(row.toString().trim());
}
}
}
Saída:
1 2 3 4 5
2 4 6 8 10
3 6 9 12 15
Exemplo 32: FizzBuzz
Um exercício clássico que usa divisibilidade por 3 e por 5.
public class Ex032FizzBuzz {
public static void main(String[] args) {
for (int i = 1; i <= 15; i++) {
if (i % 15 == 0) System.out.println("FizzBuzz");
else if (i % 3 == 0) System.out.println("Fizz");
else if (i % 5 == 0) System.out.println("Buzz");
else System.out.println(i);
}
}
}
Saída:
1
2
Fizz
4
Buzz
Fizz
7
8
Fizz
Buzz
11
Fizz
13
14
FizzBuzz
Exemplo 33: Soma dos dígitos
Use % e / para somar os dígitos de um número.
public class Ex033SumOfDigits {
public static void main(String[] args) {
int n = 98765;
int sum = 0;
while (n > 0) {
sum += n % 10;
n /= 10;
}
System.out.println("Digit sum = " + sum);
}
}
Saída:
Digit sum = 35
Exemplo 34: Teste de número primo
Teste divisores apenas até a raiz quadrada do número.
public class Ex034PrimeCheck {
static boolean isPrime(int n) {
if (n < 2) return false;
for (int i = 2; i * i <= n; i++) {
if (n % i == 0) return false;
}
return true;
}
public static void main(String[] args) {
for (int n : new int[]{1, 2, 9, 11, 29}) {
System.out.println(n + " prime? " + isPrime(n));
}
}
}
Saída:
1 prime? false
2 prime? true
9 prime? false
11 prime? true
29 prime? true
Exemplo 35: Números de Fibonacci
Imprima os dez primeiros números da sequência de Fibonacci.
public class Ex035Fibonacci {
public static void main(String[] args) {
long a = 0, b = 1;
for (int i = 0; i < 10; i++) {
System.out.print(a + " ");
long next = a + b;
a = b;
b = next;
}
System.out.println();
}
}
Saída:
0 1 1 2 3 5 8 13 21 34
Exemplo 36: Fatorial
Multiplique de 2 a 15 com long para o resultado não estourar.
public class Ex036Factorial {
public static void main(String[] args) {
long result = 1;
for (int i = 2; i <= 15; i++) {
result *= i;
}
System.out.println("15! = " + result);
}
}
Saída:
15! = 1307674368000
Exemplo 37: Máximo divisor comum
O algoritmo de Euclides com um laço.
public class Ex037GCD {
static int gcd(int a, int b) {
while (b != 0) {
int t = b;
b = a % b;
a = t;
}
return a;
}
public static void main(String[] args) {
System.out.println("gcd(48, 18) = " + gcd(48, 18));
System.out.println("gcd(17, 5) = " + gcd(17, 5));
}
}
Saída:
gcd(48, 18) = 6
gcd(17, 5) = 1
Exemplo 38: Número palíndromo
Inverta os dígitos e compare com o original.
public class Ex038Palindrome {
public static void main(String[] args) {
int original = 12321;
int n = original, reversed = 0;
while (n > 0) {
reversed = reversed * 10 + n % 10;
n /= 10;
}
System.out.println(original + " palindrome? " + (original == reversed));
}
}
Saída:
12321 palindrome? true
Exemplo 39: Contando vogais
Percorra os caracteres e conte a, e, i, o e u.
public class Ex039CountVowels {
public static void main(String[] args) {
String text = "Programming in Java is fun";
int count = 0;
for (char c : text.toLowerCase().toCharArray()) {
if ("aeiou".indexOf(c) >= 0) count++;
}
System.out.println("Vowels: " + count);
}
}
Saída:
Vowels: 8
Exemplo 40: Triângulo de asteriscos
Monte um triângulo de asteriscos com String.repeat.
public class Ex040StarTriangle {
public static void main(String[] args) {
for (int row = 1; row <= 4; row++) {
System.out.println("*".repeat(row));
}
}
}
Saída:
*
**
***
****
Tópico 6: Arrays
Um array tem tamanho fixo e guarda valores de um único tipo. A numeração dos índices começa em 0.
Declaração e indexação
int[] a = new int[5]; cria cinco zeros. a.length é o tamanho, escrito sem parênteses. O índice 5 em um array de tamanho 5 lança ArrayIndexOutOfBoundsException, porque os índices válidos vão de 0 a 4.
Arrays bidimensionais
int[][] m é um array de arrays. As linhas podem ter tamanhos diferentes. Use laços for aninhados, com m.length para o número de linhas e m[r].length para o número de colunas da linha r.
Busca, ordenação e cópia
A busca linear examina cada item em sequência. O bubble sort troca vizinhos e leva tempo proporcional a n ao quadrado, o que não é problema para dados pequenos. Arrays.sort é mais rápido e é a escolha certa em código real. O sinal de = comum copia a referência, e não os dados, então use Arrays.copyOf ou clone para obter uma cópia de verdade.
Exemplo 41: Declarando arrays
Crie arrays com valores ou com tamanho fixo.
public class Ex041DeclareArray {
public static void main(String[] args) {
int[] numbers = {10, 20, 30, 40};
int[] empty = new int[3];
System.out.println("numbers: " + java.util.Arrays.toString(numbers));
System.out.println("empty: " + java.util.Arrays.toString(empty));
}
}
Saída:
numbers: [10, 20, 30, 40]
empty: [0, 0, 0]
Exemplo 42: Tamanho e índice do array
Leia o tamanho e altere um elemento pelo seu índice.
public class Ex042ArrayAccess {
public static void main(String[] args) {
String[] names = {"Ann", "Ben", "Cat"};
System.out.println("length = " + names.length);
System.out.println("first = " + names[0]);
names[1] = "Bob";
System.out.println("second now = " + names[1]);
}
}
Saída:
length = 3
first = Ann
second now = Bob
Exemplo 43: Array bidimensional
Um array de arrays, usado como linhas e colunas.
public class Ex043TwoDimensional {
public static void main(String[] args) {
int[][] grid = {
{1, 2, 3},
{4, 5, 6}
};
System.out.println("rows = " + grid.length + ", cols = " + grid[0].length);
System.out.println("grid[1][2] = " + grid[1][2]);
}
}
Saída:
rows = 2, cols = 3
grid[1][2] = 6
Exemplo 44: Matriz identidade
Preencha uma matriz 3 por 3 com 1 na diagonal.
public class Ex044Matrix {
public static void main(String[] args) {
int[][] m = new int[3][3];
for (int i = 0; i < 3; i++) {
for (int j = 0; j < 3; j++) {
m[i][j] = (i == j) ? 1 : 0;
}
}
for (int[] row : m) {
System.out.println(java.util.Arrays.toString(row));
}
}
}
Saída:
[1, 0, 0]
[0, 1, 0]
[0, 0, 1]
Exemplo 45: Soma e média
Some os valores e divida pela quantidade.
public class Ex045SumAverage {
public static void main(String[] args) {
int[] scores = {70, 85, 90, 65};
int sum = 0;
for (int s : scores) sum += s;
double avg = (double) sum / scores.length;
System.out.println("sum = " + sum + ", average = " + avg);
}
}
Saída:
sum = 310, average = 77.5
Exemplo 46: Mínimo e máximo
Encontre o menor e o maior valor em uma única passagem.
public class Ex046MinMax {
public static void main(String[] args) {
int[] data = {14, 3, 99, -5, 27};
int min = data[0], max = data[0];
for (int v : data) {
if (v < min) min = v;
if (v > max) max = v;
}
System.out.println("min = " + min + ", max = " + max);
}
}
Saída:
min = -5, max = 99
Exemplo 47: Busca linear
Procure um valor verificando um item de cada vez.
public class Ex047LinearSearch {
public static void main(String[] args) {
int[] items = {4, 8, 15, 16, 23, 42};
int target = 16;
int index = -1;
for (int i = 0; i < items.length; i++) {
if (items[i] == target) {
index = i;
break;
}
}
System.out.println("index of " + target + " = " + index);
}
}
Saída:
index of 16 = 3
Exemplo 48: Bubble sort
Ordene trocando vizinhos que estão fora de ordem.
public class Ex048BubbleSort {
public static void main(String[] args) {
int[] a = {5, 1, 4, 2, 8};
for (int i = 0; i < a.length - 1; i++) {
for (int j = 0; j < a.length - 1 - i; j++) {
if (a[j] > a[j + 1]) {
int t = a[j];
a[j] = a[j + 1];
a[j + 1] = t;
}
}
}
System.out.println(java.util.Arrays.toString(a));
}
}
Saída:
[1, 2, 4, 5, 8]
Exemplo 49: Arrays.sort
Ordene com a biblioteca padrão e busque com binarySearch.
import java.util.Arrays;
public class Ex049ArraysSort {
public static void main(String[] args) {
int[] nums = {9, 2, 7, 4};
Arrays.sort(nums);
System.out.println("sorted: " + Arrays.toString(nums));
System.out.println("binary search 7 at " + Arrays.binarySearch(nums, 7));
}
}
Saída:
sorted: [2, 4, 7, 9]
binary search 7 at 2
Exemplo 50: Copiando um array
Arrays.copyOf cria um array novo, separado do primeiro.
import java.util.Arrays;
public class Ex050CopyArray {
public static void main(String[] args) {
int[] original = {1, 2, 3};
int[] copy = Arrays.copyOf(original, 5);
copy[0] = 100;
System.out.println("original: " + Arrays.toString(original));
System.out.println("copy: " + Arrays.toString(copy));
}
}
Saída:
original: [1, 2, 3]
copy: [100, 2, 3, 0, 0]
Exemplo 51: Invertendo um array
Troque os itens das duas extremidades em direção ao meio.
public class Ex051ReverseArray {
public static void main(String[] args) {
int[] a = {1, 2, 3, 4, 5};
for (int i = 0, j = a.length - 1; i < j; i++, j--) {
int t = a[i];
a[i] = a[j];
a[j] = t;
}
System.out.println(java.util.Arrays.toString(a));
}
}
Saída:
[5, 4, 3, 2, 1]
Tópico 7: String
String é um objeto em Java, e seu conteúdo não pode mudar depois de criado. Os métodos de string devolvem uma nova string.
Tamanho, charAt e comparação
length() conta os caracteres, e charAt(i) devolve o caractere na posição i. Compare textos com equals, e não com ==. equalsIgnoreCase compara sem diferenciar maiúsculas de minúsculas.
Métodos comuns e divisão
trim, toUpperCase, toLowerCase, isBlank, substring, indexOf e split(",") são ferramentas do dia a dia. substring(a, b) inclui o índice a e exclui o índice b.
StringBuilder e formatação
O uso repetido de + dentro de um laço cria muitas strings temporárias, então use StringBuilder. String.format e printf usam %d para inteiros, %.2f para duas casas decimais e %s para texto.
Exemplo 52: Tamanho e charAt de uma string
Leia o tamanho e o caractere de uma posição específica.
public class Ex052StringBasics {
public static void main(String[] args) {
String s = "Java";
System.out.println("length = " + s.length());
System.out.println("char at 1 = " + s.charAt(1));
}
}
Saída:
length = 4
char at 1 = a
Exemplo 53: Concatenação
Junte textos com + e veja como a ordem das operações faz diferença.
public class Ex053Concatenation {
public static void main(String[] args) {
int a = 2, b = 3;
System.out.println("a + b = " + a + b);
System.out.println("sum = " + (a + b));
String s = "x" + 1 + 2;
System.out.println(s);
}
}
Saída:
a + b = 23
sum = 5
x12
Exemplo 54: Métodos de string
trim, toUpperCase, toLowerCase e isBlank.
public class Ex054StringMethods {
public static void main(String[] args) {
String s = " Hello Java ";
System.out.println("[" + s.trim() + "]");
System.out.println(s.toUpperCase().trim());
System.out.println(s.trim().toLowerCase());
System.out.println(s.isBlank());
}
}
Saída:
[Hello Java]
HELLO JAVA
hello java
false
Exemplo 55: substring e indexOf
Corte parte de uma string e encontre a posição de um caractere.
public class Ex055SubstringIndexOf {
public static void main(String[] args) {
String s = "programming";
System.out.println(s.substring(0, 3));
System.out.println(s.substring(3));
System.out.println("index of 'g' = " + s.indexOf('g'));
System.out.println("last index of 'g' = " + s.lastIndexOf('g'));
}
}
Saída:
pro
gramming
index of 'g' = 3
last index of 'g' = 10
Exemplo 56: equals versus ==
Compare o conteúdo das strings, e não apenas as referências.
public class Ex056EqualsVsSame {
public static void main(String[] args) {
String a = "hello";
String b = "hello";
String c = new String("hello");
System.out.println("a == b: " + (a == b));
System.out.println("a == c: " + (a == c));
System.out.println("a.equals(c): " + a.equals(c));
}
}
Saída:
a == b: true
a == c: false
a.equals(c): true
Exemplo 57: StringBuilder
Monte um texto de forma eficiente, depois inverta e insira.
public class Ex057StringBuilder {
public static void main(String[] args) {
StringBuilder sb = new StringBuilder();
sb.append("Java").append(' ').append(17);
System.out.println(sb);
sb.reverse();
System.out.println(sb);
sb.insert(0, ">> ");
System.out.println(sb);
}
}
Saída:
Java 17
71 avaJ
>> 71 avaJ
Exemplo 58: Dividindo uma string
Separe uma string com vírgulas em um array.
import java.util.Arrays;
public class Ex058SplitString {
public static void main(String[] args) {
String csv = "apple,banana,cherry";
String[] parts = csv.split(",");
System.out.println(Arrays.toString(parts));
System.out.println("count = " + parts.length);
}
}
Saída:
[apple, banana, cherry]
count = 3
Exemplo 59: String.format
Formate números com casas decimais fixas e largura de coluna.
public class Ex059StringFormat {
public static void main(String[] args) {
String name = "Mali";
double price = 49.5;
System.out.println(String.format("Item: %s, price: %.2f baht", name, price));
System.out.println(String.format("%5d|%-5d|", 42, 42));
}
}
Saída:
Item: Mali, price: 49.50 baht
42|42 |
Exemplo 60: Juntando strings
String.join coloca um separador entre os itens.
import java.util.List;
public class Ex060JoinStrings {
public static void main(String[] args) {
System.out.println(String.join(" - ", "a", "b", "c"));
List<String> words = List.of("Java", "is", "fun");
System.out.println(String.join(" ", words));
}
}
Saída:
a - b - c
Java is fun
Tópico 8: Métodos
Um método é um bloco nomeado que recebe entradas e devolve um resultado. Métodos tornam a lógica reutilizável e com nomes claros.
Parâmetros e valor de retorno
Declare o tipo de cada parâmetro e o tipo de retorno. void significa que o método não devolve nada. return termina o método e envia um valor de volta a quem chamou.
Sobrecarga e varargs
Um método pode ter o mesmo nome quando a lista de parâmetros é diferente. O Java escolhe a correspondência durante a compilação. Varargs, como int... nums, aceitam qualquer quantidade de argumentos, e dentro do método são um int[].
Passagem por valor e recursão
O Java sempre passa uma cópia. Para primitivos, a cópia é o próprio valor. Para objetos, a cópia é a referência, então o método pode alterar o objeto, mas não pode fazer a variável de quem chamou apontar para outro objeto. Um método recursivo chama a si mesmo e precisa de um caso base, senão nunca para e a pilha estoura.
Exemplo 61: Método com parâmetros
O método recebe entradas e devolve um resultado.
public class Ex061MethodParams {
static int add(int a, int b) {
return a + b;
}
public static void main(String[] args) {
System.out.println("3 + 4 = " + add(3, 4));
}
}
Saída:
3 + 4 = 7
Exemplo 62: Sobrecarga
O mesmo nome de método com tipos de parâmetros diferentes.
public class Ex062Overloading {
static int area(int side) { return side * side; }
static int area(int w, int h) { return w * h; }
static double area(double radius) { return Math.PI * radius * radius; }
public static void main(String[] args) {
System.out.println("square: " + area(4));
System.out.println("rectangle: " + area(3, 5));
System.out.printf("circle: %.2f%n", area(2.0));
}
}
Saída:
square: 16
rectangle: 15
circle: 12.57
Exemplo 63: Recursão
Um método que chama a si mesmo, calculando o fatorial.
public class Ex063RecursionFactorial {
static long factorial(int n) {
if (n <= 1) return 1;
return n * factorial(n - 1);
}
public static void main(String[] args) {
System.out.println("5! = " + factorial(5));
System.out.println("10! = " + factorial(10));
}
}
Saída:
5! = 120
10! = 3628800
Exemplo 64: Varargs
Aceita qualquer quantidade de argumentos.
public class Ex064Varargs {
static int sum(int... numbers) {
int total = 0;
for (int n : numbers) total += n;
return total;
}
public static void main(String[] args) {
System.out.println(sum());
System.out.println(sum(1, 2));
System.out.println(sum(1, 2, 3, 4, 5));
}
}
Saída:
0
3
15
Exemplo 65: Passagem por valor
Primitivos são copiados; a referência de um objeto também é copiada.
public class Ex065PassByValue {
static void change(int x, int[] arr) {
x = 99;
arr[0] = 99;
}
public static void main(String[] args) {
int n = 1;
int[] a = {1};
change(n, a);
System.out.println("n = " + n);
System.out.println("a[0] = " + a[0]);
}
}
Saída:
n = 1
a[0] = 99
Tópico 9: Classes e objetos
Uma classe é um molde, e um objeto é uma instância criada a partir dela, com seus próprios dados. As classes agrupam campos e métodos e formam o núcleo do Java.
Campos, construtores e métodos
Campos guardam dados, construtores definem os valores iniciais quando new é usado, e métodos trabalham sobre os dados do objeto. this se refere ao objeto atual. Torne os campos private e exponha apenas o necessário para o restante do código.
Membros static e de instância
Um campo static é compartilhado por todos os objetos da classe, como um contador. Um método de instância precisa de um objeto para ser executado. Um método static é chamado pelo nome da classe, como Util.max(a, b).
Herança e polimorfismo
extends cria uma subclasse que herda campos e métodos e pode chamar super(...). Override substitui um método da classe-mãe por um novo comportamento. Uma variável do tipo da classe-mãe executa a versão da subclasse em tempo de execução.
Classes abstratas, interfaces e composição
Uma classe abstrata não pode ser criada diretamente e pode conter métodos ainda não implementados. Uma interface lista os métodos que uma classe deve fornecer, e desde o Java 8 um método default pode trazer um corpo compartilhado. Composição coloca um objeto dentro de outro, o que costuma ser mais flexível do que herança.
Classes aninhadas, classes internas e enums
Uma classe aninhada static não precisa de um objeto externo. Uma classe interna pode usar os campos do objeto externo. Um enum é um conjunto fixo de constantes, e cada constante pode ter seus próprios campos e métodos.
equals e hashCode
Objetos guardados em um HashSet ou usados como chave de um HashMap precisam de equals e hashCode escritos juntos. Objetos iguais devem produzir o mesmo código hash, senão as buscas falham.
Exemplo 66: Membros static
Campos e métodos compartilhados por toda a classe.
public class Ex066StaticMembers {
static int counter = 0;
static void increment() {
counter++;
}
public static void main(String[] args) {
increment();
increment();
System.out.println("counter = " + counter);
}
}
Saída:
counter = 2
Exemplo 67: Classe e objeto
Defina a classe Book e crie um objeto a partir dela.
public class Ex067ClassAndObject {
static class Book {
String title;
int pages;
Book(String title, int pages) {
this.title = title;
this.pages = pages;
}
}
public static void main(String[] args) {
Book b = new Book("Java Basics", 320);
System.out.println(b.title + " has " + b.pages + " pages");
}
}
Saída:
Java Basics has 320 pages
Exemplo 68: Método de instância
Um método que trabalha sobre os dados de um objeto.
public class Ex068InstanceMethods {
static class Counter {
private int value;
void add(int n) {
this.value += n;
}
int get() {
return value;
}
}
public static void main(String[] args) {
Counter c = new Counter();
c.add(3);
c.add(4);
System.out.println("value = " + c.get());
}
}
Saída:
value = 7
Exemplo 69: Getters e setters
Controle o acesso e valide a entrada.
public class Ex069GettersSetters {
static class Person {
private String name;
public String getName() { return name; }
public void setName(String name) {
if (name == null || name.isBlank()) {
throw new IllegalArgumentException("name required");
}
this.name = name;
}
}
public static void main(String[] args) {
Person p = new Person();
p.setName("Nok");
System.out.println("name = " + p.getName());
}
}
Saída:
name = Nok
Exemplo 70: toString
Imprima um objeto de forma legível.
public class Ex070ToStringOverride {
static class Point {
final int x, y;
Point(int x, int y) { this.x = x; this.y = y; }
@Override
public String toString() {
return "Point(" + x + ", " + y + ")";
}
}
public static void main(String[] args) {
System.out.println(new Point(3, 4));
}
}
Saída:
Point(3, 4)
Exemplo 71: Herança
Uma classe estende outra e chama super.
public class Ex071Inheritance {
static class Animal {
void speak() { System.out.println("...some sound"); }
}
static class Dog extends Animal {
@Override
void speak() {
super.speak();
System.out.println("Woof!");
}
}
public static void main(String[] args) {
new Dog().speak();
}
}
Saída:
...some sound
Woof!
Exemplo 72: Polimorfismo
Chame o método correto para cada tipo de objeto.
public class Ex072Polymorphism {
static class Shape {
double area() { return 0; }
}
static class Square extends Shape {
double side = 3;
@Override double area() { return side * side; }
}
static class Circle extends Shape {
double r = 1;
@Override double area() { return Math.PI * r * r; }
}
public static void main(String[] args) {
Shape[] shapes = {new Square(), new Circle()};
for (Shape s : shapes) {
System.out.printf("%s area %.2f%n", s.getClass().getSimpleName(), s.area());
}
}
}
Saída:
Square area 9.00
Circle area 3.14
Exemplo 73: Classe abstrata
Uma classe que não pode ser criada diretamente.
public class Ex073AbstractClass {
static abstract class Vehicle {
abstract int wheels();
String describe() { return "wheels: " + wheels(); }
}
static class Bike extends Vehicle {
@Override int wheels() { return 2; }
}
public static void main(String[] args) {
System.out.println(new Bike().describe());
}
}
Saída:
wheels: 2
Exemplo 74: Interface
Defina um contrato que uma classe implementa.
public class Ex074Interface {
interface Greeter {
String greet(String name);
}
static class English implements Greeter {
public String greet(String name) { return "Hello, " + name; }
}
public static void main(String[] args) {
Greeter g = new English();
System.out.println(g.greet("Lek"));
}
}
Saída:
Hello, Lek
Exemplo 75: Método default
Um método de interface que tem um corpo padrão.
public class Ex075DefaultMethod {
interface Logger {
void log(String msg);
default void logTwice(String msg) {
log(msg);
log(msg);
}
}
public static void main(String[] args) {
Logger console = msg -> System.out.println("LOG: " + msg);
console.logTwice("ready");
}
}
Saída:
LOG: ready
LOG: ready
Exemplo 76: Composição
Uma classe contém outro objeto como um de seus campos.
public class Ex076Composition {
static class Engine {
String start() { return "engine started"; }
}
static class Car {
private final Engine engine = new Engine();
String drive() { return engine.start() + ", car moving"; }
}
public static void main(String[] args) {
System.out.println(new Car().drive());
}
}
Saída:
engine started, car moving
Exemplo 77: Classe aninhada static
Uma classe colocada dentro de outra classe.
public class Ex077StaticNestedClass {
static class Util {
static int square(int x) { return x * x; }
}
public static void main(String[] args) {
System.out.println("square(6) = " + Util.square(6));
}
}
Saída:
square(6) = 36
Exemplo 78: Classe interna
Uma classe interna pode acessar os campos do seu objeto externo.
public class Ex078InnerClass {
private int base = 10;
class Adder {
int add(int n) { return base + n; }
}
public static void main(String[] args) {
Ex078InnerClass outer = new Ex078InnerClass();
Ex078InnerClass.Adder adder = outer.new Adder();
System.out.println("10 + 5 = " + adder.add(5));
}
}
Saída:
10 + 5 = 15
Exemplo 79: Enum com campos
Um enum pode guardar valores e métodos.
public class Ex079EnumWithFields {
enum Size {
SMALL(1), MEDIUM(2), LARGE(3);
private final int code;
Size(int code) { this.code = code; }
int code() { return code; }
}
public static void main(String[] args) {
for (Size s : Size.values()) {
System.out.println(s + " code " + s.code());
}
}
}
Saída:
SMALL code 1
MEDIUM code 2
LARGE code 3
Exemplo 80: equals e hashCode
Defina a igualdade para objetos usados em coleções.
import java.util.Objects;
public class Ex080EqualsHashCode {
static class Item {
final String id;
Item(String id) { this.id = id; }
@Override
public boolean equals(Object o) {
if (!(o instanceof Item)) return false;
return Objects.equals(id, ((Item) o).id);
}
@Override
public int hashCode() { return Objects.hash(id); }
}
public static void main(String[] args) {
System.out.println(new Item("A1").equals(new Item("A1")));
System.out.println(new Item("A1").hashCode() == new Item("A1").hashCode());
}
}
Saída:
true
true
Tópico 10: Coleções
Coleções guardam grupos de objetos. Escolha o tipo conforme a necessidade: uma lista ordenada, uma busca por chave, valores únicos ou uma fila first-in, first-out.
Lista, conjunto e mapa
ArrayList mantém a ordem de inserção e aceita duplicatas. HashSet guarda valores únicos sem uma ordem definida. HashMap guarda pares chave-valor. Cada um tem velocidades diferentes para adicionar e buscar itens.
Percorrendo um mapa
entrySet fornece chave e valor ao mesmo tempo em um único laço. HashMap não tem ordem definida, então use LinkedHashMap para manter a ordem de inserção ou TreeMap para manter as chaves ordenadas.
Fila e pilha com Deque
ArrayDeque pode ser usado como fila (offer e poll dão ordem first-in, first-out) ou como pilha (push e pop dão ordem last-in, first-out). É preferível a usar a antiga classe Stack.
Ordenação com Comparator
Comparator.comparingInt(Student::score).reversed() ordena os alunos pela nota, da maior para a menor. A ordenação altera a lista no lugar, então copie a lista antes se precisar da ordem original.
Exemplo 81: ArrayList
Uma lista de tamanho variável com add, get e remove.
import java.util.ArrayList;
import java.util.List;
public class Ex081ArrayList {
public static void main(String[] args) {
List<String> names = new ArrayList<>();
names.add("Ann");
names.add("Ben");
names.add("Cat");
System.out.println("size = " + names.size());
System.out.println("get(1) = " + names.get(1));
names.remove("Ben");
System.out.println(names);
}
}
Saída:
size = 3
get(1) = Ben
[Ann, Cat]
Exemplo 82: HashMap
Guarde pares chave-valor e recupere-os depois.
import java.util.HashMap;
import java.util.Map;
public class Ex082HashMap {
public static void main(String[] args) {
Map<String, Integer> stock = new HashMap<>();
stock.put("pen", 10);
stock.put("pencil", 4);
System.out.println("pen: " + stock.get("pen"));
System.out.println("eraser: " + stock.getOrDefault("eraser", 0));
}
}
Saída:
pen: 10
eraser: 0
Exemplo 83: HashSet
Uma coleção que não guarda duplicatas.
import java.util.HashSet;
import java.util.Set;
public class Ex083HashSet {
public static void main(String[] args) {
Set<Integer> ids = new HashSet<>();
ids.add(1);
ids.add(2);
ids.add(1);
System.out.println("unique count = " + ids.size());
System.out.println("contains 2? " + ids.contains(2));
}
}
Saída:
unique count = 2
contains 2? true
Exemplo 84: Percorrendo um mapa
Percorra as entradas com entrySet.
import java.util.Map;
import java.util.TreeMap;
public class Ex084MapEntries {
public static void main(String[] args) {
Map<String, Integer> ages = new TreeMap<>();
ages.put("Mali", 22);
ages.put("Dao", 30);
for (Map.Entry<String, Integer> e : ages.entrySet()) {
System.out.println(e.getKey() + " -> " + e.getValue());
}
}
}
Saída:
Dao -> 30
Mali -> 22
Exemplo 85: Fila com ArrayDeque
First in, first out com offer e poll.
import java.util.ArrayDeque;
import java.util.Deque;
public class Ex085Deque {
public static void main(String[] args) {
Deque<String> queue = new ArrayDeque<>();
queue.offer("first");
queue.offer("second");
System.out.println("poll: " + queue.poll());
System.out.println("left: " + queue);
}
}
Saída:
poll: first
left: [second]
Exemplo 86: Pilha com Deque
Last in, first out com push e pop.
import java.util.ArrayDeque;
import java.util.Deque;
public class Ex086StackDeque {
public static void main(String[] args) {
Deque<Integer> stack = new ArrayDeque<>();
stack.push(1);
stack.push(2);
stack.push(3);
System.out.println("pop: " + stack.pop());
System.out.println("peek: " + stack.peek());
}
}
Saída:
pop: 3
peek: 2
Exemplo 87: Ordenação com Comparator
Ordene registros por um campo, em ordem inversa.
import java.util.ArrayList;
import java.util.Comparator;
import java.util.List;
public class Ex087ComparatorSort {
record Student(String name, int score) {}
public static void main(String[] args) {
List<Student> list = new ArrayList<>(List.of(
new Student("Ann", 70),
new Student("Ben", 92),
new Student("Cat", 85)));
list.sort(Comparator.comparingInt(Student::score).reversed());
for (Student s : list) {
System.out.println(s.name() + " " + s.score());
}
}
}
Saída:
Ben 92
Cat 85
Ann 70
Tópico 11: Generics
Generics permitem que uma classe ou método funcione com vários tipos, enquanto o compilador continua verificando se os tipos batem.
Classe genérica
class Box<T> guarda um valor de qualquer tipo T. O compilador impede que você coloque uma String em um Box<Integer>, então o erro aparece antes de o programa rodar.
Método genérico
<T> T first(T[] items) funciona com um array de qualquer tipo. O compilador deduz T a partir dos argumentos fornecidos.
Tipos com restrição
<T extends Comparable<T>> afirma que T precisa fornecer compareTo, para que o método possa comparar valores. Sem essa restrição, o compilador não saberia que o método existe.
Exemplo 88: Classe genérica
Uma classe que funciona com qualquer tipo T.
public class Ex088GenericBox {
static class Box<T> {
private T item;
void put(T item) { this.item = item; }
T get() { return item; }
}
public static void main(String[] args) {
Box<String> b = new Box<>();
b.put("gift");
System.out.println("box has " + b.get());
Box<Integer> n = new Box<>();
n.put(42);
System.out.println("number " + (n.get() + 1));
}
}
Saída:
box has gift
number 43
Exemplo 89: Método genérico
Um método que funciona com arrays de qualquer tipo.
public class Ex089GenericMethod {
static <T> void printAll(T[] items) {
for (T item : items) {
System.out.println("item: " + item);
}
}
public static void main(String[] args) {
printAll(new String[]{"a", "b"});
printAll(new Integer[]{1, 2, 3});
}
}
Saída:
item: a
item: b
item: 1
item: 2
item: 3
Exemplo 90: Genérico com restrição
Use Comparable para encontrar o maior de dois valores.
public class Ex090BoundedGeneric {
static <T extends Comparable<T>> T maxOf(T a, T b) {
return a.compareTo(b) >= 0 ? a : b;
}
public static void main(String[] args) {
System.out.println("max of 3 and 9 = " + maxOf(3, 9));
System.out.println("max of pear and apple = " + maxOf("pear", "apple"));
}
}
Saída:
max of 3 and 9 = 9
max of pear and apple = pear
Tópico 12: Exceções e recursos
Uma exceção é um erro que interrompe o fluxo normal. try e catch a tratam, finally sempre é executado, e try-with-resources fecha arquivos e outros recursos automaticamente.
try, catch e finally
Coloque o código arriscado dentro de try. Capture primeiro os tipos de exceção mais específicos e depois os mais gerais. finally roda depois do bloco try, com ou sem erro, então é ideal para limpeza.
Exceção personalizada e throw
Estenda Exception para problemas que quem chama deve tratar, ou RuntimeException para erros de programação. throw envia o objeto de exceção para cima na pilha de chamadas até encontrar um catch correspondente.
try-with-resources e multi-catch
Qualquer objeto que implemente AutoCloseable é fechado automaticamente quando o bloco try termina. catch (A | B e) trata dois tipos de exceção em uma única cláusula.
Exemplo 91: try e catch
Trate um erro de divisão por zero.
public class Ex091TryCatch {
public static void main(String[] args) {
try {
int result = 10 / 0;
System.out.println("result = " + result);
} catch (ArithmeticException e) {
System.out.println("Caught: " + e.getMessage());
}
System.out.println("program continues");
}
}
Saída:
Caught: / by zero
program continues
Exemplo 92: finally
O código de finally roda com ou sem erro.
public class Ex092Finally {
public static void main(String[] args) {
try {
System.out.println("in try");
throw new RuntimeException("oops");
} catch (RuntimeException e) {
System.out.println("in catch: " + e.getMessage());
} finally {
System.out.println("in finally, always runs");
}
}
}
Saída:
in try
in catch: oops
in finally, always runs
Exemplo 93: Exceção personalizada
Crie sua própria classe de exceção.
public class Ex093CustomException {
static class InsufficientFundsException extends Exception {
InsufficientFundsException(String msg) { super(msg); }
}
static void withdraw(int balance, int amount) throws InsufficientFundsException {
if (amount > balance) {
throw new InsufficientFundsException("need " + (amount - balance) + " more");
}
System.out.println("withdrew " + amount);
}
public static void main(String[] args) {
try {
withdraw(100, 150);
} catch (InsufficientFundsException e) {
System.out.println("Error: " + e.getMessage());
}
}
}
Saída:
Error: need 50 more
Exemplo 94: try-with-resources
O recurso é fechado automaticamente quando o bloco termina.
public class Ex094TryWithResources {
static class Resource implements AutoCloseable {
Resource() { System.out.println("open"); }
void use() { System.out.println("use"); }
@Override public void close() { System.out.println("close"); }
}
public static void main(String[] args) {
try (Resource r = new Resource()) {
r.use();
}
}
}
Saída:
open
use
close
Exemplo 95: Multi-catch
Trate dois tipos de exceção em um único bloco catch.
public class Ex095MultiCatch {
public static void main(String[] args) {
String[] inputs = {"12", "abc", null};
for (String s : inputs) {
try {
System.out.println(Integer.parseInt(s) * 2);
} catch (NumberFormatException | NullPointerException e) {
System.out.println("bad input: " + s);
}
}
}
}
Saída:
24
bad input: abc
bad input: null
Exemplo 96: throw
Lance uma exceção quando a entrada não for válida.
public class Ex096ThrowsAndThrow {
static int divide(int a, int b) {
if (b == 0) {
throw new IllegalArgumentException("divisor must not be zero");
}
return a / b;
}
public static void main(String[] args) {
System.out.println(divide(10, 2));
try {
divide(1, 0);
} catch (IllegalArgumentException e) {
System.out.println(e.getMessage());
}
}
}
Saída:
5
divisor must not be zero
Tópico 13: Lambdas, streams e records
O Java moderno escreve funções pequenas e pipelines de dados de forma curta. Um record descreve uma classe de dados simples em uma linha.
Expressões lambda
(a, b) -> a + b é uma função que você pode passar como valor. Lambdas funcionam com interfaces que têm apenas um método abstrato, como Runnable ou Comparator.
Streams
Um stream leva os itens por etapas: filter mantém os que combinam, map transforma cada item, e collect reúne o resultado. Um stream não faz nada até que uma etapa terminal, como collect, sum ou findFirst, seja executada.
Records e Optional
record Student(String name, int score) cria uma classe com construtor, getters, equals, hashCode e toString. Optional envolve um valor que pode não existir, o que reduz as verificações de null espalhadas pelo código.
Exemplo 97: Expressões lambda
Funções curtas passadas como valores.
import java.util.function.Function;
public class Ex097Lambda {
public static void main(String[] args) {
Function<Integer, Integer> doubler = x -> x * 2;
System.out.println("double 7 = " + doubler.apply(7));
Runnable hello = () -> System.out.println("hello from lambda");
hello.run();
}
}
Saída:
double 7 = 14
hello from lambda
Exemplo 98: Stream: filter e map
Filtre e transforme uma lista em um pipeline.
import java.util.List;
public class Ex098StreamFilterMap {
public static void main(String[] args) {
List<Integer> nums = List.of(1, 2, 3, 4, 5, 6);
List<Integer> result = nums.stream()
.filter(n -> n % 2 == 0)
.map(n -> n * n)
.toList();
System.out.println(result);
}
}
Saída:
[4, 16, 36]
Exemplo 99: Record
Uma classe curta para dados, com os métodos já escritos para você.
public class Ex099RecordType {
record Point(int x, int y) {
int distanceSquared() { return x * x + y * y; }
}
public static void main(String[] args) {
Point p = new Point(3, 4);
System.out.println(p);
System.out.println("x = " + p.x() + ", distance^2 = " + p.distanceSquared());
}
}
Saída:
Point[x=3, y=4]
x = 3, distance^2 = 25
Exemplo 100: Stream e Optional
Some os comprimentos e encontre com segurança a palavra mais longa.
import java.util.List;
import java.util.Optional;
public class Ex100StreamCollect {
public static void main(String[] args) {
List<String> words = List.of("java", "stream", "lambda");
int totalLength = words.stream().mapToInt(String::length).sum();
System.out.println("total length = " + totalLength);
Optional<String> longest = words.stream().max((a, b) -> a.length() - b.length());
System.out.println("longest = " + longest.orElse("none"));
}
}
Saída:
total length = 16
longest = stream
Projeto de prática: Relatório de notas
Junte as ideias em um único programa. Escreva primeiro sozinho e depois compare com os exemplos. Cada etapa corresponde a um ou dois exemplos.
1. Crie um record Student com nome e nota, e depois uma lista com cinco alunos.
2. Use um stream para guardar os alunos com nota 50 ou mais, ordenados da maior para a menor.
3. Imprima cada aluno aprovado com String.format, com nome de largura fixa e nota com duas casas.
4. Guarde o conceito de cada aluno em um Map<String, String>, usando uma expressão switch: A para 80 ou mais, B para 70 ou mais, C para 50 ou mais, e F para o restante.
5. Explique em comentários por que você escolheu List, Set ou Map para cada parte do programa.
Próximos passos
Em seguida, aprenda ferramentas de build como Maven ou Gradle, escreva testes unitários com JUnit e crie um pequeno programa de console que lê um arquivo de texto. A saída mostrada para cada exemplo vem de uma execução real no JDK 17, então, se a sua saída for diferente, verifique primeiro a versão do Java que você está usando.
Resumo
Programas Java são construídos com classes e métodos. Ao longo de 100 exemplos compilados, este artigo cobre variáveis, operadores, decisões, laços, arrays, strings, métodos, classes, coleções, generics, exceções, lambdas, streams e records. Cada exemplo mostra o código completo e a saída real. A melhor forma de praticar é mudar um valor, prever o resultado e então executar o programa para conferir.