Tengo una situación en la que siempre se alcanzará la returndeclaración anidada en dos forbucles, en teoría.
El compilador no está de acuerdo y requiere una returndeclaración fuera del forciclo. Me gustaría conocer una forma elegante de optimizar este método que está más allá de mi comprensión actual, y ninguna de mis implementaciones de ruptura intentadas parece funcionar.
Attached es un método de una asignación que genera enteros aleatorios y devuelve las iteraciones recorridas hasta que se encuentra un segundo entero aleatorio, generado dentro de un rango pasado al método como un parámetro int.
private static int oneRun(int range) {
int[] rInt = new int[range+1]; // Stores the past sequence of ints.
rInt[0] = generator.nextInt(range); // Inital random number.
for (int count = 1; count <= range; count++) { // Run until return.
rInt[count] = generator.nextInt(range); // Add randint to current iteration.
for (int i = 0; i < count; i++) { // Check for past occurence and return if found.
if (rInt[i] == rInt[count]) {
return count;
}
}
}
return 0; // Never reached
}

while(true)bucle en lugar de un bucle indexado. Esto le dice al compilador que el bucle nunca regresará.oneRun(0)) y verá que rápidamente alcanza su inalcanzablereturnnextIntarroja una excepción pararange < 0El único caso en el que se alcanza el retorno es cuandorange == 0Respuestas:
La heurística del compilador nunca le permitirá omitir la última
return. Si está seguro de que nunca se alcanzará, lo reemplazaría con unthrowpara aclarar la situación.fuente
throw new AssertionError("\"unreachable\" code reached");throwque nunca se alcanzará. Con demasiada frecuencia, la gente solo quiere aplicar rápidamente "una solución para gobernarlos a todos" sin pensar demasiado en el problema subyacente. Pero programar es mucho más que codificar. Especialmente cuando se trata de algoritmos. Si inspecciona (cuidadosamente) el problema dado, se dará cuenta de que puede factorizar la última iteración delforbucle externo y, por lo tanto, reemplazar el retorno "inútil" por uno útil (consulte esta respuesta ).Como señaló @BoristheSpider, puede asegurarse de que la segunda
returndeclaración sea semánticamente inalcanzable:Se compila y funciona bien. Y si alguna vez obtiene un
ArrayIndexOutOfBoundsException, sabrá que la implementación fue semánticamente incorrecta, sin tener que arrojar nada explícitamente.fuente
for(int count = 0; true; count++)lugar.true:for(int count = 0; ; count++) …while(true), pensé que quizás Java sea un poco más estricto en este sentido. Es bueno saber que no hay necesidad de preocuparse ... En realidad, me gustatruemucho más la versión omitida : deja visualmente claro que no hay absolutamente ninguna condición para mirar :-)Como preguntaste sobre cómo romper dos
forbucles, puedes usar una etiqueta para hacerlo (mira el ejemplo a continuación):fuente
returnValuese puede usar sin inicializar?Mientras que una aserción es una buena solución rápida. En general, este tipo de problemas significa que su código es demasiado complicado. Cuando miro su código, es obvio que realmente no desea que una matriz contenga números anteriores. Quieres un
Set:Ahora tenga en cuenta que lo que estamos devolviendo es en realidad el tamaño del conjunto. La complejidad del código ha disminuido de cuadrática a lineal y es inmediatamente más legible.
Ahora podemos darnos cuenta de que ni siquiera necesitamos ese
countíndice:fuente
Como su valor de retorno se basa en la variable del ciclo externo, simplemente puede alterar la condición del ciclo externo
count < rangey luego devolver este último valor (que acaba de omitir) al final de la función:De esta forma, no es necesario introducir un código que nunca se alcanzará.
fuente
...) pero el bucle exterior se ha reducido en su última iteración. El caso correspondiente a esta última iteración es manejado por separado por la última declaración de retorno. Aunque esta es una solución elegante para su ejemplo, hay escenarios en los que este enfoque se vuelve más difícil de leer; si, por ejemplo, el valor de retorno dependiera del ciclo interno, entonces, en lugar de una declaración de retorno única al final, se quedaría con un ciclo adicional (que representa el ciclo interno para la última iteración del ciclo externo).Utilice una variable temporal, por ejemplo, "resultado", y elimine el retorno interno. Cambie el bucle for por un bucle while con la condición adecuada. Para mí, siempre es más elegante tener solo un retorno como última declaración de la función.
fuente
return resultesparcieron dentro de él y luego piensan en querer hacer una verificación más en el encontradoresultantes de devolverlo, y esto es solo un ejemplo). También puede haber contras, pero una afirmación tan amplia como "En general, no hay una buena razón para tener una sola devolución" no es válida.Tal vez esto sea una indicación de que debería reescribir su código. Por ejemplo:
fuente
Los métodos que tienen una declaración de retorno y tienen un bucle / bucles dentro de ellos siempre requieren una declaración de devolución fuera del bucle (s). Incluso si esta declaración fuera del ciclo nunca se alcanza. En tales casos, para evitar declaraciones de retorno innecesarias, puede definir una variable del tipo respectivo, un entero en su caso, al comienzo del método, es decir, antes y fuera de los bucles respectivos. Cuando se alcanza el resultado deseado dentro del ciclo, puede atribuir el valor respectivo a esta variable predefinida y usarlo para la declaración de retorno fuera del ciclo.
Como desea que su método devuelva el primer resultado cuando rInt [i] es igual a rInt [count], implementar solo la variable mencionada anteriormente no es suficiente porque el método devolverá el último resultado cuando rInt [i] es igual a rInt [count]. Una opción es implementar dos "sentencias de interrupción" que se llaman cuando tenemos el resultado deseado. Entonces, el método se verá así:
fuente
Estoy de acuerdo en que se debería lanzar una excepción cuando ocurra una declaración inalcanzable. Solo quería mostrar cómo el mismo método puede hacer esto de una manera más legible (se requieren secuencias de Java 8).
fuente
fuente
result == -1controles que se pueden omitir con elreturninterior del bucle ...