2009-06-01 16 views
5

Me gustaría crear un método de inicialización para una clase Java que acepta 3 parámetros:Método de Java con parámetros de tamaño de matriz forzada?

Employee[] method(String[] employeeNames, Integer[] employeeAges, float[] employeeSalaries) 
{ 
    Employee myEmployees[] = new Employee[SIZE];// dont know what size is 

    for (int count = 0; count < SIZE; count++) 
    { 
     myEmployees[count] = new Employee(employeeNames[count], employeeAges[count], employeeSalaries[count]); 
    } 
    return myEmployees; 
} 

Usted puede notar que este código es incorrecto. La variable TAMAÑO no está definida. Mi problema es que me gustaría pasar en 3 matrices, pero me gustaría saber si puedo asegurarme de que las tres matrices tengan TODO el mismo tamaño de matriz. De esta forma, el bucle for no fallará, ya que el constructor en el bucle for usa todos los parámetros de las matrices.

Quizás Java tenga una característica diferente que pueda imponer una solución a mi problema. Podría aceptar otro parámetro llamado SIZE que se usará en el ciclo for, pero eso no resuelve mi problema si los parámetros 1 y 2 son del tamaño 10 y el 3er parámetro es una matriz de tamaño 9.

Así que solo para rehash en caso de que no fuera claro. ¿Cómo puedo hacer cumplir que los 3 argumentos son todos los arrays que contienen exactamente la misma cantidad de elementos?

El uso de un parámetro adicional que especifica los tamaños de matriz no es muy elegante y está algo sucio. Tampoco resuelve el problema de que los parámetros de matriz contienen matrices de diferentes tamaños.

Respuesta

16

No se puede aplicar eso en tiempo de compilación. Es, básicamente, tiene que comprobar en tiempo de ejecución, y lanzar una excepción si la restricción no se cumple:

Employee[] method(String[] employeeNames, 
        Integer[] employeeAges, 
        float[] employeeSalaries) 
{ 
    if (employeeNames == null 
     || employeeAges == null 
     || employeeSalaries == null) 
    { 
     throw new NullPointerException(); 
    } 
    int size = employeeNames.length; 
    if (employeesAges.length != size || employeeSalaries.length != size) 
    { 
     throw new IllegalArgumentException 
      ("Names/ages/salaries must be the same size"); 
    } 
    ... 
} 
+0

Gracias Jon, excelente respuesta! –

+2

Este es un buen ejemplo de lo que considero la forma incorrecta de usar NullPointerException. Haría una comprobación individual para cada uno de los parámetros pasados ​​ if (employeeNames == null) { throw new IllegalArgumentException ("employeeNames == null"); } Esto hace que stacktrace sea mucho más útil para diagnosticar el problema. –

+0

Creo que es igual de aceptable lanzar un NPE en este caso (mientras que nadie estaría en desacuerdo con tirar un IAE); pero tal vez como un poco de compromiso en este debate/controversia, sería mejor incluir un mensaje con la NPE. –

2

Dado que las matrices se pasó no se generan hasta que el tiempo de ejecución, no es posible evitar que el método la llamada se completa dependiendo de las características de la matriz que se pasa como una verificación en tiempo de compilación.

Como mencionó Jon Skeet, la única manera de indicar un problema es arrojar un IllegalArgumentException o similar en tiempo de ejecución para detener el procesamiento cuando se llama al método con los parámetros incorrectos.

En cualquier caso, la documentación debe tener en cuenta claramente las expectativas y el "contrato" para utilizar el método - el paso de tres matrices que tienen las mismas longitudes. Probablemente sería una buena idea anotar esto en Javadocs para el método.

0

Una manera de rodear el problema es la creación de un constructor, por ejemplo, EmployeeArrayBuilder,

public class EmployeeArrayBuilder { 
    private Integer arraySize = null; 
    private String[] employeeNames; 
    public EmployeeArrayBuilder addName(String[] employeeNames) { 
     if (arraySize == null) { 
     arraySize = employeeNames.length; 
     } else if (arraySize != employeeNames.length) { 
     throw new IllegalArgumentException("employeeNames needs to be " + arraySize + " in length"); 
     } 
     this.employeeNames = employeeNames; 
     return this; 
    } 
    public EmployeeArrayBuilder addSalaries(float[] employeeSalaries) {/* similar to above */} 
    public EmployeeArrayBuilder addAges(Integer[] employeeAges) {/* similar */} 
    public Employee[] build() { 
     // here, you can do what you needed to do in the constructor in question, and be sure that the members are correctly sized. 
     Employee myEmployees[] = new Employee[arraySize ];// dont know what size is    
     for (int count = 0; count < arraySize ; count++) { 
      myEmployees[count] = new Employee(employeeNames[count], employeeAges[count], employeeSalaries[count]); 
     } 
     return myEmployees; 
    } 
} 
+0

No creo que un constructor es apropiado aquí porque no hay nada en la API que sugiera que se necesiten las edades, los nombres y los salarios. El generador es apropiado cuando se pueden tener argumentos opcionales. También es bastante complejo en comparación con la respuesta de Jon Skeet. –

+0

@Ken Liu: ambos resuelve el mismo problema - publiqué esto porque la otra solución ya está publicada, ¿por qué duplicar? y esta es una alternativa que merece cierta consideración. De hecho, no hay nada en la API que sugiera que estos sean argumentos necesarios, pero eso no quita nada de el patrón del constructor – Chii

Cuestiones relacionadas