Até J2SE1.4, era impossível definir métodos com parâmetros reais variáveis nos programas Java - porque o Java exige que o número e os tipos de parâmetros reais (argumentos) e parâmetros formais sejam correspondidos um por um, e o número de parâmetros formais é fixo ao definir o método. Embora o mesmo método possa ser fornecido com um número diferente de parâmetros formais através do mecanismo de sobrecarga, isso ainda não pode alcançar o objetivo de permitir que a quantidade real de parâmetros mude arbitrariamente.
No entanto, a semântica de alguns métodos exige que eles sejam capazes de aceitar o número variável de parâmetros reais - por exemplo, o famoso método principal precisa ser capaz de aceitar todos os parâmetros da linha de comando como parâmetros reais, e o número de parâmetros da linha de comando não pode ser determinado antecipadamente.
Para esse problema, tradicionalmente, a prática de "usar uma matriz para envolver os parâmetros reais a ser passada" é geralmente usada para lidar com isso.
1. Enrole os parâmetros em uma matriz
A prática de "envolver parâmetros reais com matrizes" pode ser dividida em três etapas: primeiro, defina um parâmetro do tipo Array para esse método; Então, quando chamado, gerar uma matriz contendo todos os parâmetros reais a serem passados; Finalmente, passe esta matriz como um parâmetro real.
Essa abordagem pode efetivamente alcançar o objetivo de "fazer o método aceitar parâmetros variáveis", mas a forma quando a chamada não é simples o suficiente.
O mecanismo VARARGS é fornecido no J2SE1.5, permitindo uma definição direta de parâmetros formais que podem corresponder a vários parâmetros reais. Assim, um número variável de parâmetros reais pode ser passado de maneira mais simples.
O significado de varargs
De um modo geral, "varargs" significa "variatleblenumberofargments". Às vezes, é simplesmente chamado de "órgãos variáveis", mas como esse termo não indica o que é variável, o significado é um pouco vago.
2. Defina um método com parâmetros reais variáveis
Basta adicionar três consecutivos "." (ou seja, "...", uma elipse na frase em inglês) entre o "tipo" e o "nome do parâmetro" de um parâmetro formal e pode corresponder a um parâmetro real incerto. Um método com esses parâmetros formais é um método com parâmetros reais variáveis.
Listagem 1: Um método com parâmetros reais variáveis
private static int sumup (int ... valores) {}Observe que apenas o último parâmetro formal pode ser definido como "pode corresponder a um parâmetro real incerto". Portanto, pode haver apenas um parâmetro formal em um método. Além disso, se esse método tiver outros parâmetros formais, coloque -os na posição frontal.
O compilador converterá o último parâmetro formal em um parâmetro formal da matriz em segredo e fará uma marca no arquivo de classe compilada para indicar que este é um método com parâmetros reais variáveis.
Listagem 2: forma secreta de um método com parâmetros reais variáveis
private static int sumup (int [] valores) {}Devido a tais transformações, é impossível definir um método para esta classe que seja consistente com a assinatura do método convertido.
Listagem 3: Combinações que causarão erros de compilação
private static int sumup (int ... valores) {} private static int sumup (int [] valores) {}3. Ligue para um método com número variável de parâmetros reais
Desde que os parâmetros reais a serem passados sejam escritos um por um para a posição correspondente, um método com número variável de parâmetros reais pode ser chamado. Não são necessárias outras etapas.
Listagem 4: Vários parâmetros podem ser passados
sumUp(1,3,5,7);
Indiretamente, o compilador converterá esse processo de chamada na forma de "Array envolto em parâmetros reais":
Listagem 5: Criação de matriz secretamente aparecendo
sumUp(newint[]{1,2,3,4});
Além disso, o "incerto" mencionado aqui também inclui zero, portanto, essa chamada é razoável:
Listagem 6: você também pode passar zero parâmetros reais
sumUp();
O efeito desse método de chamada secretamente convertido pelo compilador é equivalente a isso:
Listagem 7: Zero argumentos reais correspondem a matrizes vazias
sumUp(newint[]{});
Observe que o passado é passado neste momento, não nulo. Isso permite que um formulário unificado seja tratado sem precisar detectar a qual situação ela pertence.
4. Processe os parâmetros reais com números variáveis
O método de processamento de parâmetros reais com números variáveis é basicamente o mesmo que o método de processamento de parâmetros reais da matriz. Todos os parâmetros reais são salvos em uma matriz com o mesmo nome que os parâmetros formais. De acordo com as necessidades reais, depois de ler os elementos nesta matriz, cozinhar ou cozinhar, você pode fazer o que quiser.
Listagem 8: Processando os argumentos recebidos
private estático int sumup (int ... valores) {int sum = 0; for (int i = 0; i <valores.Length; i ++) {sum+= valores [i]; } retornar a soma;}5. Encaminhar o número variável de parâmetros
Às vezes, depois de aceitar um conjunto de parâmetros de número variável, eles precisam ser passados para outro método de número variável. Como o número de parâmetros reais recebidos durante a codificação não pode ser conhecido, a prática de "escrevê -los um por um no local onde eles devem aparecer" não é viável. No entanto, isso não significa que essa seja uma tarefa inacessível, porque há outra maneira de chamar um método com parâmetros reais variáveis.
Aos olhos do compilador J2SE1.5, o método com parâmetros reais variáveis é um caso especial do método com uma matriz de parâmetros formais no final. Portanto, coloque todo o conjunto de parâmetros reais a ser transmitido para uma matriz com antecedência e depois passe essa matriz como o último parâmetro real para um método com um número variável de parâmetros reais, que não causarão erros. Com esse recurso, o encaminhamento pode ser concluído sem problemas.
Listagem 9: encaminhando os parâmetros reais recebidos
classe pública printfsample {public static void main (string [] args) {printout ("pi:%f e:%f/n", math.pi, math.e); } impressão estática privada estática (formato de string, objeto ... args) {System.out.printf (formato, args); }}6. É uma matriz? Não é uma matriz?
Embora nos bastidores, o compilador converterá parâmetros formais que podem corresponder aos parâmetros reais incertos em parâmetros formais da matriz; e também pode usar uma matriz para envolver os parâmetros reais e depois passá -los para um método com número variável de parâmetros reais; No entanto, isso não significa que não há diferença entre "os parâmetros formais que podem corresponder aos parâmetros reais incertos" e "parâmetros formais de matriz".
Uma diferença óbvia é que, se você chamar um método cujo último parâmetro formal é um parâmetro formal da matriz na forma de um método com número variável de parâmetros reais, ele só levará a um erro de compilação "não pode ser o que não pode ser
Listagem 10: Um erro de compilação para "Não éBEAPLIED TO"
private estático void testOverloading (int [] i) {System.out.println ("a");} public static void main (string [] args) {testOverloading (1, 2, 3); // Erro de compilação}Por esse motivo, esse método conciso de chamada não pode ser adotado diretamente ao chamar métodos que suportam apenas os parâmetros reais de embalagem com matrizes (por exemplo, aqueles que sobraram de designs de biblioteca de terceiros para J2SE1.5).
Se você não puder modificar a classe original e adicionar uma versão variável do número de parâmetros ao método a ser chamado, e deseja adotar esse método de chamada conciso, poderá usar os métodos de reconstrução de "Introduce ForeignMethod" e "introducelocalextension" para aproximar o objetivo.
7. Quando um número variável de argumentos encontra um genérico
Um novo mecanismo "genérico" foi adicionado ao J2SE1.5, que pode parametrizar um tipo sob certas condições. Por exemplo, ao escrever uma classe, o tipo de parâmetros formais de um método pode ser representado por um identificador (como t). Quanto ao tipo esse identificador representa, ele é especificado ao gerar uma instância dessa classe. Esse mecanismo pode ser usado para fornecer uma reutilização mais completa do código e verificação mais rigorosa do tipo de tempo de compilação.
No entanto, o mecanismo genérico não pode ser usado com números variáveis de parâmetros formais. Se um tipo de parâmetro formal que corresponde a um argumento incerto for representado por um identificador, o compilador fornecerá um erro de "genericaRraycreation".
Listagem 11: Quando varargs atingem genéricos
private estático void testvarargs (t ... args) {// Erro de compilação}A razão para esse fenômeno é uma restrição inerente ao mecanismo genérico no J2SE1.5 - Uma instância desse tipo não pode ser criada com o tipo representado por um identificador. Antes que a versão Java suportasse sem essa restrição aparecer, basicamente não havia uma boa solução para esse problema.
No entanto, a prática tradicional de "envoltório com matrizes" não está sujeita a essa restrição.
Listagem 12: Solução alternável compilável
private estático void testvarargs (t [] args) {for (int i = 0; i <args.length; i ++) {System.out.println (args [i]); }}8. Questões de seleção na sobrecarga
O Java suporta mecanismos de "sobrecarga", permitindo que muitos métodos diferentes da mesma classe tenham apenas listas de parâmetros formais. Em seguida, o compilador seleciona qual método executar com base nos parâmetros reais no momento da chamada.
As escolhas tradicionais são basicamente baseadas no princípio de "pessoas especiais são preferidas". A especialidade de um método depende do número de condições que precisam ser atendidas para que ele seja executado sem problemas. Quanto mais condições você precisa, mais especial é.
Após a introdução do mecanismo de varargs, esse princípio ainda se aplica, mas os problemas a serem considerados são enriquecidos - tradicionalmente, entre as várias versões de um método sobrecarregado, apenas aqueles cujos parâmetros morfológicos e parâmetros reais são exatamente os mesmos são elegíveis para consideração posterior. No entanto, após a introdução do mecanismo de varargs, é possível corresponder às duas versões e não há diferença em outros aspectos, apenas um parâmetro real tem um número fixo e o outro parâmetro real possui um número de variável.
Nesse caso, a regra de determinação usada é que "a versão com número fixo de parâmetros reais tem precedência sobre a versão com o número variável de parâmetros reais".
Listagem 13: Versões com número fixo de parâmetros reais são preferidas
Se, na visão do compilador, vários métodos tiverem a mesma prioridade, ele ficará preso em um estado em que não puder fazer uma escolha sobre qual método chamar. Nesse caso, ele gerará um erro de compilação de "Referenceto chamado Nome do Método Isambiguio" e esperará pacientemente algumas modificações para evitar a chegada do novo código -fonte que é confuso.
Após a introdução do mecanismo VARARGS, essa situação que pode levar à confusão aumentou um pouco mais. Por exemplo, pode haver duas versões que podem corresponder, o que é exatamente o mesmo em outros aspectos, e ocorrem ambos os conflitos com números variáveis de parâmetros reais.
public classe sobrecarregando amamplea {public static void main (string [] args) {testOverloading (1); // Imprima o ATESToverLoading (1, 2); // Imprima BTESToverLoading (1, 2, 3); // imprima c} private static testoLoading (Int i) {System.out.Int.Intlnnnnnnnnnnnen (}) (}); j) {System.out.println ("b");} private estático void testOverloading (int i, int ... mais) {System.out.println ("c");}}Se, na visão do compilador, vários métodos tiverem a mesma prioridade, ele ficará preso em um estado em que não puder fazer uma escolha sobre qual método chamar. Nesse caso, ele gerará um erro de compilação de "Referenceto chamado Nome do Método Isambiguio" e esperará pacientemente algumas modificações para evitar a chegada do novo código -fonte que é confuso.
Após a introdução do mecanismo VARARGS, essa situação que pode levar à confusão aumentou um pouco mais. Por exemplo, pode haver duas versões que podem corresponder, o que é exatamente o mesmo em outros aspectos, e ocorrem ambos os conflitos com números variáveis de parâmetros reais.
Listagem 14: Não importa o quê, é difícil para o compilador ser
classe pública sobrecarregando a amostra {public static void main (string [] args) {testOverloading (1, 2, 3); // Erro de compilação} private estático void testoverging (objeto ... args) {}}Além disso, como existe o mecanismo "AutoBoxing/Auto-UNBoxing" no J2SE1.5, é possível que ambas as versões possam corresponder, e o número de parâmetros reais é variável e os outros aspectos são exatamente os mesmos. É apenas que um parâmetro real aceitável é o tipo básico, enquanto o outro parâmetro real aceitável é o conflito entre a classe do pacote.
Listagem 15: Novas questões do AutoBoxing/Auto-UNBoxing
classe pública sobrecarregando o samplec {public static void main (string [] args) {/* Erro de compilação*/testOverloading (1, 2);/* ou erro de compilação*/testOverloading (new integer (1), novo inteiro (2));}}} estatal void testverloading (Int ... args) {} {}}9. Resumo
Comparado com o método "embrulhado em matrizes", o método real com parâmetros reais variáveis é mais simples e tem significados mais claros ao ligar. No entanto, esse mecanismo também tem suas próprias limitações e não é uma solução perfeita.
O exposto acima é toda a explicação detalhada do código do parâmetro de comprimento variável no Java, espero que seja útil para todos. Amigos interessados podem continuar se referindo a este site:
Explicação detalhada de parâmetros implícitos e instâncias de parâmetros em Java
Implementação de programação Java de Código de classificação e otimização rápido explicação detalhada
Java Criptografia Decripção e Assinatura Digital Exemplo de Código Completo
Se houver alguma falha, deixe uma mensagem para apontá -la. Obrigado amigos pelo seu apoio para este site!