O Java é Passagem por Valor, Não Passagem por Referência

Introdução

Muitos programadores Java questionam se o Java é passagem por valor ou passagem por referência. Este artigo resume por que o Java é sempre passagem por valor.

Primeiro, o que significa passagem por valor e passagem por referência?

  • Passagem por valor: Os valores dos parâmetros do método são copiados para outra variável e então o objeto copiado é passado para o método. O método utiliza a cópia.
  • Passagem por referência: Um alias ou referência ao parâmetro real é passado para o método. O método acessa o parâmetro real.

Frequentemente, a confusão em torno desses termos é resultado do conceito de referência de objeto em Java. Tecnicamente, o Java é sempre passagem por valor, porque mesmo que uma variável possa conter uma referência a um objeto, essa referência de objeto é um valor que representa a localização do objeto na memória. As referências de objeto são, portanto, passadas por valor.

Ambos os tipos de dados por referência e os tipos de dados primitivos são passados por valor. Saiba mais sobre tipos de dados em Java.

Além de entender os tipos de dados, também é importante compreender alocação de memória em Java, pois os tipos de dados por referência e os tipos de dados primitivos são armazenados de maneira diferente.

Demonstrando passagem por valor

O exemplo a seguir demonstra como os valores são passados em Java.

O programa de exemplo utiliza a seguinte classe:

public class Balloon {

	private String color;

	public Balloon() {}
	
	public Balloon(String c) {
		this.color = c;
	}
	
	public String getColor() {
		return color;
	}

	public void setColor(String color) {
		this.color = color;
	}
}

O programa de exemplo a seguir utiliza um método genérico, swap(), que troca duas variáveis. Outro método, changeValue(), tenta alterar os valores das variáveis.

public class Test {

	public static void main(String[] args) {

		Balloon red = new Balloon("Red"); // referência de memória = 50
		Balloon blue = new Balloon("Blue"); // referência de memória = 100
		
		swap(red, blue);
		System.out.println("After the swap method executes:");
		System.out.println("`red` color value = " + red.getColor());
		System.out.println("`blue` color value = " + blue.getColor());
		
		changeValue(blue);
		System.out.println("After the changeValue method executes:");
		System.out.println("`blue` color value = " + blue.getColor());
		
	}

	// Método genérico de troca
	public static void swap(Object o1, Object o2){
		Object temp = o1;
		o1 = o2;
		o2 = temp;
	}

	private static void changeValue(Balloon balloon) { // balão = 100
		balloon.setColor("Red"); // balão = 100
		balloon = new Balloon("Green"); // balão = 200
		balloon.setColor("Blue"); // balão = 200
	}

}

Ao executar o programa de exemplo, você obtém a seguinte saída:

Output
After the swap method executes: 'red' color value = Red 'blue' color value = Blue After the changeValue method executes: 'blue' color value = Red

A saída mostra que o método swap() não trocou os valores de cor dos objetos originais. Isso ajuda a mostrar que Java é passado por valor, já que o método swap() atua apenas em cópias dos valores de referência de objeto originais.

Este teste do método swap() pode ser usado com qualquer linguagem de programação para verificar se é passado por valor ou por referência.

O Método de Exemplo swap() Explicado

Ao utilizar o operador new para criar uma instância de uma classe, o objeto é criado e a variável contém a localização na memória onde o objeto é salvo.

Balloon red = new Balloon("Red");
Balloon blue = new Balloon("Blue");

Aqui está uma explicação passo a passo do que acontece quando o método swap() é executado:

  • Suponha que red esteja apontando para a localização de memória 50 e blue esteja apontando para a localização de memória 100, e que estas sejam as localizações de memória de ambos os objetos Balloon.

  • Quando a classe chama o método swap() com as variáveis red e blue como argumentos, duas novas variáveis de objeto, o1 e o2, são criadas. o1 e o2 também apontam para as localizações de memória 50 e 100, respectivamente.

  • O trecho de código a seguir explica o que acontece dentro do método swap():

    public static void swap(Object o1, Object o2) { // o1 = 50, o2 = 100
    	Object temp = o1; // atribui o valor de referência do objeto o1 a temp: temp = 50, o1 = 50, o2 = 100
    	o1 = o2; // atribui o valor de referência do objeto o2 a o1: temp = 50, o1 = 100, o2 = 100
    	o2 = temp; // atribui o valor de referência de temp a o2: temp = 50, o1 = 100, o2 = 50
    } // método terminado
    
  • Os valores de o1 e o2 são trocados, mas como os valores são cópias das localizações de memória red e blue, não há alteração nos valores das cores red e blue.

Uma vez que as variáveis contêm a referência aos objetos, é um erro comum assumir que você está passando a referência e o Java é passado por referência. No entanto, você está passando um valor que é uma cópia da referência e, portanto, é passado por valor.

O Método de Exemplo changeValue() Explicado

O próximo método no programa de exemplo muda o valor da cor do objeto referenciado pela variável blue:

private static void changeValue(Balloon balloon) { // balão = 100
	balloon.setColor("Red"); // balão = 100
	balloon = new Balloon("Green"); // balão = 200
	balloon.setColor("Blue"); // balão = 200
}

Aqui está uma explicação passo a passo do que acontece dentro do método changeValue():

  • A classe chama o método changeValue() na variável blue que referencia a localização de memória 100. A primeira linha cria uma referência que também aponta para a localização de memória 100. O valor da cor do objeto na localização de memória 100 é alterado para "Vermelho".

  • A segunda linha cria um novo objeto (com valor de cor "Verde"). O novo objeto está na localização de memória 200. Quaisquer métodos adicionais executados na variável balão atuam sobre o objeto na localização de memória 200, e não afetam o objeto na localização de memória 100. A nova variável balão sobrescreve a referência criada na linha 1 e a referência de balão da linha 1 não está mais acessível dentro deste método.

  • A terceira linha altera o valor de cor do novo objeto Balloon na localização de memória 200 para "Blue", mas não afeta o objeto original referenciado por blue na localização de memória 100. Isso explica por que a última linha da saída do programa de exemplo imprime blue color value = Red, refletindo a alteração da linha 1.

Conclusão

Neste artigo, você aprendeu por que o Java é passado por valor. Continue sua aprendizagem com mais tutoriais de Java.

Source:
https://www.digitalocean.com/community/tutorials/java-is-pass-by-value-and-not-pass-by-reference