passando um array String como argumento

Um array String pode ser declarado e inicializado da seguinte maneira:

String[] str = {"A", "B"}; 

mas para um método que aceita um array String como argumento, por que o mesmo não pode ser usado lá?

Por exemplo: se no código abaixo, eu substituo a chamada para show () de show(str); para show({"A" "B"}); , mostra um erro completo. Por quê?

 public class StringArray { /** * @param args */ public static void main(String[] args) { // TODO Auto-generated method stub String[] str = {"A", "B"}; show(str); } static void show(String[] s) { System.out.println(s[0] + s[1]); } } 

Os erros do compilador mostrados são:

 StringArray.java:9: illegal start of expression show({"A", "B"}); ^ StringArray.java:9: ';' expected show({"A", "B"}); ^ StringArray.java:9: illegal start of expression show({"A", "B"}); ^ StringArray.java:9: ';' expected show({"A", "B"}); ^ StringArray.java:9: illegal start of type show({"A", "B"}); ^ StringArray.java:11: class, interface, or enum expected static void show(String[] s) { ^ StringArray.java:13: class, interface, or enum expected } ^ 7 errors 

Também usando show(new String[] {"A", "B"}); é permitido. Como o new String[]{"A", "B"} diferente de {"A", "B"} ao passá-los como argumentos de método? Thanx antecipadamente!

A syntax {"A", "B"} (sem new String[] na frente dela) só pode ser usada como uma expressão inicializadora de array. Em todos os outros contextos (incluindo chamadas de método), você precisa usar o new operador.

Veja o Java Tutorial on Arrays para mais informações.

String[] str = {"A", "B"}; é uma versão reduzida de String[] str = new String[]{"A", "B"}; , Compiler não sabe sobre plain {"A", "B"} como um array de strings, a menos que você mencione explicitamente.

Quando você passa {“A”, “B”}, não há nenhum object fazendo referência a ele porque esse array ainda não está criado na memory e essa referência é necessária para ser passada. Mas podemos passar uma string como “A” diretamente [sem uma referência] para um método que aceita String, porque String é o object especial do java para o qual o conjunto String é mantido. e esse não é o caso com array que é como um simples object java.

Resposta curta

Tem tudo a ver com gerenciamento de memory.


Resposta longa

Fundo :

Há outra questão sobre passar arrays como argumentos (marcados como duplicados), que está perguntando sobre o mesmo comportamento, mas está interessada em um “porquê” mais profundo.

Outras respostas explicaram corretamente a diferença entre

A)

 new String[]{"A", "B"} 

e

B)

 {"A", "B"} 

ao passá-los como argumentos do método.

A) constrói uma instância de um array no heap e a expressão resulta em uma referência à instância.

B) é a syntax para definir uma matriz, mas essa syntax só é válida durante a boot de uma variável de matriz local. Essa syntax não é uma expressão que pode ser avaliada por si mesma, ela espera que exista uma matriz já instanciada, mas não inicializada, em que esse bloco é usado como inicializador.

A culpa é do Java

Tudo isso já foi mencionado, então o que eu gostaria de responder é o porquê da decisão de design de linguagem que coloca esse comportamento em prática.

Um dos princípios básicos do Java é que ele gerencia a memory para realmente minimizar os enormes problemas que surgem quando cada programador tem que entender todos os detalhes, todos os casos de borda com gerenciamento de memory dinâmica. Então, quando eles projetaram o sistema de tipos da linguagem, eles gostariam que cada variável fosse um tipo de referência, mas para eficiência eles permitiam alguns tipos básicos que podem ser passados ​​por valor como um argumento para um método, onde o resultado é um simples clone de o conteúdo da variável, estes são chamados tipos primitivos, int, char, etc. Todos os outros tipos requerem uma referência ao heap, o que permite uma boa eficiência na passagem de parâmetros, estes são chamados de tipos de referência. Tipos de referência, como o nome indica, são na verdade uma referência à memory que foi alocada normalmente na pilha, mas pode ser memory na pilha.

Inicializadores de Array

Ok, é isso para o Java Primer, mas por que isso é importante? É porque quando você tenta passar uma matriz como no argumento, mas usa a syntax literal, a linguagem espera um tipo de referência, mas a construção do inicializador da matriz não é resolvida para uma referência.

Agora, a próxima pergunta poderia ser se teria sido possível para o compilador tomar a syntax do inicializador e transformá-la em uma instância apropriadamente alocada de uma matriz. Essa seria uma pergunta justa. A resposta volta para a syntax que usa a cláusula inicializadora:

String [] str = {“A”, “B”}

Se você tem apenas a expressão do lado direito do sinal de igual, como você sabe que tipo de array deve ser construído? A resposta simples é que você não. Se pegássemos esse mesmo inicializador e o usássemos assim

 Circle[] cir = {"A", "B"} 

fica mais claro porque é esse o caso. Primeiro você pode notar que a palavra-chave “novo” parece estar faltando. Não está faltando, mas está implicitamente sendo incluído pelo compilador. Isso ocorre porque a syntax do inicializador é uma forma resumida do código a seguir

 Circle[2] cir = new Circle[](); cir[0] = new Circle("A"); cir[1] = new Circle("B"); 

O compilador usa o construtor para a variável array para instanciar cada elemento da matriz com base na lista fornecida. Então, quando você tenta passar

 {"A", "B"} 

o compilador não tem nenhuma informação sobre que tipo de matriz deve ser construído nem sabe como construir os elementos individuais do array, daí a necessidade de usar o formulário que aloca memory explicitamente.

Para o estudante de idiomas

Essa separação entre o tipo de referência e o tipo de cada elemento da matriz também é o que permite que o tipo de matriz seja um tipo pai dos elementos, como

 Circle[2] shapes = new Circle[](); shapes[0] = new Circle(); // parent shapes[1] = new Ellipse(); // child of Circle 

e o uso de Java de uma class pai, Object para todas as classs permite matrizes com objects completamente não relacionados

 Object[2] myThings = new Object[](); myThings[0] = new Car(); myThings[1] = new Guitar(); // unrelated object 

Desde String[] str = {"A", "B"}; define que é uma matriz de strings, {"A", "B"} nenhum lugar diz que esta é uma matriz de string como uma matriz de objects poderia ser definida assim também, assim compilador não sabe que tipo de array você é referindo-se a 🙂

Funciona se você fizer assim

 public class StringArray { /** * @param args */ public static void main(String[] args) { show(new String[]{"A", "B"}); } static void show(String[] s) { System.out.println(s[0] + s[1]); } } 

porque você está realmente criando um novo “object” de matriz. O outro jeito, {“A”, “B”} não significa nada. {“A”, “B”} não é um object de array, então não funcionará. A primeira maneira funciona porque você está realmente especificando que o que está sendo passado para a function é um object de matriz.

show ({“A” “B”}); esta expressão não está passando o object da matriz. Passando o object array Você tem que primeiro declarar e inicializar o object array, passando a referência ao método.

String [] str = {“A”, “B”}; show (str);

OU

String [] str = {“A”, “B”}; show (new String [] {“A”, “B”});

No exemplo acima, a assinatura do método show () guia o compilador que está esperando uma referência String no momento da chamada, assim podemos passar apenas uma variável de referência do tipo String ao chamar o método show (). Por outro lado {“A”, “B”} é apenas uma expressão e não uma referência, por isso está dando um erro de compilation como “Início Ilegal da Expressão”.