Hasta J2SE1.4, ha sido imposible definir métodos con parámetros reales variables en los programas de Java, porque Java requiere que el número y los tipos de parámetros reales (argumentos) y los parámetros formales se coincidan con uno por uno, y el número de parámetros formales se solucione al definir el método. Aunque se puede proporcionar el mismo método con un número diferente de parámetros formales a través del mecanismo de sobrecarga, esto aún no puede lograr el propósito de permitir que la cantidad de parámetros reales cambie arbitrariamente.
Sin embargo, la semántica de algunos métodos requiere que deben poder aceptar el número variable de parámetros reales; por ejemplo, el famoso método principal debe poder aceptar todos los parámetros de la línea de comandos como parámetros reales, y el número de parámetros de línea de comandos no se puede determinar con anticipación.
Para este problema, tradicionalmente, la práctica de "usar una matriz para envolver los parámetros reales a pasar" generalmente se usa para lidiar con él.
1. Envuelva los parámetros en una matriz
La práctica de "envolver los parámetros reales con matrices" se puede dividir en tres pasos: primero, defina un parámetro de tipo matriz para este método; Luego, cuando se lo llame, genere una matriz que contenga todos los parámetros reales que se pasarán; Finalmente, pase esta matriz como un parámetro real.
Este enfoque puede lograr efectivamente el propósito de "hacer que el método acepte los parámetros variables", pero la forma en que llamar no es lo suficientemente simple.
El mecanismo VARARGS se proporciona en J2SE1.5, lo que permite una definición directa de parámetros formales que pueden coincidir con múltiples parámetros reales. Por lo tanto, se puede pasar un número variable de parámetros reales de manera más simple.
El significado de los varargs
En términos generales, "Varargs" significa "VariAblenumingumentSoFargumentos". A veces simplemente se llama "variablargumentos", pero debido a que este término no indica qué es variable, el significado es un poco vago.
2. Defina un método con parámetros reales variables
Simplemente agregue tres consecutivos "." (es decir, "...", un elipsis en la oración en inglés) entre el "tipo" y el "nombre del parámetro" de un parámetro formal, y puede coincidir con un parámetro real incierto. Un método con tales parámetros formales es un método con parámetros reales variables.
Listado 1: un método con parámetros reales variables
privado static int sumup (int ... valores) {}Tenga en cuenta que solo el último parámetro formal puede definirse como "puede coincidir con un parámetro real incierto". Por lo tanto, solo puede haber uno de esos parámetros formales en un método. Además, si este método tiene otros parámetros formales, colóquelos en la posición frontal.
El compilador convertirá el último parámetro formal en un parámetro formal de matriz en secreto y hará una marca en el archivo de clase compilada para indicar que este es un método con parámetros reales variables.
Listado 2: forma secreta de un método con parámetros reales variables
privado static int sumup (int [] valores) {}Debido a tales transformaciones, es imposible definir un método para esta clase que sea consistente con la firma del método convertido.
Listado 3: Combinaciones que causarán errores de compilación
privado static int sumup (int ... valores) {} private static int sumup (int [] valores) {}3. Llame a un método con un número variable de parámetros reales
Mientras los parámetros reales a pasar se escriban uno por uno a la posición correspondiente, se puede llamar a un método con un número variable de parámetros reales. No se requieren otros pasos.
Listado 4: Se pueden pasar varios parámetros
sumUp(1,3,5,7);
Indirectamente, el compilador convertirá este proceso llamado en forma de "matriz envuelta en parámetros reales":
Listado 5: Creación de matriz que aparece en secreto
sumUp(newint[]{1,2,3,4});
Además, el "incierto" mencionado aquí también incluye cero, por lo que tal llamada es razonable:
Listado 6: también puede aprobar cero parámetros reales
sumUp();
El efecto de este método de llamadas convertido en secreto por el compilador es equivalente a esto:
Listado 7: Cero argumentos reales corresponden a matrices vacías
sumUp(newint[]{});
Tenga en cuenta que el pasado se pasa en este momento, no nulo. Esto permite que se maneje una forma unificada sin tener que detectar a qué situación pertenece.
4. Procese los parámetros reales con números variables
El método de procesamiento de parámetros reales numerosos es básicamente el mismo que el método de procesamiento de parámetros reales de matriz. Todos los parámetros reales se guardan en una matriz con el mismo nombre que los parámetros formales. Según las necesidades reales, después de leer los elementos en esta matriz, al vapor o cocinar, puede hacer lo que quiera.
Listado 8: procesar los argumentos recibidos
privado static int sumup (int ... valores) {int sum = 0; for (int i = 0; i <value.length; i ++) {sum+= valores [i]; } suma de retorno;}5. Reenviar el número variable de parámetros
A veces, después de aceptar un conjunto de parámetros de número variable, deben pasar a otro método de número de variable. Debido a que no se puede conocer el número de parámetros reales recibidos durante la codificación, no es factible la práctica de "escribirlos uno por uno en el lugar donde deben aparecer". Sin embargo, esto no significa que esta sea una tarea inquebrantable, porque hay otra forma de llamar a un método con parámetros reales variables.
A los ojos del compilador J2SE1.5, el método con parámetros reales variables es un caso especial del método con una serie de parámetros formales al final. Por lo tanto, coloque el conjunto completo de parámetros reales que se pasen a una matriz por adelantado, y luego pase esta matriz como el último parámetro real a un método con un número variable de parámetros reales, que no causarán ningún error. Con esta característica, el reenvío se puede completar sin problemas.
Listado 9: Reenviar los parámetros reales recibidos
public class printfSample {public static void main (string [] args) {printOut ("pi:%f e:%f/n", math.pi, math.e); } Private static void Printout (formato de cadena, objeto ... args) {system.out.printf (formato, args); }}6. ¿Es una matriz? ¿No es una matriz?
Aunque detrás de escena, el compilador convertirá parámetros formales que pueden igualar los parámetros reales inciertos en parámetros formales de matriz; y también puede usar una matriz para envolver los parámetros reales y luego pasarlos a un método con un número variable de parámetros reales; Sin embargo, esto no significa que no haya diferencia entre "los parámetros formales que pueden igualar los parámetros reales inciertos" y los "parámetros formales de matriz".
Una diferencia obvia es que si llama a un método cuyo último parámetro formal es un parámetro formal de matriz en forma de un método con un número variable de parámetros reales, solo conducirá a un error de compilación "no puede aplicarse".
Listado 10: un error de compilación para "no se puede aplicar"
Private static void testoverloading (int [] i) {system.out.println ("a");} public static void main (string [] args) {testoverloading (1, 2, 3); // error de compilación}Por esta razón, este método de llamada concisa no se puede adoptar directamente al llamar a métodos que solo admiten los parámetros reales con matrices (por ejemplo, los que quedan de diseños de biblioteca de terceros para J2SE1.5).
Si no puede modificar la clase original y agregar una versión variable del número de parámetros al método a llamar, y desea adoptar este método de llamadas concisas, puede usar los métodos de reconstrucción de "IntrodoreignMethod" y "Introcelocalextension" para aproximar el propósito.
7. Cuando un número variable de argumentos encuentra un genérico
Se ha agregado un nuevo mecanismo "genérico" a J2SE1.5, que puede parametrizar un tipo bajo ciertas condiciones. Por ejemplo, al escribir una clase, el tipo de parámetros formales de un método puede ser representado por un identificador (como T). En cuanto a qué tipo representa este identificador, se especifica al generar una instancia de esta clase. Este mecanismo se puede utilizar para proporcionar una reutilización de código más completa y una verificación de tipo de compilación más estricta.
Sin embargo, el mecanismo genérico no puede usarse con números variables de parámetros formales. Si un identificador representa un tipo de parámetro formal que coincide con un argumento incierto, el compilador dará un error de "GenericArrayCreation".
Listado 11: Cuando Varargs cumple con los genéricos
Private static void testVarargs (t ... args) {// error de compilación}La razón de este fenómeno es una restricción inherente del mecanismo genérico en J2SE1.5: no se puede crear una instancia de este tipo con el tipo representado por un identificador. Antes de que apareciera la versión Java sin esta restricción, básicamente no había buena solución a este problema.
Sin embargo, la práctica tradicional de "envoltura con matrices" no está sujeto a esta restricción.
Listado 12: soluciones compilables
Private static void testVarargs (t [] args) {para (int i = 0; i <args.length; i ++) {system.out.println (args [i]); }}8. Problemas de selección en sobrecarga
Java admite mecanismos de "sobrecarga", lo que permite que muchos métodos diferentes en la misma clase tengan solo listas de parámetros formales. Luego, el compilador selecciona qué método ejecutar en función de los parámetros reales en el momento de la llamada.
Las opciones tradicionales se basan básicamente en el principio de "se prefieren las personas especiales". La especialidad de un método depende de la cantidad de condiciones que deben cumplirse para que se ejecute sin problemas. Cuantas más condiciones necesite, más especial es.
Después de la introducción del mecanismo Varargs, este principio aún se aplica, pero los problemas a considerar están enriquecidos, tradicionalmente, entre las diversas versiones de un método sobrecargado, solo aquellos cuyos parámetros morfológicos y parámetros reales son exactamente los mismos son elegibles para una mayor consideración. Sin embargo, después de la introducción del mecanismo Varargs, es posible que coincida con ambas versiones, y no hay diferencia en otros aspectos, solo que un parámetro real tiene un número fijo y el otro parámetro real tiene un número variable.
En este caso, la regla de determinación utilizada es que "la versión con número fijo de parámetros reales tiene prioridad sobre la versión con un número variable de parámetros reales".
Listado 13: Se prefieren versiones con un número fijo de parámetros reales
Si, en la opinión del compilador, múltiples métodos tienen la misma prioridad, se atascará en un estado en el que no puede elegir qué método llamar. En este caso, generará un error de compilación de "referencia de referencia llamado nombre del método isambiguo" y espere pacientemente algunas modificaciones para evitar la llegada del nuevo código fuente que es confuso.
Después de la introducción del mecanismo Varargs, esta situación que puede conducir a la confusión ha aumentado un poco más. Por ejemplo, puede haber dos versiones que pueden coincidir, que es exactamente las mismas en otros aspectos, y ambos conflictos con números variables de parámetros reales se producen.
Public Class OverloadingsAsmpeA {public static void main (string [] args) {testoverloading (1); // imprime atestoverloading (1, 2); // imprime btestoverloading (1, 2, 3); // imprime c} private static void void void loading (int i) {system.out.println ("a");} static static void void loadering (inti) j) {System.out.println ("B");} private static void testoverloading (int i, int ... más) {system.out.println ("c");}}Si, en la opinión del compilador, múltiples métodos tienen la misma prioridad, se atascará en un estado en el que no puede elegir qué método llamar. En este caso, generará un error de compilación de "referencia de referencia llamado nombre del método isambiguo" y espere pacientemente algunas modificaciones para evitar la llegada del nuevo código fuente que es confuso.
Después de la introducción del mecanismo Varargs, esta situación que puede conducir a la confusión ha aumentado un poco más. Por ejemplo, puede haber dos versiones que pueden coincidir, que es exactamente las mismas en otros aspectos, y ambos conflictos con números variables de parámetros reales se producen.
Listado 14: pase lo que pase, es difícil para el compilador ser
Public Class OverloadingSampleB {public static void main (string [] args) {testoverloading (1, 2, 3); // Error de compilación} private static void testoverloading (objeto ... args) {}}Además, debido a que existe el mecanismo de "autoboxing/auto-unboxing" en J2SE1.5, es posible que ambas versiones puedan coincidir, y el número de parámetros reales es variable, y los otros aspectos son exactamente el mismo. Es solo que un parámetro real aceptable es el tipo básico, mientras que el otro parámetro real aceptable es el conflicto entre la clase de paquete.
Listado 15: Nuevos problemas de Autoboxing/Auto-Unboxing
Public Class OverloadingsAsmplec {public static void main (string [] args) {/* Error de compilación*/testOverloading (1, 2);/* o compilar error*/testaroverloading (new Integer (1), nuevo entero (2));} private estático Voide testoverloverloadering (int ... args) {} Void voides de voides privado (intregerger ...9. Resumen
En comparación con el método "envuelto con matrices", el método real con parámetros reales variables es más simple y tiene significados más claros al llamar. Sin embargo, este mecanismo también tiene sus propias limitaciones y no es una solución perfecta.
Lo anterior es toda la explicación detallada del código de parámetros de longitud variable en Java, espero que sea útil para todos. Los amigos interesados pueden continuar referiéndose a este sitio:
Explicación detallada de los parámetros implícitos y las instancias de parámetros de visualización en Java
Implementación de programación de Java de la clasificación rápida y el código de optimización Explicación detallada
Decryto de cifrado Java y ejemplo de código completo de firma digital
Si hay alguna deficiencia, deje un mensaje para señalarlo. ¡Gracias amigos por su apoyo para este sitio!