Java Tipos Primitivos
Na aula Variáveis você viu que toda variável tem um tipo, o "formato da caixa". O Java tem exatamente oito tipos básicos, embutidos na linguagem, chamados tipos primitivos. Esta aula apresenta os oito de uma vez, para você ter o mapa completo; as próximas aulas aprofundam cada grupo.
- Os 8 tipos primitivos: o que cada um guarda, quanto espaço ocupa e até onde vai.
- Por que o Java exige tipos (e como eles protegem você de erros).
- A diferença entre um tipo primitivo e um tipo de referência, como
String. - Qual tipo escolher em cada situação.
Por que existem tipos?
Imagine o armário de uma cozinha. Há potes pequenos para o sal, potes grandes para o arroz, uma garrafa para o óleo. Você não guarda óleo num saquinho de papel nem uma colher de sal num pote de 5 kg. Cada recipiente é feito para um tipo de conteúdo e um tamanho.
No computador é igual. Tudo é guardado na memória como bits (zeros e uns), e o mesmo punhado de bits pode significar um número, uma letra ou "verdadeiro". O tipo diz ao Java como ler aqueles bits e quanto espaço reservar. Em troca, o Java confere, antes de rodar, se você está guardando cada coisa no recipiente certo:
public class Main {
public static void main(String[] args) {
int quantidade = 2.5;
}
}
$ javac Main.java
Main.java:3: error: incompatible types: possible lossy conversion from double to int
int quantidade = 2.5;
^
1 error
"Tipos incompatíveis: possível conversão com perda, de double para int". Uma caixa int só guarda inteiros; para caber, o 2.5 perderia o .5, e o Java não faz isso escondido. O erro aparece na compilação, antes de o programa rodar, e é exatamente para isso que os tipos existem: achar erros cedo. Linguagens que verificam os tipos assim são chamadas de estaticamente tipadas.
Os 8 tipos primitivos
Eles se dividem em quatro famílias:
| Família | Tipos | Guardam | Aula |
|---|---|---|---|
| Inteiros | byte, short, int, long | Números sem parte decimal | int, long, short, byte |
| Decimais (ponto flutuante) | float, double | Números com parte decimal | double e float |
| Caractere | char | Uma letra, dígito ou símbolo | char e boolean |
| Lógico | boolean | true (verdadeiro) ou false (falso) | char e boolean |
E aqui está a tabela completa. Não precisa decorar os números: guarde a ideia de que cada tipo tem um limite.
| Tipo | Tamanho | Faixa de valores | Valor padrão | Exemplo |
|---|---|---|---|---|
byte | 8 bits (1 byte) | -128 a 127 | 0 | byte idadeDoGato = 7; |
short | 16 bits (2 bytes) | -32.768 a 32.767 | 0 | short ano = 1997; |
int | 32 bits (4 bytes) | -2.147.483.648 a 2.147.483.647 (cerca de ±2,1 bilhões) | 0 | int habitantes = 213000000; |
long | 64 bits (8 bytes) | cerca de ±9,2 quintilhões (19 dígitos) | 0L | long estrelas = 400000000000L; |
float | 32 bits (4 bytes) | até cerca de ±3,4 × 1038, com 6 a 7 dígitos de precisão | 0.0f | float temperatura = 36.5f; |
double | 64 bits (8 bytes) | até cerca de ±1,8 × 10308, com 15 a 16 dígitos de precisão | 0.0 | double preco = 9.90; |
char | 16 bits (2 bytes) | um caractere Unicode (códigos 0 a 65.535) | '\u0000' | char inicial = 'A'; |
boolean | não definido pela especificação | true ou false | false | boolean temCadastro = true; |
Os nomes vêm do inglês: byte (8 bits), short ("curto"), int (integer, "inteiro"), long ("longo"), float ("flutuar", de floating point, "ponto flutuante"), double ("duplo": o dobro da precisão do float), char (character, "caractere") e boolean (do matemático George Boole, que criou a lógica de verdadeiro e falso).
Os oito num programa
public class Main {
public static void main(String[] args) {
byte idadeDoGato = 7;
short anoDeNascimento = 1997;
int habitantes = 213000000;
long estrelas = 400000000000L;
float temperatura = 36.5f;
double preco = 9.90;
char inicial = 'A';
boolean temCadastro = true;
System.out.println(idadeDoGato);
System.out.println(anoDeNascimento);
System.out.println(habitantes);
System.out.println(estrelas);
System.out.println(temperatura);
System.out.println(preco);
System.out.println(inicial);
System.out.println(temCadastro);
}
}
$ javac Main.java && java Main 7 1997 213000000 400000000000 36.5 9.9 « o zero do fim de 9.90 não é guardado A true
Repare nos detalhes de escrita, cada um explicado na aula da sua família:
- 400000000000L
- O
Lno fim marca um númerolong. Sem ele, o Java acha que é umintgrande demais e recusa (int, long, short, byte). - 36.5f
- O
fmarca umfloat. Sem ele,36.5édouble(double e float). - 'A'
- Um
charvai entre aspas simples; texto (String) vai entre aspas duplas (char e boolean). - true
- Um
booleané escrito sem aspas, em minúsculas.
Brinque com o código: mude os valores. Tente byte idadeDoGato = 200; (passa do limite de 127), tire o L do long ou o f do float, e veja o que o compilador responde.
public class Main {
public static void main(String[] args) {
byte idadeDoGato = 7;
short anoDeNascimento = 1997;
int habitantes = 213000000;
long estrelas = 400000000000L;
float temperatura = 36.5f;
double preco = 9.90;
char inicial = 'A';
boolean temCadastro = true;
System.out.println(idadeDoGato);
System.out.println(anoDeNascimento);
System.out.println(habitantes);
System.out.println(estrelas);
System.out.println(temperatura);
System.out.println(preco);
System.out.println(inicial);
System.out.println(temCadastro);
}
}
Os limites, direto do Java
Você não precisa decorar as faixas: o próprio Java as guarda em constantes, como Integer.MAX_VALUE ("valor máximo de um inteiro"). Byte, Short, Integer, Long, Float, Double e Character são classes "irmãs" dos primitivos, chamadas wrappers:
public class Main {
public static void main(String[] args) {
System.out.println("byte: " + Byte.MIN_VALUE + " a " + Byte.MAX_VALUE);
System.out.println("short: " + Short.MIN_VALUE + " a " + Short.MAX_VALUE);
System.out.println("int: " + Integer.MIN_VALUE + " a " + Integer.MAX_VALUE);
System.out.println("long: " + Long.MIN_VALUE + " a " + Long.MAX_VALUE);
System.out.println("float: até " + Float.MAX_VALUE);
System.out.println("double: até " + Double.MAX_VALUE);
System.out.println("char: " + (int) Character.MIN_VALUE + " a " + (int) Character.MAX_VALUE);
System.out.println("bits de um int: " + Integer.SIZE + ", bytes: " + Integer.BYTES);
}
}
$ javac Main.java && java Main byte: -128 a 127 short: -32768 a 32767 int: -2147483648 a 2147483647 long: -9223372036854775808 a 9223372036854775807 float: até 3.4028235E38 double: até 1.7976931348623157E308 char: 0 a 65535 bits de um int: 32, bytes: 4
3.4028235E38 é a notação científica que o Java usa para números enormes: quer dizer 3,4028235 × 1038 (explicada em double e float). O (int) antes de Character.MIN_VALUE pede para mostrar o código numérico em vez do caractere; isso se chama casting (Conversão de Tipos).
Missão: no JShell, descubra o maior valor que cabe num int. Digite Integer.MAX_VALUE e aperte Enter. Depois, por curiosidade, experimente Long.MAX_VALUE e Byte.MIN_VALUE.
Integer.MAX_VALUE
O valor padrão
A coluna "valor padrão" da tabela é o valor que o Java coloca sozinho em variáveis que ficam dentro de objetos e arrays (os atributos e os elementos de um array, assuntos de outras aulas). O JShell, que guarda as variáveis de um jeito parecido, mostra esses valores quando você declara sem atribuir:
$ jshell | Welcome to JShell -- Version 25.0.4.1 | For an introduction type: /help intro jshell> int x; x ==> 0 jshell> double d; d ==> 0.0 jshell> boolean b; b ==> false jshell> char c; c ==> '\000' jshell> String s; s ==> null jshell> /exit | Goodbye
'\000' é o caractere de código zero (invisível). null quer dizer "nenhum objeto"; você vai entender na próxima seção.
main não ganham valor padrão
Num programa, as variáveis declaradas dentro de um método (como o main) são variáveis locais e começam sem valor nenhum. Usar uma delas antes de atribuir dá variable … might not have been initialized, como você viu em Variáveis. O valor padrão vale só para atributos e arrays (e para o JShell).
Primitivo × referência: e a String?
Você já usou String e ela não está na lista dos oito. Isso porque String não é primitivo: é uma classe, e as variáveis de classes são de tipo de referência.
| Tipo primitivo | Tipo de referência | |
|---|---|---|
| Quais são | Só os 8: byte short int long float double char boolean | Todos os outros: String, Scanner, arrays, as classes que você criar… |
| Como se escreve | Tudo minúsculo: int | Por convenção, começa com maiúscula: String |
| O que a variável guarda | O próprio valor (29) | O endereço de um objeto que mora em outro lugar da memória |
| Tem métodos (ações com ponto)? | Não | Sim: nome.length(), nome.toUpperCase() |
Pode valer null? | Não | Sim (null = "não aponta para nenhum objeto") |
Na comparação da caixa: uma variável primitiva é uma caixa com o valor dentro. Uma variável de referência é uma caixa com um papel anotado com o endereço de onde o objeto está guardado. O objeto String sabe fazer coisas, como contar as próprias letras; um int é só um número.
public class Main {
public static void main(String[] args) {
String nome = "Ana";
int idade = 29;
System.out.println(nome.length());
System.out.println(nome.toUpperCase());
System.out.println(idade.length());
}
}
$ javac Main.java
Main.java:7: error: int cannot be dereferenced
System.out.println(idade.length());
^
1 error
"int não pode ser desreferenciado": o ponto (.) depois de uma variável quer dizer "vá até o objeto e peça algo a ele". Um int não aponta para objeto nenhum, então não há onde ir. Sem a linha 7, o programa compila e mostra 3 (o número de letras) e ANA. Strings ganham aulas próprias: Strings e Métodos de String. A diferença entre guardar o valor e guardar o endereço volta em Classes e Objetos.
int tem Integer, double tem Double, char tem Character, boolean tem Boolean, e assim por diante. São elas que guardam as constantes como Integer.MAX_VALUE e métodos úteis como Integer.parseInt. Veja Wrappers e Autoboxing.
Como escolher o tipo
Na prática, quatro tipos resolvem quase tudo. Comece por esta tabela:
| Você quer guardar… | Use | Exemplo |
|---|---|---|
| Quantidades, contagens, idades, anos | int | int alunos = 32; |
| Números inteiros que podem passar de 2 bilhões (população mundial, milissegundos, tamanho de arquivos) | long | long populacao = 8100000000L; |
| Medidas e contas com vírgula (altura, média, temperatura) | double | double media = 7.5; |
| Sim ou não, ligado ou desligado | boolean | boolean aprovada = true; |
| Uma única letra ou símbolo | char | char turma = 'B'; |
| Texto (nome, frase, até uma letra só, se for "texto") | String (referência) | String nome = "Ana"; |
| Dinheiro | BigDecimal (referência) | Veja BigDecimal e Dinheiro |
| Economizar memória em milhões de valores pequenos | byte, short, float | Raro em programas do dia a dia |
byte para uma idade, já que cabe?
Poderia, mas não vale a pena. As contas em Java são feitas em int (você vai ver em Conversão de Tipos que byte + byte dá int), então um byte obriga a conversões chatas, e a economia de 3 bytes não faz diferença num programa comum. Use int como padrão para inteiros e double para decimais.
Você não faz contas com eles, eles podem começar com zero (01310-100) e o CPF passa do limite do int. Guarde em String: String cep = "01310-100";.
Quando dá errado
public class Main {
public static void main(String[] args) {
string nome = "Ana";
}
}
$ javac Main.java
Main.java:3: error: cannot find symbol
string nome = "Ana";
^
symbol: class string
location: class Main
1 error
O que quer dizer: o Java procurou uma classe chamada string (minúsculo) e não achou. A classe se chama String, com S maiúsculo. O erro inverso também existe: Int idade = 29; dá symbol: class Int, porque os primitivos são sempre minúsculos.
Como consertar: primitivos em minúsculas (int, double, boolean); String com maiúscula.
$ javac Main.java
Main.java:3: error: incompatible types: possible lossy conversion from int to byte
byte idade = 200;
^
1 error
O que quer dizer: 200 passa do limite do byte (127). O Java trata o 200 como um int e avisa que guardá-lo num byte perderia informação. Com byte idade = 100; não há erro: o Java vê que 100 cabe.
Como consertar: use um tipo maior (int). Os limites e o que acontece quando um número passa deles estão em int, long, short, byte.
O que quer dizer: você colocou um ponto depois de uma variável primitiva (idade.length(), preco.toString()). Primitivos não têm métodos.
Como consertar: use os métodos das classes embrulho, que recebem o valor entre parênteses: String.valueOf(idade) ou Integer.toString(idade) transformam o número em texto (Conversão de Tipos).
Missão: a professora Ana declarou tudo como int e o programa não compila. Troque o tipo de cada variável pelo tipo certo (e, se precisar, as aspas do valor) para a saída ser 32 7.5 B true.
public class Main {
public static void main(String[] args) {
int alunos = 32;
int media = 7.5;
int turma = "B";
int aprovada = true;
System.out.println(alunos + " " + media + " " + turma + " " + aprovada);
}
}
public class Main {
public static void main(String[] args) {
int alunos = 32;
double media = 7.5;
char turma = 'B';
boolean aprovada = true;
System.out.println(alunos + " " + media + " " + turma + " " + aprovada);
}
}
Referência
| Tipo | Literal (como escrever o valor) | Máximo / mínimo | Classe embrulho |
|---|---|---|---|
byte | 7 | Byte.MAX_VALUE / Byte.MIN_VALUE | Byte |
short | 1997 | Short.MAX_VALUE / Short.MIN_VALUE | Short |
int | 29, 1_000_000 | Integer.MAX_VALUE / Integer.MIN_VALUE | Integer |
long | 29L | Long.MAX_VALUE / Long.MIN_VALUE | Long |
float | 36.5f | Float.MAX_VALUE | Float |
double | 9.90, 1.5e3 | Double.MAX_VALUE | Double |
char | 'A', 'é' | Character.MAX_VALUE | Character |
boolean | true, false | — | Boolean |
Exercícios
1. O tipo da média
Complete com o tipo mais indicado para guardar a média 8.25:
2. Sim ou não
Complete com o tipo primitivo que guarda true ou false:
3. Quantos tipos?
Quantos tipos primitivos o Java tem? Escreva o número:
4. Qual destes não é um tipo primitivo?
5. Qual o melhor tipo para guardar um CEP como 01310-100?
6. O que acontece com byte nota = 300;?
7. Por que idade.length() não compila quando idade é int?
Resumo
- O Java tem 8 tipos primitivos:
byte,short,int,long(inteiros),float,double(decimais),char(um caractere) eboolean(verdadeiro/falso). - Cada tipo tem tamanho e faixa fixos; as constantes
Integer.MAX_VALUEe companhia mostram os limites. - Os tipos deixam o
javacachar erros antes de o programa rodar (incompatible types). Stringnão é primitivo: é uma classe (tipo de referência), começa com maiúscula, tem métodos e pode sernull.- Valor padrão (0,
false,null…) só vale para atributos e arrays; variáveis locais precisam de valor antes do uso. - No dia a dia:
int,longpara números muito grandes,double,boolean,chareString.