¡Hola! Hoy hablaremos de operadores de salto en Java:
return
break
continue
goto
if
) y bucles ( for
, while
etc.). Además de las construcciones de control, la ejecución lineal de un programa se puede modificar mediante declaraciones de salto. Son responsables de redirigir la ejecución del programa a una ubicación específica, lo que depende del contexto y de la declaración específica. Echemos un vistazo más de cerca a cada uno de los cuatro operadores.
devolver
Es este operador con el que los recién llegados suelen familiarizarse primero. La declaraciónreturn
finaliza el método en el que fue llamada y la ejecución del programa regresa a la ubicación desde la que se llamó el método. Tiene return
dos formas:
- Finaliza inmediatamente la ejecución del método.
- Finaliza inmediatamente la ejecución del método y devuelve algún valor como resultado del método.
return;
return value; // где value — некоторое возвращаемое significado
Los métodos que devuelven un valor deben tener al menos un operador return
con un valor de retorno cuya llamada esté garantizada y no deben tener un operador return
sin un valor de retorno. Veamos los ejemplos a continuación:
public int sum(int a, int b) {
return a + b;
}
public String getGreetings(String name) {
return "Hello " + name;
}
public int max(int x, int y) {
if (x > y) {
return x;
} else {
return y;
}
}
En los métodos que no devuelven un valor (métodos void
), es aceptable, pero no obligatorio, tener al menos una declaración return
sin valor de retorno y ni una sola declaración return
con valor de retorno. Veamos esto con los siguientes ejemplos:
public void print(String s) {
// наличие return в void методах не обязательно
System.out.println(s);
}
//Метод выведет в консоль число, если оно нечетное
public void printIfOdd(int number) {
if (number % 2 == 0) {
// Если число четное, метод завершит свою работу
// Наличие return в void методах опционально
return;
}
System.out.println(number);
}
// Метод выведет в консоль наибольшее significado из массива
private void printMaxInArray(int[] array) {
if (array == null || array.length == 0) {
/*
Если массив пуст, метод завершит свою работу.
Иногда полезно проверять подобным образом аргументы метода вначале и прерывать выполнение метода, если аргументы не подходят для дальнейшей корректной работы
*/
System.out.println("Empty array");
return;
}
int max = array[1];
for (int i = 1; i < array.length; i++) {
if (array[i] > max) {
max = array[i];
}
}
System.out.println(max);
}
etiquetas
Antes de ver los operadoresbreak
y continue
, me gustaría hablar sobre las etiquetas en Java. Esto es importante porque, en algunas situaciones, los operadores break
y continue
se utilizan junto con etiquetas. Pero primero, intente responder la pregunta de si este código se compilará:
public static void main(String[] args) {
https://www.google.com/
System.out.println("Interesting...");
}
Una etiqueta es un fragmento de código con nombre. La etiqueta en sí no proporciona ninguna funcionalidad. Esto es algo así como un marcador en el código que el programador pretende utilizar más adelante. Una etiqueta en el código se define de forma muy sencilla: mediante un nombre y dos puntos. Por ejemplo:
labelName:
outerLoop:
printing:
anyWordYouLike:
public static void main(String[] args) {
definePrintName:
System.out.println("Таблица Умножения");
loop1:
for (int i = 1; i <= 10; i++) {
loop2:
for (int j = 1; j <= 10; j++) {
System.out.printf("%4d", i * j);
}
System.out.println();
}
}
La salida del método main
será la siguiente:
Таблица Умножения
1 2 3 4 5 6 7 8 9 10
2 4 6 8 10 12 14 16 18 20
3 6 9 12 15 18 21 24 27 30
4 8 12 16 20 24 28 32 36 40
5 10 15 20 25 30 35 40 45 50
6 12 18 24 30 36 42 48 54 60
7 14 21 28 35 42 49 56 63 70
8 16 24 32 40 48 56 64 72 80
9 18 27 36 45 54 63 72 81 90
10 20 30 40 50 60 70 80 90 100
Process finished with exit code 0
En el ejemplo anterior definePrintName
, loop1:
y loop2:
son etiquetas. loop1:
y loop2:
"marcar" dos ciclos: externo e interno. Veremos el uso de etiquetas en la sección siguiente. Mientras tanto, si respondió "no" a la pregunta de si este código se compilará:
public static void main(String[] args) {
https://www.google.com/
System.out.println("Interesting...");
}
Intente responder nuevamente, usando el IDE.
romper
El operadorbreak
se utiliza en dos casos:
- Para completar cualquier rama de ejecución en un bloque switch-case.
- Interrumpir la ejecución de un bucle.
break labelName; // Синтаксис оператора с меткой
break; // Синтаксис оператора без метки
En bloques de caja de interruptores, el operador break
se utiliza sin etiquetas:
public static void main(String[] args) {
int dayOfWeekInt = 4;
String dayOfWeek;
switch (dayOfWeekInt) {
case 1:
dayOfWeek = "Lunes";
break;
case 2:
dayOfWeek = "Martes";
break;
case 3:
dayOfWeek = "Miércoles";
break;
case 4:
dayOfWeek = "Jueves";
break;
case 5:
dayOfWeek = "Viernes";
break;
case 6:
dayOfWeek = "Sábado";
break;
case 7:
dayOfWeek = "Domingo";
break;
default:
dayOfWeek = "Неизвестный день";
break;
}
System.out.println("Сегодня " + dayOfWeek);
}
En los bucles, break
se utiliza una declaración para interrumpir iteraciones adicionales después de que se cumplan ciertas condiciones. Esto a menudo se puede encontrar cuando necesita iterar a través de una matriz o colección de elementos y encontrar algún elemento que satisfaga las condiciones necesarias. Consideremos este ejemplo. Tenemos una matriz y necesitamos determinar si la matriz contiene elementos negativos:
int a[] = {1,2,234,-123,12,-2,312,0,412,433};
boolean arrayHasNegativeElements = false;
for (int i = 0; i < a.length; i++) {
if (a[i] < 0) {
/*
Как только найдется
хотя бы один отрицательный элемент,
мы прервем цикл с помощью
оператора break, потому что
мы выяснo то, что нас интересовало,
и дальнейший перебор элементов не имеет смысла.
*/
arrayHasNegativeElements = true;
break;
}
}
Veamos el mismo ejemplo con diferentes bucles. Ciclo for-each
:
public static void main(String[] args) {
int a[] = {1,2,234,-123,12,-2,312,0,412,433};
boolean arrayHasNegativeElements = false;
for (int number : a) {
if (number < 0) {
arrayHasNegativeElements = true;
break;
}
}
}
Ciclo while
:
public static void main(String[] args) {
int a[] = {1,2,234,-123,12,-2,312,0,412,433};
boolean arrayHasNegativeElements = false;
int counter = 0;
while (counter < a.length) {
if (a[counter] < 0) {
arrayHasNegativeElements = true;
break;
}
counter ++;
}
}
Ciclo do-while
:
public static void main(String[] args) {
int a[] = {1,2,234,-123,12,-2,312,0,412,433};
boolean arrayHasNegativeElements = false;
int counter = 0;
do {
if (a[counter] < 0) {
arrayHasNegativeElements = true;
break;
}
counter ++;
} while (counter < a.length);
}
Otro ejemplo de declaración break
en bucles es interrumpir un bucle infinito cuando se cumplen ciertas condiciones. A continuación se muestra un ejemplo de un programa que muestra la línea ingresada por el usuario hasta que el usuario ingresa la palabra "detener":
public static void main(String[] args) {
Scanner scanner = new Scanner(System.in);
String line;
while (true) {
line = scanner.nextLine();
if ("stop".equals(line)){
/*
Прерываем бесконечный цикл,
при достижении
определенного условия
*/
break;
}
System.out.println("Пользователь ввел: " + line);
}
}
Consideremos usar el operador break
junto con una etiqueta. Una interrupción con etiqueta se utiliza en casos con varios ciclos, además, anidados uno dentro del otro. En este caso, uno de los ciclos (o todos los ciclos) está marcado con una etiqueta. A continuación, el operador, break
junto con la indicación de la etiqueta, interrumpe el ciclo deseado. Consideremos un ejemplo en el que necesitamos entender si hay un elemento negativo, pero no en la matriz, sino en la matriz:
public static void main(String[] args) {
int[][] a = {
{1, 2, 3},
{-412, 12, 0},
{1223, 474, -54}
};
boolean hasNegative = false;
searchNegative:
for (int i = 0; i < a.length; i++) {
for (int j = 0; j < a[i].length; j++) {
if (a[i][j] < 0) {
/*
Если использовать break без метки,
тогда прервется вложенный цикл for,
но внешний продолжит выполнять свои итерации
и поиск продолжится.
Поэтому мы "помечаем" внешний цикл меткой `searchNegative`
и прерываем внешний цикл оператором break совместно с нужной меткой.
*/
hasNegative = true;
break searchNegative;
}
}
}
}
continuidad
El operadorcontinue
también tiene dos formularios, con y sin etiqueta:
continue; // форма оператора без метки
continue labelName; // форма оператора с меткой
A diferencia del operador break
, que interrumpe todas las iteraciones restantes del ciclo, el operador continue
interrumpe la iteración actual y hace que comience la siguiente. Esto puede resultar útil si necesita realizar algunas operaciones en elementos que satisfacen determinadas condiciones. Digamos que tenemos una cadena y queremos contar el número de palabras que comienzan con la letra "m":
public static void main(String[] args) {
String sentence = "Мама мыла раму";
String[] words = sentence.split(" ");
int mWordsCount = 0;
for (int i = 0; i < words.length; i++) {
if ( ! words[i].toLowerCase().startsWith("м")) {
/*
Если слово не начинается с буквы м,
то текущая итерация прервется и цикл
ПРОДОЛЖИТ выполнение со следующей итерации
*/
continue;
}
mWordsCount ++;
}
System.out.println("Кол-во слов, начинающихся с буквы М в предложении: " + "[" + sentence + "] = " + mWordsCount);
}
Después de ejecutar este código, aparecerá el siguiente resultado en la consola:
Кол-во слов, начинающихся с буквы М в предложении: [Мама мыла раму] = 2
El operador continue
junto con la etiqueta también se utiliza al iterar sobre elementos. Imaginemos una matriz en la que necesitamos contar el número de filas con elementos negativos:
public static void main(String[] args) {
int[][] a = {
{1, 23, -1, 23, -12},
{21, 21, 0, 23, 123, 45},
{123, 3},
{123, -5, 4, -3},
{-1, -2, -3}
};
int rowsWithNegativeElementsCount = 0;
rowsLoop:
// Проходим по каждой строке
for (int[] arr : a) {
for (int number : arr) {
if (number < 0) {
/*
Если в текущей строке найдется
хотя бы 1 отрицательный элемент,
тогда мы увеличим переменную счетчик,
и с помощью оператора continue rowsLoop
прервем текущую итерацию внешнего цикла и
принудительно начнем следующую
*/
rowsWithNegativeElementsCount ++;
continue rowsLoop;
}
}
}
System.out.println("Rows With Negative Elements Count = " + rowsWithNegativeElementsCount);
}
La salida de este código será:
Rows With Negative Elements Count = 3
Vale decir que los operadores break
, continue
y return
pueden usarse de diferentes formas para lograr la misma funcionalidad. Entonces, puedes reescribir el último ejemplo y continue
usar break
:
public static void main(String[] args) {
int[][] a = {
{1, 23, -1, 23, -12},
{21, 21, 0, 23, 123, 45},
{123, 3},
{123, -5, 4, -3},
{-1, -2, -3}
};
int rowsWithNegativeElementsCount = 0;
for (int[] arr : a) {
for (int number : arr) {
if (number < 0) {
rowsWithNegativeElementsCount ++;
break;
}
}
}
System.out.println("Rows With Negative Elements Count = " + rowsWithNegativeElementsCount);
}
La diferencia entre break
y continue
con una etiqueta es lo que break
completa las iteraciones del bucle en el que está escrita. Y continue
con una etiqueta, omite la iteración actual del ciclo marcado con la etiqueta. En algunas situaciones, puedes reemplazar uno por otro y todo en la funcionalidad del programa seguirá siendo el mismo. Hablaremos sobre qué es mejor elegir (spoiler: legibilidad del código) a continuación. El operador break
se puede sustituir no sólo por continue
una etiqueta, sino también por return
. Justo antes de esto necesitas mover el bucle anidado a un método separado:
public static void main(String[] args) {
int[][] a = {
{1, 23, -1, 23, -12},
{21, 21, 0, 23, 123, 45},
{123, 3},
{123, -5, 4, -3},
{-1, -2, -3}
};
int rowsWithNegativeElementsCount = 0;
for (int[] arr : a) {
if (arrayHasNegativeElements(arr)) {
rowsWithNegativeElementsCount ++;
}
}
System.out.println("Rows With Negative Elements Count = " + rowsWithNegativeElementsCount);
}
static boolean arrayHasNegativeElements(int[] array) {
for (int number : array) {
if (number < 0) {
return true;
}
}
return false;
}
Muchas maneras de escribir lo mismo. ¿Cuál elegir? En programación industrial, esta cuestión la decide la facilidad de comprensión del código. Cuanto más sencillo esté escrito, mejor. Cuantos más bucles anidados, más difícil será percibir el código. Especialmente si los bucles están marcados con etiquetas diferentes, que se utilizan en interrupciones y continuaciones ( break
y continue
). Si es posible no utilizar etiquetas, es mejor hacerlo. De lo contrario, intenta escribir de la manera más clara y bella posible.
ir a
En algunos lenguajes de programación existe un operadorgoto
. Normalmente redirige la ejecución del código a alguna parte del programa marcada con una etiqueta. Pero en Java goto
, se podría decir, lo es y no lo es. Vamos a resolverlo. La lista de palabras clave en Java incluye la palabra goto
. Sin embargo, esta declaración está marcada como no utilizada. El caso es que James Gosling, el creador del lenguaje Java, inicialmente incluyó soporte para el operador en la JVM goto
. Sin embargo, esta característica fue eliminada posteriormente. Una de las razones es que los bloques de código que contienen el operador goto
no eran tan legibles como los bloques de código que realizaban las mismas funciones pero sin goto
, pero con enfoques alternativos ( break
,, continue
colocando el bloque de código en métodos). De hecho, hubo otros, como:
- dificultad para leer y comprender el código que contiene operadores
goto
; - complicar la optimización del código para el compilador (y a veces incluso imposible);
- aumentando la probabilidad de crear errores sutiles en el código.
goto
funciona con bastante éxito. Sin embargo, los programadores evitan usarlo. Puede leer sobre las razones de esto en un artículo sobre Habré . Pero ¿por qué entonces dejarla goto
en la lista de palabras reservadas? Es simple: para el futuro. Si, por ejemplo, se llaman variables, métodos o clases en el código Java de los desarrolladores de todo el mundo goto
, si esta declaración se devuelve en una versión futura de Java, todo el código antiguo se romperá. Para evitar tal escenario, goto
permanece en la lista de palabras clave de Java, pero no tiene ninguna funcionalidad. Quizás algún día goto
regrese a nuestras filas, pero la probabilidad de que esto ocurra es baja.
Resultados
Hemos analizado varios operadores de salto en Java:return
— finalización del método, devolviendo un valor del método.- con valor de retorno: métodos que devuelven valores;
- sin valor de retorno:
void
métodos.
break
— interrupción de ciclos, bloques de cajas de interruptores.- con etiquetas: ciclos de varios anidamientos;
- sin etiquetas: ramas de caja de interruptores del bloque; interrumpiendo el bucle en el que fue llamado.
continue
.- con etiquetas: ciclos de varios anidamientos;
- sin etiquetas: continuación del bucle en el que fue llamado.
goto
.- está en la lista de palabras clave, pero no se utiliza.
GO TO FULL VERSION