Arrays: passagem por valor e passagem por referência em métodos

7 respostas
Alberto.S

Então o próprio compilador faz com que um tipo primitivo seja passado por valor e um objeto por referência automaticamente, certo?

Mas então, como modificar o valor de um tipo primitivo em um objeto, através de um método?

No exemplo abaixo, o resultado do elemento array[3] é 8, tanto antes quanto depois de usado o método modifyElement() e mesmo mudando o método para retornar um inteiro com [color=blue]return[/color], nada acontece.

import javax.swing.JApplet;
import javax.swing.JTextArea;
import java.awt.Container;


public class ArrayFigura710 extends JApplet
{
    
    public void init()
    {

        JTextArea outputArea = new JTextArea();
        Container container = getContentPane();
        container.add( outputArea );

        int array[] =
        {
            1, 2, 3, 4, 5
        };

        String output = "Efeitos da passagem de um array por referência:\n"
                + "Os valores do array original são:\n";

        // acrescenta os elementos do array original ao String output
        for ( int counter = 0; counter < array.length; counter++ )
        {
            output += " " + array[counter];
        }

        modifyArray( array ); // array passado por referência

        output += "\n\nOs valores do array modificado são:\n";

        // acrescenta os elementos do array modificado ao String output
        for ( int counter = 0; counter < array.length; counter++ )
        {
            output += " " + array[counter];
        }

        output += "\n\nEfeitos da passagem por valor dos elementos do array:\n"
                + "a[3] antes de modificar os elementos: " + array[3];

        // tentativa de modificar array[3]
        modifyElement( array[3] );

        output += "\na[3] depois de modificar os elementos: " + array[3]
                + "\n(inalterado, como vc percebe)";
        outputArea.setText( output );

    } // fim do método init()

    // multiplica cada elemento de um array por 2

    public void modifyArray( int array2[] )
    {
        for ( int counter = 0; counter < array2.length; counter++ )
        {
            array2[counter] *= 2;
        }
    }

    // multiplica o argumento por 2

    public void modifyElement( int element )
    {
        element *= 2;
    }


} // fim da classe public

[size=18]Como fazer então?[/size]

7 Respostas

pmlm
array[3] = modifyElement( array[3] );
public int modifyElement( int element )
    {
        return element *= 2;
    }
Alberto.S

Entendi, faltou essa parte aqui: array[3] = modifyElement(array[3]);

Obrigado. :slight_smile:

aeciovc

eu esperava outras respostas:

1. array[3] = modifyElement( array[3] );

array[3] = modifyElement( array[3] );
view plaincopy to clipboardprint?

  1. public int modifyElement( int element )
  2. {
  3. return element *= 2;
    
  4. }

Entendi, faltou essa parte aqui: array[3] = modifyElement(array[3]);

Obrigado.

ai vc atribui ao array de fora o retorno do método.

quando falamos de passagem de valor e referência queremos dizer que o método que não retorna nada conseguirá mudar o elemento que foi passado como parâmetro tanto dentro como o de fora.

Exemplo em Pascal

procedure modify(var p:integer);
begin
   p := p + 10;
end;

então, a palavra var faria toda diferença na declaração do procedimento acima.

p := 1; modify(p); writeln(p);

pra mim isso que seria passagem de valor por referência.

alguém sabe algo no Java com tipos primitivos??

Eric_Yuzo

Passagem de parâmetro em java é por valor.

Os parâmetros dos métodos são variáveis locais que recebem uma cópia do valor passado por parâmetro. Quando passamos uma referência, o parâmetro recebe uma cópia dessa referência, já que as duas variáveis vão apontar para o mesmo objeto, existe a impressão que é uma atribuição por referência. Mas na verdade é uma cópia do valor que foi passado.

Como os primitivos seguram apenas o valor, é necessário atribuir o retorno do método à alguma variável.

Espero que tenha conseguido ser claro.

douglaskd

tem jeito não :frowning:

Alberto.S

Passagem de parâmetro em java é por valor.

Os parâmetros dos métodos são variáveis locais que recebem uma cópia do valor passado por parâmetro. Quando passamos uma referência, o parâmetro recebe uma cópia dessa referência, já que as duas variáveis vão apontar para o mesmo objeto, existe a impressão que é uma atribuição por referência. Mas na verdade é uma cópia do valor que foi passado.

Como os primitivos seguram apenas o valor, é necessário atribuir o retorno do método à alguma variável.

Espero que tenha conseguido ser claro.

De acordo com o livro do Deitel, Java - Como Programar 4ª edição, objetos são passados como referências para métodos, e arrays são objetos, por isso temos que inicializá-los com [color=blue]new[/color]. E é como vc disse mesmo, ele cria uma cópia de referência que então pode modificar o objeto diretamente. Porém, com tipos primitivos, no caso do método void que não retorna nada, a passagem é feita por valor, então o argumento (no caso do exemplo que coloquei acima) é multiplicado por 2 o resultado guardado na variável local element, então quando o método termina a variável local element é destruída. Portanto guando retorna o controle para init(), o valor de array[3] permanece inalterado.

De acordo com o livro isso é feito assim para evitar efeitos colaterais que costumam entravar o desenvolvimento de sistemas de software. Por enquanto eu ainda não percebo a utilidade desta diferença, com o tempo quem sabe… :slight_smile:

Eric_Yuzo

O que ocorre é que certas linguagens permitem passagem de parâmetro por valor e por referência, que são conceitos diferentes, independente se estamos falando de primitivos ou de referências a objetos. Quando se fala que um parâmetro é passado por referência, significa que a mesma referência passada é a que será trabalhada dentro do método. É exatamente isso que ocorre com a variável p no exemplo do aeciovc, por isso não é necessário atribuir o valor, já que variável cujo valor foi alterado no método é a mesma que foi passada.

Mas o java trata as passagens como passagem por valor, quer dizer que uma cópia do valor passado por parâmetro é atribuida. Como as referências são apenas uma forma de acessar um objeto, quando o parâmetro é uma referência existe a impressão de a passagem é por referência, pois o objeto será manipulado da mesma forma, mas na verdade são duas variáveis diferentes que apontam para o mesmo objeto. Um exemplo clichê para testar este conceito é a inversão de referências:
public class Teste {

	String nome;
	
	Teste(String nome) {
		this.nome = nome;
	}
	
	public static void inverterReferencia(Teste a, Teste b) {
		// Inverte as referências e imprime os nomes.
		Teste aux = a;
		a = b;
		b = aux;
		System.out.println(a.nome); // imprime o nome que antes estava em b
		System.out.println(b.nome); // imprime o nome que antes estava em a
	}
	
	public static void main(String[] args) {
		Teste a = new Teste("Referência A");
		Teste b = new Teste("Referência B");
		
		inverterReferencia(a, b); // Tenta inverter as referências de a e b pelo método.
		
		System.out.println(a.nome); // imprime o nome original de a, pois a inversão ocorreu apenas nas variáveis locais do método, porém as referências criadas aqui no main continuam com seus valores originais.
		System.out.println(b.nome); // imprime o nome original de b
		
		//Faz a inversão diretamente com as referências criadas no main.
		Teste aux = a;
		a = b;
		b = aux;
		
		//Agora sim as variáveis estão invertidas.
		System.out.println(a.nome);
		System.out.println(b.nome);
	}
}
Criado 11 de novembro de 2010
Ultima resposta 12 de nov. de 2010
Respostas 7
Participantes 5