O Paradigma Orientado a Objetos e a Máquina Java

Aula 1 — Programação Orientada a Objetos

Marcos M. Raimundo — Instituto de Computação, UNICAMP

2026-08-26

Proposta da Aula

A pergunta desta aula inteira: como escrever software que sobrevive à mudança?

Design não é sobre como o software funciona. É sobre como ele muda.

TRUE (Sandi Metz):

  • Transparent — consequências óbvias
  • Reasonable — custo proporcional ao benefício
  • Usable — reaproveitável em contextos novos
  • Exemplary — encoraja boas práticas em quem o modifica

Roteiro: paradigma → encapsulamento → JVM → memória e parâmetros.

A Mudança de Paradigma

Procedural vs. Espaço do Problema

Procedural

  • Foco na máquina (bits, ponteiros)
  • Dados e função separados
  • Risco: dados globais, efeito colateral

Orientado a Objetos

  • Foco no domínio (Cliente, Pedido)
  • Dados e comportamento unidos
  • O código fala a língua do negócio

O Desconto no E-commerce

Procedural: preco é um número passivo; uma função externa lê, calcula, sobrescreve. Qualquer código pode alterar preco sem checar regra nenhuma.

OO: você não calcula o desconto — você diz ao Produto: “aplique 10% de desconto em si mesmo”. O objeto pode recusar.

Estado, Comportamento, Identidade e Encapsulamento

Três Propriedades de um Objeto

  • Estado — o que ele sabe agora
  • Comportamento — o que ele faz
  • Identidade — cada instância é única na memória

Encapsulamento: a Membrana

Volante e pedais (interface) vs. motor (implementação) — trocar o motor não muda como se dirige.

Information Hiding não é segurança contra hackers — é engenharia contra a fragilidade do próprio código.

O Encapsulamento Sustenta os Três Pilares

  1. Sustenta o Estado → invariantes de negócio
  2. Sustenta o ComportamentoTell, Don’t Ask
  3. Sustenta a Identidade → sem integridade, o objeto vira “zumbi” lógico

Por que “ocultar informação” é uma estratégia de engenharia, e não uma questão de segurança contra invasores?

Escreva sua resposta com suas próprias palavras e compare com um colega antes de avançar (2 min).

Encapsulamento e Ocultamento de Informação

Dica

Julgue V ou F — a questão só conta se acertar os 4 itens:

  1. Encapsulamento e Ocultamento de Informação são, na prática, o mesmo mecanismo de engenharia visto de dois ângulos.
  2. O objetivo do Ocultamento de Informação é impedir que hackers leiam os dados do objeto em tempo de execução.
  3. Um objeto sem encapsulamento perde autonomia e volta a se comportar como uma estrutura procedural.
  4. O princípio Tell, Don’t Ask propõe delegar decisões para dentro do objeto, em vez de extrair seus dados para decidir por fora.

Encapsulamento e Ocultamento de Informação — Resposta

Dica

  1. Verdadeiro — a “caixa preta” e o “Information Hiding” descrevem o mesmo mecanismo: separar o quê do como.
  2. Falso — é uma medida de engenharia contra a fragilidade e o acoplamento, não uma medida de segurança contra invasão.
  3. Verdadeiro — sem a membrana do encapsulamento, o objeto é só uma estrutura de dados manipulada de fora, como no paradigma procedural.
  4. Verdadeiro — é exatamente essa a definição de Tell, Don’t Ask.

Classe vs. Objeto/Instância

Classe (o Molde) vs. Objeto (a Realidade)

Classe

  • Abstração / contrato
  • Define atributos e métodos
  • Não ocupa espaço de instância

Objeto

  • Entidade física, na Heap
  • Valores concretos de estado
  • Identidade única

Detalhe que confunde: a classe também vive na memória — no Metaspace, carregada pelo ClassLoader. 500 clientes no banco → 500 instâncias na Heap, todas rodando o mesmo bytecode carregado uma única vez.

A Infraestrutura Java: JVM, Bytecode e JIT

Da Fonte ao Bytecode

  1. javac: .javaBytecode (.class), independente de plataforma
  2. JVM: lê o bytecode, mapeia para instruções nativas do hospedeiro
  3. WORA — mesma .class, qualquer JVM compatível

O Compilador JIT

“Bytecode interpretado” ≠ “lento” — a JVM faz profiling em tempo real.

Identifica hotspots → compila só eles para código nativo, otimizado para a CPU atual e o uso real dos dados.

Vantagem sobre compilação estática (AOT): informação que só existe em tempo de execução.

Memória: Stack, Heap e o Coletor de Lixo

A Ilusão da Destruição

public void processarPedido() {
    Pedido p1 = new Pedido("Notebook", 4500.0);
    enviarEmailConfirmacao(p1);
    // fim do metodo: p1 (Stack) morre.
    // o objeto Pedido (Heap) fica orfao, nao morto.
}

Fim de escopo mata o ponteiro (Stack), não o objeto (Heap).

GC Roots e Alcançabilidade

O GC rastreia o que está vivo, não o que é lixo.

Parte das GC Roots (variáveis locais ativas, atributos static) e navega pelos ponteiros. Inalcançável a partir de toda raiz \(\Rightarrow\) elegível para coleta.

Retenção Obsoleta: os “Zumbis”

private static Map<Integer, Pedido> cacheInfinito = new HashMap<>();
// static = GC Root eterna. Nunca fica inalcançável sozinho.

Java não tem memory leak clássico — tem objetos que a lógica já descartou, mas a JVM ainda alcança.

