Olá! Hoje falaremos sobre operadores de salto em Java:
return
break
continue
goto
if
) e loops ( for
, while
etc.). Além das estruturas de controle, a execução linear de um programa pode ser modificada por instruções de salto. Eles são responsáveis por redirecionar a execução do programa para um local específico, que depende do contexto e da instrução específica. Vamos dar uma olhada mais de perto em cada um dos quatro operadores.
retornar
É com esse operador que os recém-chegados geralmente se familiarizam primeiro. A instruçãoreturn
encerra o método no qual foi chamada e a execução do programa retorna ao local de onde o método foi chamado. Possui return
duas formas:
- Termina imediatamente a execução do método.
- Finaliza imediatamente a execução do método e retorna algum valor como resultado do método.
return;
return value; // где value — некоторое возвращаемое meaning
Os métodos que retornam um valor devem ter pelo menos um operador return
com um valor de retorno que seja garantido para ser chamado e não devem ter um operador return
sem um valor de retorno. Vejamos os exemplos abaixo:
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;
}
}
Em métodos que não retornam um valor (methods void
), é aceitável, mas não obrigatório, ter pelo menos uma instrução return
sem valor de retorno, e nem uma única instrução return
com valor de retorno. Vejamos isso com os exemplos abaixo:
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);
}
// Метод выведет в консоль наибольшее meaning из массива
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);
}
rótulos
Antes de examinar os operadoresbreak
e continue
, gostaria de falar sobre rótulos em Java. Isso é importante porque, em algumas situações, os operadores break
e continue
são usados em conjunto com rótulos. Mas primeiro, tente responder à pergunta se este código será compilado:
public static void main(String[] args) {
https://www.google.com/
System.out.println("Interesting...");
}
Um rótulo é um trecho de código nomeado. A etiqueta em si não fornece nenhuma funcionalidade. Isto é algo como um marcador no código que o programador pretende usar mais tarde. Um rótulo no código é definido de forma bastante simples - por meio de um nome e dois pontos. Por exemplo:
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();
}
}
A saída do método main
será a seguinte:
Таблица Умножения
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
No exemplo acima definePrintName
, loop1:
e loop2:
são rótulos. loop1:
e loop2:
“marcar” dois ciclos – externo e interno. Veremos como usar rótulos na seção abaixo. Enquanto isso, se você respondeu “não” à pergunta se este código será compilado:
public static void main(String[] args) {
https://www.google.com/
System.out.println("Interesting...");
}
Tente responder novamente, usando o IDE.
quebrar
O operadorbreak
é usado em dois casos:
- Para completar qualquer ramificação de execução em um bloco switch-case.
- Para interromper a execução de um loop.
break labelName; // Синтаксис оператора с меткой
break; // Синтаксис оператора без метки
Em blocos switch-case, o operador break
é usado sem rótulos:
public static void main(String[] args) {
int dayOfWeekInt = 4;
String dayOfWeek;
switch (dayOfWeekInt) {
case 1:
dayOfWeek = "Monday";
break;
case 2:
dayOfWeek = "Tuesday";
break;
case 3:
dayOfWeek = "Wednesday";
break;
case 4:
dayOfWeek = "Thursday";
break;
case 5:
dayOfWeek = "Friday";
break;
case 6:
dayOfWeek = "Saturday";
break;
case 7:
dayOfWeek = "Sunday";
break;
default:
dayOfWeek = "Неизвестный день";
break;
}
System.out.println("Сегодня " + dayOfWeek);
}
Em loops, uma instrução break
é usada para interromper iterações adicionais após certas condições serem atendidas. Muitas vezes, isso pode ser encontrado quando você precisa iterar em uma matriz ou coleção de elementos e encontrar algum elemento que satisfaça as condições necessárias. Vamos considerar este exemplo. Temos um array e precisamos determinar se o array contém 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, потому что
мы выяснor то, что нас интересовало,
и дальнейший перебор элементов не имеет смысла.
*/
arrayHasNegativeElements = true;
break;
}
}
Vejamos o mesmo exemplo com loops diferentes. 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);
}
Outro exemplo de instrução break
em loops é interromper um loop infinito quando certas condições são atingidas. Aqui está um exemplo de programa que exibe a linha inserida pelo usuário até que ele insira a palavra “stop”:
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);
}
}
Vamos considerar o uso do operador break
junto com um rótulo. Uma interrupção com rótulo é utilizada em casos com vários ciclos, aliás, aninhados um dentro do outro. Neste caso, um dos ciclos (ou todos os ciclos) é marcado com uma etiqueta. A seguir, o operador, break
juntamente com a indicação da etiqueta, interrompe o ciclo desejado. Vamos considerar um exemplo em que precisamos entender se existe um elemento negativo, mas não no array, mas na 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;
}
}
}
}
continuidade
A operadoracontinue
também possui dois formulários - com e sem etiqueta:
continue; // форма оператора без метки
continue labelName; // форма оператора с меткой
Ao contrário do operador break
, que interrompe todas as iterações restantes do loop, o operador continue
interrompe a iteração atual e faz com que a próxima seja iniciada. Isto pode ser útil se você precisar realizar algumas operações em elementos que satisfaçam determinadas condições. Digamos que temos uma string e queremos contar o número de palavras que começam com a 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);
}
Após executar este código, haverá a seguinte saída no console:
Кол-во слов, начинающихся с буквы М в предложении: [Мама мыла раму] = 2
O operador continue
junto com o rótulo também é usado ao iterar sobre elementos. Vamos imaginar uma matriz na qual precisamos contar o número de linhas com 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);
}
A saída deste código será:
Rows With Negative Elements Count = 3
Vale dizer que os operadores break
, continue
e return
podem ser utilizados de diversas maneiras para atingir a mesma funcionalidade. Então, você pode reescrever o último exemplo e 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);
}
A diferença entre break
e continue
com um rótulo é o que break
completa as iterações do loop em que ele está escrito. E continue
com um rótulo, pula a iteração atual do ciclo marcado com o rótulo. Em algumas situações, você pode substituir um pelo outro, e tudo na funcionalidade do programa permanecerá o mesmo. Falaremos sobre o que é melhor escolher (spoiler: legibilidade do código) abaixo. O operador break
pode ser substituído não apenas por continue
um rótulo, mas também por return
. Pouco antes disso você precisa mover o loop aninhado para um 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;
}
Muitas maneiras de escrever a mesma coisa. Qual escolher? Na programação industrial, essa questão é decidida pela facilidade de compreensão do código. Quanto mais simples for escrito, melhor. Quanto mais loops aninhados, mais difícil será perceber o código. Principalmente se os loops estiverem marcados com marcas diferentes, que são usadas em interrupções e continuações ( break
e continue
). Se for possível não usar tags, é melhor fazê-lo. Caso contrário, tente escrever da forma mais clara e bonita possível.
Vá para
Em algumas linguagens de programação existe um operadorgoto
. Normalmente ele redireciona a execução do código para alguma parte do programa marcada com um rótulo. Mas em Java goto
, pode-se dizer, é e não é. Vamos descobrir. A lista de palavras-chave em Java inclui a palavra goto
. No entanto, esta declaração está marcada como não usada. O fato é que James Gosling, o criador da linguagem Java, inicialmente incluiu suporte ao operador na JVM goto
. No entanto, esse recurso foi posteriormente eliminado. Uma das razões é que os blocos de código contendo o operador goto
não eram tão legíveis quanto os blocos de código que executavam as mesmas funções, mas sem goto
, mas com abordagens alternativas ( break
,, continue
colocando o bloco de código em métodos). Houve, de fato, outros, como:
- dificuldade de leitura e compreensão de código que contém operadores
goto
; - complicar a otimização do código para o compilador (e às vezes até impossível);
- aumentando a probabilidade de criar erros sutis no código.
goto
funciona com bastante sucesso. No entanto, os programadores evitam usá-lo. Você pode ler sobre as razões para isso em um artigo no Habré . Mas por que então deixá-la goto
na lista de palavras reservadas? É simples: para o futuro. Se, por exemplo, variáveis, métodos ou classes forem chamados, no código Java de desenvolvedores em todo o mundo goto
, se esta instrução for retornada em uma versão futura do Java, todo o código antigo será quebrado. Para evitar tal cenário, goto
ela permanece na lista de palavras-chave Java, mas não possui nenhuma funcionalidade. Talvez um dia goto
ele retorne às nossas fileiras, mas a probabilidade de isso acontecer é baixa.
Resultados
Vimos vários operadores de salto em Java:return
— conclusão do método, retornando um valor do método.- com valor de retorno: métodos que retornam valores;
- sem valor de retorno:
void
métodos.
break
— interrupção de ciclos, bloqueios de caixas de comutação.- com tags: ciclos de vários aninhamentos;
- sem rótulos: ramificações da caixa de comutação do bloco; interrompendo o loop em que foi chamado.
continue
.- com tags: ciclos de vários aninhamentos;
- sem rótulos: continuação do loop em que foi chamado.
goto
.- está na lista de palavras-chave, mas não é usado.
GO TO FULL VERSION