AFF Education Construa seu Futuro

Aula 60 — O operador new e a memória em Java

Entenda o que new realmente faz e que tipo de "gaveta" ele constrói para cada estrutura

O que o new faz, exatamente?

Toda vez que você escreve new em Java, três coisas acontecem nos bastidores:

  1. Alocação de memória — o Java reserva espaço na memória heap para guardar os dados do objeto.
  2. Inicialização — o construtor da classe é chamado e os valores iniciais são definidos.
  3. Retorno da referência — o endereço desse espaço de memória é devolvido e armazenado na variável.
O operador new constrói um objeto na memória (heap) e devolve uma referência — um endereço — para a variável que está do lado esquerdo do =.

Analogia da gaveta: pense no new como um carpinteiro que constrói uma gaveta sob encomenda e entrega a etiqueta com o endereço de onde a gaveta foi colocada. A variável guarda essa etiqueta — não a gaveta em si.

// "nomes" guarda o ENDEREÇO da ArrayList na memória, não a lista em si
ArrayList<String> nomes = new ArrayList<>();
//                         ↑ new constrói a gaveta e devolve o endereço

// Consequência: duas variáveis podem apontar para a MESMA gaveta
ArrayList<String> copia = nomes;  // copia aponta para a mesma gaveta!
nomes.add("Java");
System.out.println(copia);        // imprime [Java] — mesma gaveta!

[Java]

⚠ Atenção: copia = nomes não cria uma segunda gaveta — apenas copia a etiqueta (referência). Para criar uma cópia independente, use new ArrayList<>(nomes).

As diferentes gavetas que new constrói

O new é usado com muitos tipos em Java, mas cada um organiza sua gaveta de uma forma diferente. Veja abaixo:

Figura mostrando 6 tipos de gavetas criadas pelo operador new em Java: Array, ArrayList, HashMap, Classe, String e Scanner

Cada new constrói um tipo diferente de gaveta na memória heap

1. Array [] — gaveta com N compartimentos fixos

O array é a gaveta mais simples: você define o número de compartimentos na criação e ele nunca muda. Cada compartimento é acessado pelo seu índice numérico (começando em 0).

public class GavetaArray {
    public static void main(String[] args) {
        // new int[4] constrói gaveta com exatamente 4 compartimentos
        int[] nums = new int[4];

        nums[0] = 10;
        nums[1] = 20;
        nums[2] = 30;
        nums[3] = 40;
        // nums[4] = 50;  → ArrayIndexOutOfBoundsException!

        System.out.println("Tamanho: " + nums.length);
        for (int i = 0; i < nums.length; i++) {
            System.out.println("[" + i + "] = " + nums[i]);
        }
    }
}

Tamanho: 4

[0] = 10

[1] = 20

[2] = 30

[3] = 40

Características da gaveta Array: compartimentos numerados de 0 a N-1 · tamanho definido na criação e imutável · aceita tipos primitivos diretamente (int, double, etc.) · acesso via [] · tamanho via .length

2. ArrayList — gaveta elástica

O ArrayList é uma gaveta que cresce e encolhe automaticamente. Você não precisa dizer quantos compartimentos quer — a estrutura gerencia isso sozinha por baixo dos panos. Por isso ela exige um tipo de referência (wrapper) no lugar de primitivos.

import java.util.ArrayList;

public class GavetaArrayList {
    public static void main(String[] args) {
        // new ArrayList<>() constrói a gaveta elástica vazia
        ArrayList<String> linguagens = new ArrayList<>();

        linguagens.add("Java");      // gaveta cresce para 1
        linguagens.add("Python");    // gaveta cresce para 2
        linguagens.add("C++");       // gaveta cresce para 3

        System.out.println("Tamanho: " + linguagens.size());
        System.out.println("Elemento 0: " + linguagens.get(0));

        linguagens.remove("Python"); // gaveta encolhe para 2
        System.out.println("Após remover Python: " + linguagens);
    }
}

Tamanho: 3

Elemento 0: Java

Após remover Python: [Java, C++]

Características da gaveta ArrayList: tamanho dinâmico · só aceita tipos de referência (Integer, Double, String…) · acesso via .get(índice) · tamanho via .size() · métodos prontos: add, remove, contains, set…

3. HashMap — gaveta com etiquetas (chave → valor)

O HashMap não usa índices numéricos — cada compartimento tem uma chave personalizada (qualquer String, número ou objeto). É ideal para representar registros com campos nomeados.

import java.util.HashMap;

public class GavetaHashMap {
    public static void main(String[] args) {
        // new HashMap<>() constrói gaveta de pares chave-valor
        HashMap<String, Object> pessoa = new HashMap<>();

        pessoa.put("nome",  "Ana");
        pessoa.put("idade", 28);
        pessoa.put("nota",  9.5);
        pessoa.put("ativo", true);

        System.out.println("Nome: "  + pessoa.get("nome"));
        System.out.println("Idade: " + pessoa.get("idade"));
        System.out.println("Nota: "  + pessoa.get("nota"));

        // verificar se chave existe
        System.out.println("Tem 'email'? " + pessoa.containsKey("email"));

        // percorrer todos os pares
        for (String chave : pessoa.keySet()) {
            System.out.println(chave + " → " + pessoa.get(chave));
        }
    }
}

Nome: Ana

Idade: 28

Nota: 9.5

Tem 'email'? false

nome → Ana

idade → 28

nota → 9.5

ativo → true

Características da gaveta HashMap: acesso por chave, não por índice · chaves são únicas (repetir sobrescreve) · ordem de iteração não é garantida · acesso via .get(chave) · inserção via .put(chave, valor)

