Antes de ler este artigo, com base em sua própria experiência e compreensão, você pode primeiro pensar e escolher o método de passagem de parâmetros das funções Java:
A. É passado por valor?
B. Aprovado por referência?
C. Em parte por valor e em parte por referência?
A resposta correta ainda não será anunciada aqui. Deixaremos que você encontre a resposta sozinho através de um exemplo simples:
1. Primeiro defina um tipo de valor
classe estática pública Valor { private String valor = "valor"; public String getValue() { valor de retorno } public void setValue (String valor) { this.value = valor } }
2. Escreva duas funções newValue e ModifyValue: newValue apontará o parâmetro de entrada para um novo objeto e ModifyValue chamará o método setValue do parâmetro de entrada para modificar o valor do objeto.
public static void newValue(Valor valor) { valor = new Value(); " + value.getValue()); } public static void modificarValue(Valor valor) { value.setValue("novo valor"); System.out.println("Em modificarValue, HashCode = " + valor.hashCode() + ", valor = " + valor.getValue()); }
3. Código de teste simples
public static void main(String[] args) { Valor valor1 = new Value(); ); // Aponta valor1 para o novo objeto Value newValue(value1); System.out.println("Após modificação, HashCode = " + value1.hashCode() + ", value = " + value1.getValue() + "/n"); Value value2 = new Value() + ", value = " + value2.getValue()); // Use o método set do objeto para modificar o valor interno do objeto modificarValue(value2); System.out.println("Após modificar, HashCode = " + valor2.hashCode() + ", valor = " + valor2.getValue() }
4. Registro de resultados de execução:
Antes de modificar, HashCode = 12677476, valor = valor Em newValue, HashCode = 33263331, valor = novo valor Após modificar, HashCode = 12677476, valor = valor Antes de modificar, HashCode = 6413875, valor = valor Em modificarValue, HashCode = 6413875, valor = novo valor Após modificação, HashCode = 6413875, valor = novo valor
5. Análise de resultados:
O código acima é um padrão de programação muito comum: define | save | obtém um valor ou objeto na periferia, passa o objeto como parâmetro para um método e modifica as propriedades e o comportamento do objeto no método. No entanto, os métodos de modificação dos dois métodos newValue e modificarValue são diferentes. Depois que o método é chamado, o objeto parece muito diferente visto de fora! Como entender essa diferença? Vamos primeiro revisar os conceitos de passagem por valor e passagem por referência:
* Passar por valor significa que quando você passa um argumento para uma função, a função recebe uma cópia do valor original. Portanto, se a função modificar o parâmetro, apenas a cópia será alterada, enquanto o valor original permanecerá inalterado.
* Passar por referência significa que quando um argumento é passado para uma função, a função recebe o endereço de memória do valor original em vez de uma cópia do valor. Portanto, se a função modifica o parâmetro, o valor original do parâmetro (no código de chamada fora do bloco funcional) também muda.
Resposta correta: A - Funções Java passam parâmetros por valor!
Analise o registro:
* Na primeira seção da saída do log, o parâmetro value1 é alterado para apontar para um novo objeto dentro do método newValue, e o hashCode e o valor do novo objeto são gerados. No entanto, após sair do domínio do método newValue, nenhuma alteração. ocorre para valor1 no método principal. Isto está de acordo com a definição e características de passagem por valor; se for passado por referência, valor1 deve mudar após chamar o método newValue(Value value).
* A segunda saída de log mostra que value2 executa uma operação setValue dentro do método modificarValue. O hashCode permanece inalterado, mas o valor é modificado. Depois de sair do domínio do método modificarValue, value2 muda no método principal. Pessoas que usaram C++ podem facilmente entender esse fenômeno como: passar parâmetros de função por referência! Porque isso é muito semelhante à passagem por referência em C++! Mas é exatamente aqui que é mais provável que caia em mal-entendidos!
O princípio oculto por trás dos diferentes fenômenos dos dois logs é que a linguagem Java passa parâmetros por valor e objetos por referência; os objetos operados em Java são na verdade referências aos objetos operacionais, e os próprios objetos são armazenados no "heap"; e a “referência” do objeto é armazenada em um registrador ou “pilha”.
O pseudocódigo descreve a diferença entre o método newValue e o método modificarValue:
newValue{ Value_ref2 = value_ref1; // Passa a referência value_ref1 por valor e obtém uma cópia de value_ref1 value_obj2 = new Value(); // value_obj2 é criado e inicializado no "heap" value_ref2 -> value_obj2; valor_obj2 valor_ref2 - >valor_obj2.setValue(“xxx”); // valor_obj2; O valor é modificado printValueObj2(); // O que é impresso aqui é o valor de obj2}modifyValue{ Value_ref2 = value_ref1; // Passe a referência value_ref1 por valor e obtenha uma cópia de value_ref1 value_ref2 ->value_obj1.setValue("xxx "); // O valor de value_obj1 é modificado printValueObj1(); // O que é impresso aqui é o valor de obj1}
Isso está bastante claro! Quando value1_ref1 é passado para a função como um parâmetro, uma cópia de value1_ref2 é primeiro copiada para uso no domínio da função. Neste momento, ambas as referências apontam para o mesmo código value_obj na função newObject [value = new Value(); ] Na verdade, value1_ref1 aponta para um novo objeto value_obj2; as operações definidas depois disso são todas operações no novo objeto;
Passar parâmetros por valor
Ao chamar um método, você precisa fornecer parâmetros e deve fornecê-los na ordem especificada na lista de parâmetros.
Por exemplo, o método a seguir imprime uma mensagem n vezes seguidas:
public static void nPrintln(String mensagem, int n) { for (int i = 0; i < n; i++) System.out.println(message);}
Exemplo O exemplo a seguir demonstra o efeito da passagem por valor.
Este programa cria um método que troca duas variáveis.
public class TestPassByValue { public static void main(String[] args) { int num1 = 1; int num2 = 2; ; // Chama o método de troca swap(num1, num2); System.out.println("Após o método de troca, num1 é " + num1 + " e num2 é " + num2); } /** Método para trocar duas variáveis*/ public static void swap(int n1, int n2) { System.out.println("/tDentro do método de troca"); .out.println("/t/tAntes de trocar n1 é " + n1 + " n2 é " + n2); // Troca os valores de n1 e n2 int temp = n1 =; n2;
Os resultados de compilação e execução do exemplo acima são os seguintes:
Antes do método de troca, num1 é 1 e num2 é 2 Dentro do método de troca Antes de trocar n1 é 1 n2 é 2 Depois de trocar n1 é 2 n2 é 1Depois do método de troca, num1 é 1 e num2 é 2
Chame o método swap passando dois parâmetros. Curiosamente, os valores dos parâmetros reais não mudam depois que o método é chamado.