Fundamentos de Java: Sintaxe Avançada e Introdução à Orientação a Objetos

  1. Comportamento de Métodos e Passagem de Parâmetros
public class DemoParametros {
    static void tentarModificarTexto(String param) {
        param = "novo_valor";
    }
    
    static void alterarElementos(String[] lista) {
        for (int j = 0; j < lista.length; j++) {
            lista[j] = lista[j].concat("_" + j);
        }
    }
    
    public static void main(String[] args) {
        String txt = "original";
        tentarModificarTexto(txt);
        System.out.println(txt);
        
        alterarElementos(args);
        System.out.println(Arrays.toString(args));
    }
}

Análise do comportamento:

  • O método tentarModificarTexto recebe uma String como parâmetro e tenta reatribuir seu valor, porém essa alteração não afeta a variável original na chamada. Isso ocorre porque em Java a passagem de parâmetros é sempre por valor — para tipos referenciais, é passada uma cópia da referência. Ao reatribuir param, apenas a cópia local da referência passa a apontar para outro objeto, sem impactar a referência original.
  • O método alterarElementos percrore o array recebido e concatena o índice a cada elemento. Como a referência aponta para o mesmo objeto array em memória, as modificações nos elementos afetam o array original.
  • Os valores de args vêm dos argumentos passados na linha de comando ao executar o programa: java DemoParametros valor1 valor2.
  1. Semântica de Referências em Arrays
int[] dados = new int[3];
dados[0] = 1;
dados[1] = 1;
int[] copiaRef = dados;
dados[0] = 2;
System.out.println(Arrays.toString(dados));
System.out.println(Arrays.toString(copiaRef));

A saída será [2, 1, 0] para ambas as linhas. A atribuição int[] copiaRef = dados não cria um novo array, mas sim uma nova referência para o mesmo objeto em memória. Logo, qualquer modificação feita através de uma variável é visível pela outra.

String[] nomes = {"alfa", "beta", "gama"};
nomes[1] = "delta";
System.out.println(Arrays.toString(nomes));

Embora String seja imutável em Java, o código acima funciona porque não está modificando o conteúdo de uma String, e sim trocando a referência armazenada na posição 1 do array — de "beta" para "delta". A imutabilidade da String permanece intacta.

  1. Arrays Multidimensionais Irregulares

Em Java, ao declarar int[5][], apenas a primeira dimensão é fixada com tamanho 5. A segunda dimensão pode ter comprimentos distintos para cada linha:

public class MatrizIrregular {
    public static void main(String[] args) {
        int[][] matriz = new int[5][];
        matriz[0] = new int[]{1, 2, 3};
        matriz[1] = new int[]{4, 5};
        matriz[2] = new int[]{6, 7, 8, 9};
        matriz[3] = new int[]{10};
        matriz[4] = new int[]{11, 12, 13, 14, 15};
        
        for (int[] linha : matriz) {
            for (int valor : linha) {
                System.out.print(valor + " ");
            }
            System.out.println();
        }
    }
}

Este padrão é conhecido como array jagged (irregular), onde cada sub-array pode ter um tamanho diferente, oferecendo flexibilidade na representação de dados não uniformes.

  1. Classes, Objetos e Encapsulamento

Classe vs. Objeto: Uma classe é uma abstração que define a estrutura e o comportamento de um conjunto de entidades. Um objeto é uma instância concreta dessa abstração, ocupando espaço em memória durante a execução.

Math: A classe Math não pode ser instanciada — seu construtor é privado. Todos os seus membros são estáticos, acessados diretamente via nome da classe.

String e encapsulamento: A classe String mantém seu array interno de caracteres como private final char value[], garantindo imutabilidade. Se esse campo fosse público, qualquer código poderia alterar o conteúdo, quebrando o contrato de imutabilidade. Já métodos como length(), substring() e charAt() são públicos, permitindo que usuários consultem e manipulem Strings de forma controlada sem comprometer sua integridade interna.

  1. Padrão Setter/Getter e Encapsulamento

Embora atributos public ofereçam acesso direto, o padrão de accessors (getters/setters) é amplamente adotado por várias razões:

  • Validação de dados: Um setter pode rejeitar valores inválidos antes de atribuí-los, como verificar se uma idade não é negativa.
  • Controle de acesso: Pode-se expor apenas o getter, criando propriedades somente leitura, ou apenas o setter para propreidades somente escrita.
  • Flexibilidade de implementação: Se a representação interna de um atributo mudar, apenas os accessors precisam ser ajustadso, sem impactar quem consome a classe.
  • Lógica adicional: Pode-se adicionar notificações, logs ou cálculos derivados dentro dos accessors.

O encapsulamento é o princípio de ocultar detalhes internos e expor apenas interfaces controladas. Os accessors são a materialização prática desse princípio.

  1. Inicialização de Atributos em Objetos

Os atributos de um objeto podem ser inicializados em diferentes momentos:

  • Na declaração: private int contador = 0;
  • No construtor: atribuição dentro da lógica de inicialização
  • Em blocos de inicialização: blocos { } executados antes do construtor
  • Após a instanciação: via setters ou métodos de configuração
public class ExemploInicializacao {
    private int valor = 10;          // na declaração
    private String nome;
    
    {
        nome = "padrão";             // bloco de inicialização
    }
    
    public ExemploInicializacao(String nome) {
        this.nome = nome;            // no construtor
    }
    
    public void configurarValor(int v) {
        this.valor = v;              // pós-instanciação
    }
}

  1. Escopos de Acesso e Encapsulamento

Os modificadores de acesso em Java definem o escopo de visibilidade de membros, sendo fundamentais para o encapsulamento:

  • private: Restrito à própria classe. Esconde a implementação interna, protegendo dados de manipulação externa direta.
  • protected: Acessível pela classe, suas subclasses e classes do mesmo pacote. Oferece um equilíbrio entre reutilização em hierarquias de herança e proteção contra acesso irrestrito.
  • public: Sem restrições de acesso. Deve ser reservado para a interface pública da classe — métodos que representam o contrato de uso.
  • Default (sem modificador): Acessível apenas dentro do mesmo pacote.

A combinação estratégica desses modificadores permite construir APIs robustas: dados internos ficam privados, métodos utilitários internos são protegidos, e apenas operações relevantes são expostas publicamente.

Tags: java Sintaxe Java OOP encapsulamento arrays multidimensionais

Publicado em 8-8 00:03