4. Instância de Classe — gaveta com atributos nomeados

Quando você usa new NomeDaClasse(), está construindo um objeto cujos compartimentos são os atributos definidos na classe. É a gaveta mais flexível: você define o formato dela ao escrever a classe.

public class Carro {
    // Atributos = compartimentos da gaveta
    String marca;
    String modelo;
    int    ano;
    double velocidade;

    // Construtor = instruções para montar a gaveta
    public Carro(String marca, String modelo, int ano) {
        this.marca      = marca;
        this.modelo     = modelo;
        this.ano        = ano;
        this.velocidade = 0.0;
    }
}

public class GavetaClasse {
    public static void main(String[] args) {
        // new Carro(...) constrói a gaveta com 4 compartimentos nomeados
        Carro c = new Carro("Toyota", "Corolla", 2024);

        System.out.println("Marca: "      + c.marca);
        System.out.println("Modelo: "     + c.modelo);
        System.out.println("Ano: "        + c.ano);
        System.out.println("Velocidade: " + c.velocidade);
    }
}

Marca: Toyota

Modelo: Corolla

Ano: 2024

Velocidade: 0.0

Características da gaveta Objeto: compartimentos = atributos definidos na classe · construtor inicializa os valores · acesso via objeto.atributo ou objeto.metodo() · cada new cria uma gaveta independente (instância própria)

5. String — gaveta imutável de caracteres

A String também é um objeto — internamente ela armazena uma sequência de caracteres. O detalhe importante: uma vez criada, ela não pode ser modificada. Qualquer operação como concatenar ou trocar letras cria uma nova gaveta na memória.

public class GavetaString {
    public static void main(String[] args) {
        // Forma literal — Java cria o objeto automaticamente
        String s1 = "Java";

        // Forma explícita com new — menos comum, mas válida
        String s2 = new String("Java");

        // Concatenar não modifica s1 — cria uma NOVA gaveta
        String s3 = s1 + " é ótimo!";

        System.out.println(s1);          // s1 continua "Java"
        System.out.println(s2);
        System.out.println(s3);          // nova gaveta: "Java é ótimo!"
        System.out.println(s1.length()); // 4 caracteres
        System.out.println(s1.toUpperCase()); // outra gaveta nova: "JAVA"
    }
}

Java

Java

Java é ótimo!

4

JAVA

💡 Dica: por causa da imutabilidade, o Java reutiliza Strings idênticas em um pool interno. Por isso "Java" == "Java" pode ser true, mas new String("Java") == new String("Java") é false — cada new força a criação de uma gaveta nova. Para comparar conteúdo de Strings, sempre use .equals().

6. Scanner — gaveta de comportamento (leitura)

O Scanner mostra que new não serve só para guardar dados: ele também constrói objetos que encapsulam comportamento. A gaveta do Scanner não tem dados fixos — ela conecta seu programa ao teclado (ou a um arquivo) e disponibiliza métodos de leitura.

import java.util.Scanner;

public class GavetaScanner {
    public static void main(String[] args) {
        // new Scanner(System.in) conecta a gaveta ao teclado
        Scanner sc = new Scanner(System.in);

        System.out.print("Digite seu nome: ");
        String nome = sc.nextLine();   // lê texto

        System.out.print("Digite sua idade: ");
        int idade = sc.nextInt();      // lê inteiro

        System.out.println("Olá, " + nome + "! Você tem " + idade + " anos.");

        sc.close(); // boa prática: fechar o Scanner quando não precisar mais
    }
}

Digite seu nome: Ana

Digite sua idade: 28

Olá, Ana! Você tem 28 anos.

Características da gaveta Scanner: conecta a uma fonte de dados (teclado, arquivo…) · não armazena seus dados — processa o fluxo de entrada · deve ser fechada com .close() ao terminar · exemplifica que objetos encapsulam comportamento, não apenas dados

Resumo: qual gaveta o new constrói?

Expressão com new Tipo de gaveta Acesso aos compartimentos Tamanho
new int[N] Array de N compartimentos fixos v[0], v[1]… Fixo (.length)
new ArrayList<>() Lista elástica numerada .get(0), .get(1)… Dinâmico (.size())
new HashMap<>() Dicionário chave → valor .get("chave") Dinâmico (.size())
new Carro(...) Objeto com atributos nomeados c.marca, c.ano… Fixo (definido na classe)
new String("...") Sequência imutável de chars .charAt(0), .substring()… Fixo após criação
new Scanner(System.in) Objeto de comportamento (leitura) .nextLine(), .nextInt()… N/A — fluxo de dados
Regra geral: em Java, tudo que não é tipo primitivo (int, double, boolean, char…) é um objeto — e todo objeto foi criado por um new em algum momento, seja explicitamente por você, seja automaticamente pelo Java nos bastidores.

Exercícios

Teste seus conhecimentos sobre o operador new e os tipos de gavetas em Java:

1. O que o operador new faz em Java?

2. Qual é a diferença entre ArrayList e Array no que diz respeito ao tamanho?

3. No código abaixo, o que a variável lista2 contém?
ArrayList<String> lista1 = new ArrayList<>();
ArrayList<String> lista2 = lista1;

4. Como o HashMap organiza seus compartimentos?

5. Por que uma String é chamada de "gaveta imutável"?

6. O que o new Scanner(System.in) constrói?

7. Qual afirmação sobre o operador new e tipos primitivos é correta?

Exercícios de Aplicação AFF Education

Reforce o conteúdo desta aula com mais dois exercícios práticos:

1. O que o operador new faz em int[] v = new int[5];?

2. Em ArrayList<String> l = new ArrayList<>();, a variável l guarda: