Arrays são passados ​​por valor ou passados ​​por referência em Java?

Duplicar Possível:
O Java é “pass-by-reference”?

Arrays não são um tipo primitivo em Java, mas também não são objects , então são passados ​​por valor ou por referência? Depende do que o array contém, por exemplo, referências ou um tipo primitivo?

Sua pergunta é baseada em uma falsa premissa.

Arrays não são um tipo primitivo em Java, mas também não são objects … “

De fato, todas as matrizes em Java são objects 1 . Cada tipo de matriz Java tem java.lang.Object como seu supertipo e herda a implementação de todos os methods na API do Object .

Como todos os objects Java, as matrizes são passadas por valor … mas o valor é a referência à matriz.

Real passando por referência envolve passar o endereço de uma variável para que a variável possa ser atualizada. Isto NÃO é o que acontece quando você passa um array em Java.

Aqui estão alguns links que explicam a diferença entre “pass-by-reference” e “pass-by-value”:

Perguntas SO relacionadas:

  • Java é “pass-by-reference” ou “pass-by-value”?

Contexto histórico:

A frase “pass-by-reference” era originalmente “call-by-reference”, e era usada para distinguir a semântica de passagem de argumentos do FORTRAN (chamada por referência) daqueles do ALGOL-60 (call-by-value) e chamada por nome).

  • Em chamada por valor, a expressão de argumento é avaliada para um valor e esse valor é copiado para o método chamado.

  • Em chamada por referência, a expressão de argumento é parcialmente avaliada para um “lvalue” (ou seja, o endereço de uma variável ou elemento de matriz) que é passado para o método de chamada. O método de chamada pode então ler e atualizar diretamente a variável / elemento.

  • Em chamada por nome, a expressão de argumento real é passada para o método de chamada (!!), que pode avaliá-lo várias vezes (!!!). Isso era complicado de implementar e podia ser usado (abusado) para escrever código que era muito difícil de entender. Call-by-name só foi usado em Algol-60 (felizmente!).

ATUALIZAR

Na verdade, a chamada por nome do Algol-60 é semelhante à passagem de expressões lambda como parâmetros. O enrugamento é que essas expressões não exatamente-lambda (elas eram chamadas de “thunks” no nível de implementação) podem modificar indiretamente o estado das variables ​​que estão no escopo no procedimento / function de chamada. Isso é parte do que os torna tão difíceis de entender. (Veja a página da Wikipedia no dispositivo de Jensen, por exemplo).


1. Nada no Q & A vinculado ( Arrays em Java e como eles são armazenados na memory ) indica ou implica que arrays não são objects.

Everything in Java are passed-by value. . No caso de Matriz (que não é nada além de um Objeto), a referência de matriz é passada por valor. (Assim como uma referência de object é passada por valor).

Quando você passa uma matriz para outro método, na verdade, a referência a essa matriz é copiada.

  • Quaisquer alterações no conteúdo da matriz por meio dessa referência afetarão a matriz original.
  • Mas alterar a referência para apontar para uma nova matriz não alterará a referência existente no método original.

Veja este post ..

Java é “pass-by-reference” ou “pass-by-value”?

Veja este exemplo de trabalho: –

 public static void changeContent(int[] arr) { // If we change the content of arr. arr[0] = 10; // Will change the content of array in main() } public static void changeRef(int[] arr) { // If we change the reference arr = new int[2]; // Will not change the array in main() arr[0] = 15; } public static void main(String[] args) { int [] arr = new int[2]; arr[0] = 4; arr[1] = 5; changeContent(arr); System.out.println(arr[0]); // Will print 10.. changeRef(arr); System.out.println(arr[0]); // Will still print 10.. // Change the reference doesn't reflect change here.. } 

Matrizes são de fato objects, então uma referência é passada (a própria referência é passada por valor, confusa ainda?). Exemplo rápido:

 // assuming you allocated the list public void addItem(Integer[] list, int item) { list[1] = item; } 

Você verá as alterações na lista do código de chamada. No entanto, você não pode alterar a referência em si, já que ela é passada por valor:

 // assuming you allocated the list public void changeArray(Integer[] list) { list = null; } 

Se você passar uma lista não nula, ela não será nula no momento em que o método retornar.

Não está errado. Matrizes são objects especiais em Java. Portanto, é como passar outros objects para onde você passa o valor da referência, mas não a referência em si. Ou seja, alterar a referência de uma matriz na rotina chamada não será refletida na rotina de chamada.

Tudo em Java é passado por valor.

No caso da matriz, a referência é copiada em uma nova referência, mas lembre-se de que tudo em Java é passado por valor.

Dê uma olhada neste artigo interessante para mais informações …

A discussão definitiva das matrizes está em http://docs.oracle.com/javase/specs/jls/se5.0/html/arrays.html#27803 . Isso deixa claro que os arrays Java são objects. A class desses objects é definida em 10.8.

A seção 8.4.1 da especificação do idioma, http://docs.oracle.com/javase/specs/jls/se5.0/html/classs.html#40420 , descreve como os argumentos são transmitidos aos methods. Como a syntax Java é derivada de C e C ++, o comportamento é semelhante. Tipos primitivos são passados ​​por valor, como com C. Quando um object é passado, uma referência de object (ponteiro) é passada por valor, espelhando a syntax C de passar um ponteiro por valor. Veja 4.3.1, http://docs.oracle.com/javase/specs/jls/se5.0/html/typesValues.html#4.3 ,

Em termos práticos, isso significa que modificar o conteúdo de uma matriz dentro de um método é refletido no object de matriz no escopo de chamada, mas reatribuir um novo valor à referência dentro do método não tem efeito sobre a referência no escopo de chamada, que é exatamente o comportamento que você esperaria de um ponteiro para uma estrutura em C ou um object em C ++.

Pelo menos parte da confusão na terminologia decorre da história de linguagens de alto nível antes do uso comum de C. Em linguagens de alto nível populares anteriores, referenciar diretamente memory por endereço era algo a ser evitado na medida do possível, e foi considerado o trabalho da linguagem para fornecer uma camada de abstração. Isso tornou necessário que o idioma suporte explicitamente um mecanismo para retornar valores de sub-rotinas (não necessariamente funções). Este mecanismo é o que significa formalmente quando se refere a ‘passar por referência’.

Quando C foi introduzido, ele veio com uma noção simplificada de chamada de procedimento, em que todos os argumentos são apenas de input, e o único valor retornado ao chamador é um resultado de function. No entanto, o propósito de passar referências poderia ser alcançado através do uso explícito e amplo de pointers. Uma vez que serve ao mesmo propósito, a prática de passar um ponteiro como referência a um valor é muitas vezes coloquialmente referida como passagem por referência. Se a semântica de uma rotina exigir que um parâmetro seja passado por referência, a syntax de C requer que o programador passe explicitamente um ponteiro. Passar um ponteiro por valor é o padrão de design para implementar a passagem por semântica de referência em C.

Como muitas vezes parece que o único objective dos pointers brutos em C é criar bugs falhos, desenvolvimentos posteriores, especialmente Java, têm procurado retornar a meios mais seguros para passar parâmetros. No entanto, o domínio de C fez com que os desenvolvedores imitassem o estilo familiar de codificação C. O resultado são referências que são passadas de forma semelhante a pointers, mas são implementadas com mais proteções para torná-las mais seguras. Uma alternativa teria sido a rica syntax de uma linguagem como Ada, mas isso teria apresentado a aparência de uma curva de aprendizado indesejada e diminuiria a provável adoção de Java.

Em suma, o design da passagem de parâmetros para objects, incluindo arrays, em Java, é essencialmente para servir a intenção semântica de passar por referência, mas é imple- mentado com a syntax de passar uma referência por valor.

Tipo de truque realty … Mesmo referências são passadas por valor em Java, portanto, uma mudança para a própria referência sendo escopo no nível de function chamado. O compilador e / ou a JVM geralmente transformarão um tipo de valor em uma referência.