Java Arrays

A professora Ana tem uma turma com 30 alunos. Para guardar as notas com o que você aprendeu até agora, ela precisaria de 30 variáveis: nota1, nota2, …, nota30. E para tirar a média, uma conta com 30 parcelas. O array resolve isso: uma variável que guarda vários valores do mesmo tipo, cada um numa posição numerada.

Você vai aprender
  • O que é um array e quando usar.
  • As duas formas de criar: new int[5] (vazio, com tamanho) e {7, 8, 6} (já com os valores).
  • Por que as posições (os índices) começam no 0, e como usar o length.
  • Os valores que um array novo já tem (os valores padrão).
  • Como ler e mudar um elemento.
  • O erro mais famoso dos arrays: ArrayIndexOutOfBoundsException.
  • Por que System.out.println(notas) mostra [I@1e9e725a, e como mostrar o array de verdade.
  • Arrays de String.

Os exemplos rodam no terminal da Ana (máquina fictícia notebook, pasta ~/java, JDK 25) com java Main.java.


A ideia antes do código

Pense num armário de escola com gavetas numeradas, todas do mesmo tamanho, uma ao lado da outra. O armário inteiro tem um nome ("o armário da turma B") e cada gaveta tem um número. Para pegar algo, você diz: "o armário da turma B, gaveta 3".

Um array é esse armário:

  • O nome do array é o nome do armário: notas.
  • Cada gaveta é um elemento e guarda um valor.
  • O número da gaveta é o índice. E aqui vem a surpresa: a primeira gaveta é a de número 0.
  • Todas as gavetas guardam o mesmo tipo de coisa: um array de int só guarda int.
  • O número de gavetas é decidido na construção e não muda depois.
Índice01234
Valor786910
Como acessarnotas[0]notas[1]notas[2]notas[3]notas[4]

Array, em inglês, quer dizer "arranjo, fileira organizada". Em português também se fala vetor (comum na faculdade) ou arranjo. É tudo a mesma coisa.


Criar um array já com os valores

Quando você já sabe o que vai guardar, escreva os valores entre chaves:

public class Main {
    public static void main(String[] args) {
        int[] notas = {7, 8, 6, 9, 10};
        System.out.println("Primeira nota: " + notas[0]);
        System.out.println("Terceira nota: " + notas[2]);
        System.out.println("Última nota: " + notas[4]);
        System.out.println("Quantidade de notas: " + notas.length);
    }
}
$ java Main.java
Primeira nota: 7
Terceira nota: 6
Última nota: 10
Quantidade de notas: 5
int[]
O tipo: "array de int". Os colchetes [] são o que transforma int (um número) em int[] (vários números).
notas
O nome da variável. Use plural: ela guarda várias notas.
=
Atribuição, como em qualquer variável.
{7, 8, 6, 9, 10};
Os valores, entre chaves e separados por vírgula. O Java conta quantos são (5) e cria o array desse tamanho.

E para usar:

notas
O array.
[2]
O índice entre colchetes: "a gaveta 2". Como a contagem começa no 0, é o terceiro elemento.

Por que começa no 0?

Pense no índice como "quantas gavetas eu ando a partir do começo". A primeira gaveta está a 0 passos do início; a segunda, a 1 passo; a terceira, a 2. Essa é a herança da linguagem C, e quase todas as linguagens populares (Java, C#, JavaScript, Python) seguem a mesma regra. A consequência prática:

  • O primeiro elemento é sempre [0].
  • Num array de tamanho 5, o último é [4]. Em geral, o último é [length - 1].
  • O elemento "número N" (contando como gente) está no índice N - 1.

length: o tamanho

notas.length ("comprimento") diz quantos elementos o array tem. Repare: é sem parênteses. Na String é texto.length(), com parênteses, porque lá é um método; no array, length é um campo fixo. Trocar um pelo outro é um erro muito comum (veja "Quando dá errado").

Um exemplo com os dias da semana, usando o length para achar o último:

import java.util.Arrays;

public class Main {
    public static void main(String[] args) {
        String[] semana = {"domingo", "segunda", "terça", "quarta", "quinta", "sexta", "sábado"};
        System.out.println("Hoje é " + semana[5]);
        System.out.println("A semana tem " + semana.length + " dias");
        semana[0] = "DOMINGO";
        System.out.println(Arrays.toString(semana));
        System.out.println("Último dia: " + semana[semana.length - 1]);
    }
}
$ java Main.java
Hoje é sexta                 « semana[5]: o sexto elemento
A semana tem 7 dias
[DOMINGO, segunda, terça, quarta, quinta, sexta, sábado]
Último dia: sábado           « semana[7 - 1] = semana[6]

(O Arrays.toString mostra o array inteiro; ele é explicado mais abaixo, em Imprimir um array.)


Criar um array vazio, com tamanho: new

Às vezes você sabe quantos valores vai guardar, mas ainda não sabe quais: as notas de 5 alunos que ainda vão fazer a prova. Aí você cria o array com new e o tamanho:

public class Main {
    public static void main(String[] args) {
        int[] notas = new int[5];
        System.out.println("Antes: " + notas[0] + " " + notas[1] + " " + notas[2]);
        notas[0] = 7;
        notas[1] = 8;
        notas[2] = 6;
        System.out.println("Depois: " + notas[0] + " " + notas[1] + " " + notas[2]);
        System.out.println("Tamanho: " + notas.length);
    }
}
$ java Main.java
Antes: 0 0 0                 « um array novo de int já vem cheio de zeros
Depois: 7 8 6
Tamanho: 5                   « o tamanho é 5, mesmo com só 3 notas preenchidas
int[] notas
Declara a variável do tipo "array de int".
=
Atribuição.
new
"Novo": pede ao Java para construir um array novo na memória. A mesma palavra cria objetos, como você verá em Classes e Objetos.
int[5];
O tipo dos elementos e, entre colchetes, o tamanho: 5 gavetas, de [0] a [4].

O tamanho pode vir de uma variável ou de uma conta (new int[quantidadeDeAlunos]), mas, uma vez criado, o array não cresce nem diminui. Para listas que mudam de tamanho, o Java tem o ArrayList.

Os valores padrão

Um array criado com new nunca vem com "lixo": cada tipo tem um valor inicial, chamado valor padrão:

public class Main {
    public static void main(String[] args) {
        int[] inteiros = new int[2];
        double[] decimais = new double[2];
        boolean[] marcados = new boolean[2];
        char[] letras = new char[2];
        String[] nomes = new String[2];
        System.out.println("int: " + inteiros[0]);
        System.out.println("double: " + decimais[0]);
        System.out.println("boolean: " + marcados[0]);
        System.out.println("char: código " + (int) letras[0]);
        System.out.println("String: " + nomes[0]);
    }
}
$ java Main.java
int: 0
double: 0.0
boolean: false
char: código 0               « o caractere de código 0, que não aparece na tela
String: null                 « null = "nenhum texto ainda"
Tipo do arrayValor padrão
int[], long[], short[], byte[]0
double[], float[]0.0
boolean[]false
char[]o caractere de código 0 ('\u0000'), invisível
String[] e qualquer outro objetonull ("nada")

Isso é diferente das variáveis comuns dentro do main, que não têm valor padrão: usar uma sem dar valor é erro de compilação (variable … might not have been initialized, veja Variáveis).

Chaves ou new?

FormaExemploQuando usar
Chaves (inicializador)int[] notas = {7, 8, 6};Você já sabe os valores. Só vale na mesma linha da declaração.
new com tamanhoint[] notas = new int[30];Você sabe quantos, mas os valores virão depois (do teclado, de uma conta, de um arquivo).
new com chavesnotas = new int[] {7, 8, 6};Você quer dar valores a uma variável já declarada, ou passar um array direto para um método.
Colchetes no nome (estilo C)int notas[] = {7, 8, 6};Funciona, mas evite: o estilo Java é int[] notas, com o tipo inteiro junto.

Mudar um elemento

Cada elemento funciona como uma variável comum: dá para atribuir, somar, usar ++ e --. A professora revisou duas provas: a terceira nota sobe 2 pontos e a última perde 1:

import java.util.Arrays;

public class Main {
    public static void main(String[] args) {
        int[] notas = {7, 8, 6, 9, 10};
        notas[2] = notas[2] + 2;
        notas[4]--;
        System.out.println(Arrays.toString(notas));
    }
}
$ java Main.java
[7, 8, 8, 9, 9]

Missão: a nota do terceiro aluno foi lançada errada: era 10. Acrescente uma linha que corrige esse elemento, para a saída ficar [7, 8, 10, 9, 10]. Lembre: terceiro aluno, índice…?

import java.util.Arrays;

public class Main {
    public static void main(String[] args) {
        int[] notas = {7, 8, 6, 9, 10};
        // corrija a nota aqui

        System.out.println(Arrays.toString(notas));
    }
}
import java.util.Arrays;

public class Main {
    public static void main(String[] args) {
        int[] notas = {7, 8, 6, 9, 10};
        notas[2] = 10;
        System.out.println(Arrays.toString(notas));
    }
}

Cuidado: = não copia o array

A variável do array guarda o endereço do armário, não as gavetas. Por isso, int[] outro = original; não cria um segundo armário: cria um segundo nome para o mesmo armário.

import java.util.Arrays;

public class Main {
    public static void main(String[] args) {
        int[] original = {7, 8, 6};
        int[] outro = original;
        outro[0] = 0;
        System.out.println("original: " + Arrays.toString(original));
        System.out.println("outro:    " + Arrays.toString(outro));
    }
}
$ java Main.java
original: [0, 8, 6]          « mudou também!
outro:    [0, 8, 6]

Mexer em outro[0] mudou o original, porque os dois nomes apontam para o mesmo array. Para ter uma cópia de verdade, use Arrays.copyOf, ensinado em A Classe Arrays.


Fora dos limites: ArrayIndexOutOfBoundsException

O que acontece se você pede uma gaveta que não existe? O array notas tem 5 elementos (índices 0 a 4). Vamos pedir o índice 5:

public class Main {
    public static void main(String[] args) {
        int[] notas = {7, 8, 6, 9, 10};
        System.out.println(notas[5]);
    }
}
$ java Main.java
Exception in thread "main" java.lang.ArrayIndexOutOfBoundsException: Index 5 out of bounds for length 5
	at Main.main(Main.java:4)

Repare que o programa compila: o javac não verifica índices, porque normalmente eles vêm de contas e variáveis que só têm valor quando o programa roda. O erro aparece durante a execução, como uma exceção (o assunto de O que são Exceções). Vamos ler a mensagem por partes:

Exception in thread "main"
"Exceção na linha de execução main": o programa parou por um erro.
java.lang.ArrayIndexOutOfBoundsException:
O tipo do erro: "índice de array fora dos limites" (out of bounds = "fora da área permitida").
Index 5 out of bounds for length 5
O detalhe: "o índice 5 está fora dos limites para o tamanho 5". Num array de tamanho 5, o maior índice válido é 4.
at Main.main(Main.java:4)
Onde: no método main da classe Main, arquivo Main.java, linha 4.

Índice negativo também não existe:

$ java Main.java              « o mesmo programa, agora com notas[-1]
Exception in thread "main" java.lang.ArrayIndexOutOfBoundsException: Index -1 out of bounds for length 5
	at Main.main(Main.java:4)

Os casos mais comuns na vida real: usar notas[notas.length] para pegar o último (o certo é length - 1) e laços com <= no lugar de < (for (int i = 0; i <= notas.length; i++) dá uma volta a mais). Os laços sobre arrays têm a sua aula: Percorrer Arrays.


Imprimir um array: o mistério do [I@

A primeira coisa que todo iniciante tenta é mandar o array inteiro para o println. Veja o que sai:

import java.util.Arrays;

public class Main {
    public static void main(String[] args) {
        int[] notas = {7, 8, 6, 9, 10};
        double[] precos = {4.5, 12.0};
        String[] frutas = {"maçã", "uva"};
        System.out.println(notas);
        System.out.println(precos);
        System.out.println(frutas);
        System.out.println(Arrays.toString(notas));
        System.out.println(Arrays.toString(precos));
        System.out.println(Arrays.toString(frutas));
    }
}
$ java Main.java
[I@1e9e725a
[D@15d9bc04
[Ljava.lang.String;@473b46c3
[7, 8, 6, 9, 10]
[4.5, 12.0]
[maçã, uva]

As três primeiras linhas não são um erro nem lixo: é o "crachá" do array, o jeito padrão que o Java tem de descrever um objeto que não sabe se mostrar. Ele tem três partes:

[
"Isto é um array".
I
O tipo dos elementos, num código de uma letra: I = int, D = double, Z = boolean, C = char, J = long. Para objetos, L + o nome completo da classe + ;, como Ljava.lang.String;.
@
Separador.
1e9e725a
Um número de identificação do objeto (o hash code), escrito em hexadecimal. Não tem nada a ver com os valores guardados e não serve para você.

Para ver o conteúdo, use Arrays.toString(array), que monta o texto [elemento, elemento, …]. Ele mora na classe java.util.Arrays, por isso o import java.util.Arrays; no topo (sem ele, o javac diz cannot find symbol). Essa classe tem várias outras ferramentas, como ordenar e copiar: veja A Classe Arrays. Outra forma é percorrer o array com um laço e mostrar elemento por elemento, como em Percorrer Arrays.

E o array de char?

É a exceção: System.out.println tem uma versão especial para char[] e mostra as letras juntas, como um texto. char[] l = {'o', 'i'}; System.out.println(l); mostra oi. Mas basta juntar com texto ("Letras: " + l) para voltar o "crachá" [C@….


Arrays de String

Tudo o que você viu vale para textos. Um array de nomes, de frutas, de dias da semana:

String[] alunos = {"Ana", "Bruno", "Carla"};
String[] chamada = new String[30];   // 30 posições, todas null

A diferença está no valor padrão: null. Ele significa "esta gaveta ainda não tem texto nenhum", e não é o mesmo que um texto vazio "". Mostrar um null funciona (aparece a palavra null), mas usar um método nele derruba o programa:

public class Main {
    public static void main(String[] args) {
        String[] nomes = new String[3];
        nomes[0] = "Ana";
        System.out.println(nomes[0].length());
        System.out.println(nomes[1].length());
    }
}
$ java Main.java
3                            « "Ana" tem 3 letras
Exception in thread "main" java.lang.NullPointerException: Cannot invoke "String.length()" because "<local1>[1]" is null
	at Main.main(Main.java:6)

NullPointerException ("exceção de ponteiro nulo") é a exceção mais comum do Java. A mensagem diz: "não dá para chamar String.length() porque <local1>[1] é null". O <local1> é como o Java chama a variável nomes quando o programa foi compilado sem os nomes das variáveis (o padrão do java Main.java e do javac comum). Compilando com javac -g Main.java, que guarda esses nomes, a mesma linha fica mais clara:

$ javac -g Main.java
$ java Main
3
Exception in thread "main" java.lang.NullPointerException: Cannot invoke "String.length()" because "nomes[1]" is null
	at Main.main(Main.java:6)

A gaveta nomes[1] nunca recebeu um nome. Preencha antes de usar, ou teste com if (nomes[1] != null).


Quando dá errado

"array dimension missing"
public class Main {
    public static void main(String[] args) {
        int[] notas = new int[];
    }
}
$ java Main.java
Main.java:3: error: array dimension missing
        int[] notas = new int[];
                               ^
1 error
error: compilation failed

O que quer dizer: "falta a dimensão do array". Com new, o Java precisa saber o tamanho: new int[5]. Ou então os valores: new int[] {7, 8, 6}.

"possible lossy conversion from double to int"
public class Main {
    public static void main(String[] args) {
        int[] notas = {7, 8.5, 6};
    }
}
$ java Main.java
Main.java:3: error: incompatible types: possible lossy conversion from double to int
        int[] notas = {7, 8.5, 6};
                          ^
1 error
error: compilation failed

O que quer dizer: "conversão com possível perda de double para int". Todos os elementos têm o mesmo tipo; um int[] não guarda o 8.5. O ^ aponta o intruso.

Como consertar: se as notas podem ter vírgula, use double[] notas = {7, 8.5, 6}; (o 7 e o 6 viram 7.0 e 6.0 sozinhos).

"illegal start of expression" ao usar chaves depois
public class Main {
    public static void main(String[] args) {
        int[] notas;
        notas = {7, 8, 6};
    }
}
$ java Main.java
Main.java:4: error: illegal start of expression
        notas = {7, 8, 6};
                ^
Main.java:4: error: not a statement
        notas = {7, 8, 6};
                 ^
Main.java:4: error: ';' expected
        notas = {7, 8, 6};
                  ^
3 errors
error: compilation failed

O que quer dizer: as chaves sozinhas só valem na mesma linha da declaração. Numa atribuição depois, o javac não entende o { e se perde (três erros, uma causa).

Como consertar: notas = new int[] {7, 8, 6};.

"cannot find symbol … method length()"
public class Main {
    public static void main(String[] args) {
        int[] notas = {7, 8, 6};
        System.out.println(notas.length());
    }
}
$ java Main.java
Main.java:4: error: cannot find symbol
        System.out.println(notas.length());
                                ^
  symbol:   method length()
  location: variable notas of type int[]
1 error
error: compilation failed

O que quer dizer: "não encontro o método length() na variável notas, do tipo int[]". Array não tem método length(); tem o campo length.

Como consertar: notas.length, sem parênteses. Para lembrar: array, sem parênteses; String, com: nome.length().

"cannot find symbol … variable Arrays": faltou o import
public class Main {
    public static void main(String[] args) {
        int[] notas = {7, 8};
        System.out.println(Arrays.toString(notas));
    }
}
$ java Main.java
Main.java:4: error: cannot find symbol
        System.out.println(Arrays.toString(notas));
                           ^
  symbol:   variable Arrays
  location: class Main
1 error
error: compilation failed

O que quer dizer: o javac não conhece o nome Arrays. A classe existe, mas mora no pacote java.util, e é preciso avisar que você vai usá-la (veja Pacotes e import).

Como consertar: acrescente import java.util.Arrays; na primeira linha do arquivo, antes de public class Main.

NegativeArraySizeException
public class Main {
    public static void main(String[] args) {
        int quantidade = -3;
        int[] notas = new int[quantidade];
    }
}
$ java Main.java
Exception in thread "main" java.lang.NegativeArraySizeException: -3
	at Main.main(Main.java:4)

O que quer dizer: "tamanho de array negativo: -3". Não existe armário com -3 gavetas. Acontece quando o tamanho vem de uma conta ou do usuário; valide o número antes (um tamanho 0 é permitido e cria um array vazio).


Referência

CódigoO que faz
int[] a = {1, 2, 3};Cria um array com esses valores (tamanho 3)
int[] a = new int[5];Cria um array de 5 elementos, todos com o valor padrão (0)
a = new int[] {1, 2, 3};Cria e atribui a uma variável já declarada
a[0]O primeiro elemento
a[a.length - 1]O último elemento
a[2] = 10;Muda o terceiro elemento
a.lengthQuantidade de elementos (sem parênteses)
Arrays.toString(a)Texto [1, 2, 3] (precisa de import java.util.Arrays;)
System.out.println(a)Mostra o "crachá", como [I@1e9e725a, e não o conteúdo
String[] s = new String[3];Três posições com null

Exercícios

1. Criar com valores

Complete para criar um array com os preços 10, 20 e 30:

int[] precos =

2. Criar vazio

Complete para criar um array de 12 double (um por mês):

double[] gastos =

3. O último

Complete o índice do último elemento, sem escrever o número:

String ultimo = nomes[];

4. Em int[] v = {4, 8, 15, 16, 23};, quanto vale v[3]?

5. O que new boolean[4] contém logo depois de criado?

6. System.out.println(notas) mostrou [I@1e9e725a. O que isso significa?

7. Num array com length igual a 10, quais são os índices válidos?

Missão final: este programa quer mostrar a última nota, mas termina com ArrayIndexOutOfBoundsException. Rode, leia a mensagem e conserte usando o length (sem escrever o número 4).

public class Main {
    public static void main(String[] args) {
        int[] notas = {7, 8, 6, 9, 10};
        System.out.println("Última nota: " + notas[notas.length]);
    }
}
public class Main {
    public static void main(String[] args) {
        int[] notas = {7, 8, 6, 9, 10};
        System.out.println("Última nota: " + notas[notas.length - 1]);
    }
}

Resumo

  • Um array guarda vários valores do mesmo tipo numa variável só. O tipo se escreve com colchetes: int[], String[].
  • Crie com os valores ({7, 8, 6}) ou com o tamanho (new int[5]). O tamanho não muda depois.
  • Os índices vão de 0 a length - 1. length não tem parênteses.
  • Arrays novos vêm com valores padrão: 0, 0.0, false ou null.
  • Um índice fora dos limites compila, mas derruba o programa com ArrayIndexOutOfBoundsException: Index 5 out of bounds for length 5.
  • println(array) mostra o "crachá" ([I@…); para ver o conteúdo, Arrays.toString(array).
  • int[] b = a; não copia: os dois nomes apontam para o mesmo array.