O GC Não Cuida de Recursos do S.O.

Arquivos, sockets, conexões de BD: liberação determinística, via try-with-resources — não dá para esperar o GC.

Um mapa static nunca fica vazio sozinho, mesmo que os objetos que ele guarda não sirvam mais para nada. Por que o Garbage Collector se recusa a limpá-lo?

Escreva sua resposta e compare com um colega antes de avançar (2 min).

Memória, GC e Recursos do Sistema

Dica

Julgue V ou F — a questão só conta se acertar os 4 itens:

  1. O fim do escopo de um método destrói automaticamente os objetos instanciados dentro dele, junto com a variável local.
  2. Um objeto se torna elegível para coleta quando nenhuma GC Root consegue alcançá-lo através do grafo de referências.
  3. Uma coleção static pode reter objetos indefinidamente, mesmo que a lógica de negócio já não precise mais deles.
  4. O Garbage Collector é a ferramenta adequada para fechar arquivos e conexões de rede.

Memória, GC e Recursos do Sistema — Resposta

Dica

  1. Falso — destrói só o ponteiro na Stack; o objeto continua na Heap até ficar inalcançável.
  2. Verdadeiro — é exatamente a definição de inalcançabilidade.
  3. Verdadeiro — é a retenção obsoleta: a coleção estática age como GC Root eterna.
  4. Falso — o GC só libera memória RAM; recursos do S.O. exigem try-with-resources (fechamento determinístico).

A Anatomia de uma Classe em Código: o Exemplo Produto

Construindo Produto: Nome e Contrato

/** Representa um item comercializavel no mercado. */
public class Produto {
    // ...
}

Construindo Produto: Estado e Construtor

private String nome;
private double preco;

public Produto(String nome, double preco) {
    this.nome = nome;
    setPreco(preco);  // usa o accessor para validar
}

Construindo Produto: Acessores e Interface Pública

public void setPreco(double p) {
    if (p >= 0) this.preco = p;
}

public void aplicarDesconto(double pct) {
    if (isDescontoAceitavel(pct)) {
        this.preco -= calcularAbatimento(pct);
    }
}

Construindo Produto: Ocultando a Implementação

private boolean isDescontoAceitavel(double p) {
    return p > 0 && p < 50;
}
private double calcularAbatimento(double p) {
    return this.preco * (p / 100);
}

Regra muda? Só o método private muda. A interface pública — e todo código que já depende dela — permanece intacta.

Modificadores de Acesso e a Palavra-chave this

public e private: os Guardiões da Fronteira

public class ContaBancaria {
    private double saldo;               // O SEGREDO
    public void depositar(double valor) { // A PROMESSA
        if (valor > 0) this.saldo += valor;
        else throw new IllegalArgumentException("Valor invalido!");
    }
}

private fora da classe não é aviso — é erro de compilação.

O Problema do Sombreamento

public Produto(String nome) {
    nome = nome; // atribui a variavel local a ela mesma!
}

Compilador prioriza o escopo mais interno (o parâmetro). O atributo continua null.

A Solução: this

public Produto(String nome) {
    this.nome = nome; // this.nome -> Heap; nome -> Stack
}

this não só desambigua nomes — garante que p1.metodo() altera p1, não p2, mesmo rodando o mesmo bytecode.

Primitivos vs. Referências: a Mecânica de Passagem de Parâmetros

Primitivos: Isolamento Total

Duas cópias isoladas. Alterar valor não afeta preco.

Referências: o Controle Remoto

Cópia do endereço, não do objeto. Os dois “controles remotos” abrem a mesma “porta” na Heap.

A Prova da Reatribuição

public void sabotarProduto(Produto prod) {
    prod.setPreco(999.0);                     // reflete fora!
    prod = new Produto("Geladeira", 3000.0);   // so troca a copia local
    // a variavel do chamador continua apontando para a TV
}

Passagem por valor da referência — nunca passagem por referência de verdade.

Se Java sempre passa por valor, como alterar prod.setPreco(999.0) dentro do método afeta o objeto original visto por quem chamou?

Escreva sua resposta e compare com um colega antes de avançar (2 min).

Passagem de Parâmetros

Dica

Julgue V ou F — a questão só conta se acertar os 4 itens:

  1. Em Java existe passagem por referência estrita para objetos, assim como em C++ com &.
  2. Ao passar um objeto para um método, o parâmetro recebe uma cópia do endereço de memória, não do objeto físico.
  3. Alterar o estado interno de um objeto por dentro de um método (ex.: prod.setPreco(999.0)) é visto por quem chamou o método.
  4. Reatribuir o parâmetro (prod = new Produto(...)) dentro do método altera a variável original de quem chamou.

Passagem de Parâmetros — Resposta

Dica

  1. Falso — Java só tem passagem por valor; para objetos, o valor copiado é o endereço.
  2. Verdadeiro — é a “cópia do controle remoto”, não da “TV”.
  3. Verdadeiro — as duas variáveis apontam para o mesmo objeto físico na Heap.
  4. Falso — a reatribuição só troca o endereço guardado na cópia local; a variável original nunca é afetada.

Conclusão

O que Aprendemos

  1. Procedural → OO: dados e comportamento unidos numa entidade
  2. Estado + Comportamento + Identidade, protegidos por encapsulamento
  3. JVM: bytecode portável, otimizado em tempo real pelo JIT
  4. Objetos vivem na Heap; variáveis guardam só o endereço

Próxima aula: o construtor como guardião de integridade — Fail-Fast e invariantes de estado.