Por que a classe é declarada daquele jeito, o que cada palavra do main significa, e como
formatar números, textos e datas sem cair nas armadilhas de sempre.
⌨️ Antes de tudo: deixe o editor trabalhar por você
Ninguém digita public static void main(String[] args) por extenso. Os editores têm atalhos
de expansão — você escreve uma abreviação, aperta Tab, e o bloco completo aparece.
Uma confusão comum
Se você viu sout e psvm em algum tutorial, saiba que esses são atalhos do
IntelliJ IDEA. No VS Code, com o Extension Pack for Java, os
equivalentes canônicos são outros:
| O que você quer | VS Code | IntelliJ |
|---|---|---|
System.out.println(); | sysout | sout |
System.err.println(); | syserr | serr |
Método main completo | main | psvm |
Laço for indexado | fori | fori |
| Construtor da classe | ctor | — |
Vale testar os dois na sua instalação: algumas versões da extensão Java aceitam os apelidos do IntelliJ também. O que importa é descobrir qual funciona no seu ambiente e usar sempre.
Atalhos de teclado que valem mais que os snippets
| Atalho | O que faz |
|---|---|
| Ctrl + Space | Autocompletar — a base de tudo |
| Ctrl + . | Correção rápida: adiciona o import que falta |
| Shift + Alt + O | Organiza os imports, remove os não usados |
| Shift + Alt + F | Formata o arquivo inteiro |
| Ctrl + / | Comenta ou descomenta a linha |
| F5 | Executa com depurador |
| Ctrl + F5 | Executa direto, sem depurador |
O Ctrl + . é o que mais economiza tempo no começo: você escreve
LocalDate sem ter importado nada, o editor sublinha, você aperta e ele resolve.
🏗️ A anatomia de uma classe
class Lesson1Print {
public static void main(String[] args) {
System.out.println("Hello Java");
}
}
Parece muita cerimônia para imprimir uma frase. Cada pedaço tem uma razão.
O nome da classe não é livre
Em Java, a convenção é PascalCase: cada palavra começa em maiúscula, sem underscore.
class lesson1_print // funciona, mas destoa de todo código Java
class Lesson1Print // convenção
class PrintBasico // ainda mais descritivo
Não é frescura. O compilador aceita lesson1_print, mas quem ler seu código vai estranhar —
em Java, snake_case é sinal de quem veio de outra linguagem e não ajustou o hábito.
Há também uma regra rígida: se a classe for public, o arquivo precisa ter
exatamente o mesmo nome. public class Lesson1Print mora obrigatoriamente em
Lesson1Print.java. Sem o public, a regra afrouxa — mas mantenha o hábito.
public static void main(String[] args), palavra por palavra
Essa linha é o ponto de entrada: é ela que a JVM procura ao rodar o programa.
-
public— visível de fora da classe. A JVM precisa enxergar esse método a partir de outro lugar; se fosseprivate, ela não o encontraria. -
static— pertence à classe, não a um objeto. É o que permite executar sem que ninguém tenha feitonewem nada. Semstatic, a JVM precisaria criar um objeto primeiro — e não teria como saber qual construtor usar. -
void— não devolve valor. O programa se comunica com o sistema operacional por outro caminho (System.exit), não pelo retorno domain. -
String[] args— o vetor de argumentos da linha de comando. Se você rodarjava Lesson1Print teste 123, oargschega com["teste", "123"]. Na maior parte dos programas iniciais ele fica vazio, mas continua obrigatório na assinatura.
Troque qualquer uma dessas palavras e o programa compila, mas não roda: a JVM procura por essa assinatura exata.
🖨️ Três formas de imprimir
System.out.print("sem quebrar linha");
System.out.println("quebra a linha no fim");
System.out.printf("com formatação: %d%n", 42);
print— escreve e para ali. Útil para montar uma linha em pedaços.println— escreve e pula linha. É o padrão do dia a dia.printf— escreve com formatação. Não pula linha sozinho: você controla com%n.
🔗 Concatenar ou formatar?
Com uma variável, concatenar é natural:
String nome = "Matheus";
System.out.println(nome + ", hello Java");
Com três, vira sopa de aspas e sinais de mais:
// difícil de ler e fácil de errar
System.out.println("Nome: " + nome + " | Idade: " + idade + " | Altura: " + altura + " m");
// o formato fica visível, separado dos dados
System.out.printf("Nome: %s | Idade: %d | Altura: %.2f m%n", nome, idade, altura);
A vantagem do printf não é economizar caracteres — é separar o molde do
conteúdo. Você bate o olho e entende o layout da saída sem precisar decifrar onde uma variável
termina e o texto recomeça.
📐 Os especificadores de formato
| Especificador | Serve para | Exemplo | Saída |
|---|---|---|---|
%s | Texto (qualquer objeto) | %s com "Ana" | Ana |
%d | Inteiro | %d com 42 | 42 |
%f | Decimal | %f com 1.5 | 1,500000 |
%.2f | Decimal com 2 casas | %.2f com 19.98765 | 19,99 |
%05d | Inteiro com zeros à esquerda | %05d com 42 | 00042 |
%-10s | Texto alinhado à esquerda em 10 colunas | %-10s| com "Ana" | Ana | |
%,d | Inteiro com separador de milhar | %,d com 1234567 | 1.234.567 |
%b | Booleano | %b com true | true |
%% | Um sinal de porcentagem literal | 50%% | 50% |
%n | Quebra de linha | — | — |
%n e \n não são a mesma coisa
Ambos quebram a linha, mas:
\né sempre o caractere LF, ponto de códigoU+000A.%né a quebra de linha do sistema operacional — LF no Linux e no macOS, CRLF no Windows.
Em texto que vai para o terminal, a diferença raramente aparece. Ela morde quando você grava arquivo: um
.txt gerado com \n no Windows pode abrir todo em uma linha só no Bloco de
Notas antigo. Dentro de printf, prefira %n.
🇧🇷 A armadilha da vírgula decimal
Este é o erro que mais pega brasileiro:
double preco = 19.98765;
System.out.printf("Preço: R$ %.2f%n", preco);
O que sai depende da configuração regional da máquina:
Máquina em en-US: Preço: R$ 19.99
O printf usa o locale padrão do sistema. Isso é ótimo quando você quer o formato
local — e desastroso quando precisa de saída previsível, como ao gerar um CSV, um JSON ou um arquivo que
outro sistema vai ler.
Para fixar o formato, informe o locale:
import java.util.Locale;
// sempre com ponto, independente da máquina
System.out.printf(Locale.US, "%.2f%n", preco); // 19.99
// sempre com vírgula
System.out.printf(new Locale("pt", "BR"), "%.2f%n", preco); // 19,99
📅 Datas: o %tD mente para você
System.out.printf("Hoje é %tD%n", new Date());
// Saída: Hoje é 07/28/26
Isso não é a data errada — é a data no formato americano. O %tD equivale a
%tm/%td/%ty: mês, dia, ano com dois dígitos. Para 28 de julho de 2026, sai
07/28/26.
Para o formato brasileiro, monte os pedaços:
System.out.printf("Hoje é %td/%tm/%tY%n", data, data, data);
Repetir o argumento três vezes incomoda. Existe atalho — o sinal < reaproveita o
argumento anterior:
System.out.printf("Hoje é %td/%<tm/%<tY%n", data);
// Saída: Hoje é 28/07/2026
Os principais conversores de data:
| Conversor | Significa | Exemplo |
|---|---|---|
%td | Dia com 2 dígitos | 28 |
%tm | Mês com 2 dígitos | 07 |
%tY | Ano com 4 dígitos | 2026 |
%ty | Ano com 2 dígitos | 26 |
%tH | Hora, 24h | 14 |
%tM | Minuto | 05 |
E tem um problema maior que o formato
import java.util.Date; // legado
java.util.Date é de 1996 e carrega decisões ruins: é mutável, mistura data com hora, e
vários métodos estão marcados como obsoletos desde o Java 1.1.
Desde o Java 8 existe o pacote java.time, que resolve isso:
import java.time.LocalDate;
import java.time.format.DateTimeFormatter;
LocalDate hoje = LocalDate.now();
System.out.println(hoje.format(DateTimeFormatter.ofPattern("dd/MM/yyyy")));
// Saída: 28/07/2026
Além de mais legível, LocalDate é imutável — nenhum método altera o
objeto, todos devolvem um novo. Isso elimina uma classe inteira de bugs em que uma data muda sem você
perceber.
Você ainda vai encontrar Date em código antigo e precisa saber lê-lo. Mas em código novo,
use java.time.
✅ O código completo, revisado
import java.time.LocalDate;
import java.time.format.DateTimeFormatter;
import java.util.Locale;
public class Lesson1Print {
public static void main(String[] args) {
System.out.println("Hello Java");
String nome = "Matheus";
System.out.println(nome + ", hello Java");
// Decimal com 2 casas — locale fixo para saída previsível
double preco = 19.98765;
System.out.printf(Locale.US, "Preço: US$ %.2f%n", preco); // 19.99
System.out.printf("Preço: R$ %.2f%n", preco); // 19,99 em pt-BR
// Inteiro com zeros à esquerda
int numero = 42;
System.out.printf("Número: %05d%n", numero); // 00042
// Data no formato brasileiro — o < reaproveita o argumento
LocalDate hoje = LocalDate.now();
System.out.printf("Hoje é %td/%<tm/%<tY%n", hoje); // 28/07/2026
// Alternativa mais legível para datas
System.out.println(hoje.format(DateTimeFormatter.ofPattern("dd/MM/yyyy")));
// Várias variáveis: o molde fica separado dos dados
int idade = 25;
double altura = 1.82;
System.out.printf("Nome: %s | Idade: %d | Altura: %.2f m%n", nome, idade, altura);
}
}
📌 Recapitulando
public static void main(String[] args)é a assinatura que a JVM procura. Trocar qualquer palavra quebra a execução.- Classes em PascalCase, e o arquivo com o mesmo nome se a classe for
public. printfganha do+quando há mais de duas variáveis: o formato fica legível.%nem vez de\ndentro deprintf.- Locale importa em decimais: fixe-o quando a saída for para outro sistema.
%tDé formato americano. Para o brasileiro,%td/%<tm/%<tY.java.timeem vez dejava.util.Dateem código novo.