JavaRush /Java Blog /Random EN /Jump Operators in Java

Jump Operators in Java

Published in the Random EN group
Hello! Today we’ll talk about jump operators in Java:
  • return
  • break
  • continue
  • goto
First, let's define what it actually is. As you know, in a normal situation, a program is executed linearly - from top to bottom, command by command. The linear flow of a program can be changed by so-called control structures: for example, branches ( if) and loops ( for, whileetc.). In addition to control constructs, the linear execution of a program can be modified by jump statements. They are responsible for redirecting program execution to a specific location, which depends on the context and the specific statement. Jump Operators in Java - 1Let's take a closer look at each of the four operators.

return

It is this operator that newcomers most often become familiar with first. The statement returnterminates the method in which it was called, and program execution returns to the location from which the method was called. It returnhas two forms:
  1. Immediately ends execution of the method.
  2. Immediately ends execution of the method and returns some value as the result of the method.
The syntax for both forms is:
return;
return value; // где value — некоторое возвращаемое meaning
Methods that return a value must have at least one operator returnwith a return value that is guaranteed to be called, and must not have a operator returnwithout a return value. Let's look at the examples below:
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;
    }
}
In methods that do not return a value (methods void), it is acceptable, but not required, to have at least one statement returnwithout a return value, and not a single statement returnwith a return value. Let's look at this with the examples below:
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);
}

labels

Before looking at the breakand operators continue, I would like to talk about labels in Java. This is important because in some situations, breakand operators continueare used in conjunction with labels. But first, try to answer the question whether this code will compile:
public static void main(String[] args) {
    https://www.google.com/
    System.out.println("Interesting...");
}
A label is a named piece of code. The label itself does not provide any functionality. This is something like a bookmark in the code that the programmer intends to use later. A label in the code is defined quite simply - through a name and a colon. For example:
  • labelName:
  • outerLoop:
  • printing:
  • anyWordYouLike:
And this is what the labels look like inside the Java code:
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();
    }
}
The output of the method mainwill be as follows:
Таблица Умножения
   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
In the example above definePrintName, loop1:and loop2:are labels. loop1:and loop2:“mark” two cycles - external and internal. We'll look at using labels in the section below. In the meantime, if you answered “no” to the question whether this code will compile:
public static void main(String[] args) {
      https://www.google.com/
      System.out.println("Interesting...");
  }
Try answering it again, using the IDE.

break

The operator breakis used in two cases:
  1. To complete any execution branch in a switch-case block.
  2. To interrupt the execution of a loop.
The operator has two forms: with markings (label) and without. The syntax for both forms is:
break labelName; // Синтаксис оператора с меткой
break; // Синтаксис оператора без метки
In switch-case blocks, the operator breakis used without labels:
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);
}
In loops, a statement breakis used to interrupt further iterations after certain conditions are met. This can often be found when you need to iterate through an array or collection of elements and find some element in it that satisfies the necessary conditions. Let's consider this example. We have an array and we need to determine if the array contains negative elements:
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;
   }
}
Let's look at the same example with different loops. Cycle 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;
        }
    }
}
Cycle 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 ++;
    }
}
Cycle 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);
}
Another example of a statement breakin loops is to interrupt an infinite loop when certain conditions are met. Here is an example of a program that displays the line entered by the user until the user enters the word “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);
    }
}
Let's consider using the operator breaktogether with a label. An interrupt with a label is used in cases with several cycles, moreover, nested one within the other. In this case, one of the cycles (or all cycles) is marked with a label. Next, the operator, breaktogether with indicating the label, interrupts the desired cycle. Let's consider an example in which we need to understand whether there is a negative element, but not in the array, but in the matrix:
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;
               }
           }
       }
}

continuity

The operator continuealso has two forms - with and without a label:
continue; // форма оператора без метки
continue labelName; // форма оператора с меткой
Unlike the operator break, which interrupts all remaining iterations of the loop, the operator continueinterrupts the current iteration and causes the next one to start. Jump Operators in Java - 2This can be useful if you need to perform some operations on elements that satisfy certain conditions. Let's say we have a string and we want to count the number of words starting with the letter "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);
}
After executing this code there will be the following output in the console:
Кол-во слов, начинающихся с буквы М в предложении: [Мама мыла раму] = 2
The operator continuetogether with the label is also used when iterating over elements. Let's imagine a matrix in which we need to count the number of rows with negative elements:
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);
}
The output of this code will be:
Rows With Negative Elements Count = 3
It is worth saying that the operators break, continueand returncan be used in different ways to achieve the same functionality. So, you can rewrite the last example and continueuse 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);
}
The difference between breakand continuewith a label is what breakcompletes the iterations of the loop in which it is written. And continuewith a label, skips the current iteration of the cycle marked with the label. In some situations, you can replace one with the other, and everything in the functionality of the program will remain the same. We’ll talk about what’s best to choose (spoiler: code readability) below. The operator breakcan be replaced not only with continuewith a label, but also with return. Just before this you need to move the nested loop into a separate method:
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;
}
Lots of ways to write the same thing. Which one to choose? In industrial programming, this issue is decided by the ease of understanding the code. The simpler it is written, the better. The more nested loops, the more difficult it is to perceive the code. Especially if the loops are marked with different marks, which are used in interrupts and continuations ( breakand continue). If it is possible not to use tags, it is better to do so. Otherwise, try to write as clearly and beautifully as possible.

goto

In some programming languages ​​there is an operator goto. Typically it redirects code execution to some part of the program marked with a label. But in Java goto, one might say, it is and it is not. Let's figure it out. The list of keywords in Java includes the word goto. However, this statement is marked as not used. The fact is that James Gosling, the creator of the Java language, initially included support for the operator in the JVM goto. However, this feature was later cut out. One of the reasons is that blocks of code containing the operator gotowere not as readable as blocks of code that performed the same functions but without goto, but with alternative approaches ( break, continue, placing the code block in methods). There were, in fact, others, such as:
  • difficulty reading and understanding code that contains operators goto;
  • complicating code optimization for the compiler (and sometimes even impossible);
  • increasing the likelihood of creating subtle errors in the code.
It is no secret to many that in some programming languages ​​the operator gotofunctions quite successfully. However, programmers avoid using it. You can read about the reasons for this in one article on Habré . But why then leave it gotoon the list of reserved words? It's simple: for the future. If, for example, variables, methods, or classes are called , in developers' Java code all over the world goto, if this statement is returned in a future version of Java, all the old code will break. To avoid such a scenario, gotoit remains in the list of Java keywords, but does not carry any functionality. Perhaps someday gotohe will return to our ranks, but the likelihood of this is low.

Results

We have looked at various jump operators in Java:
  1. return— completion of the method, returning a value from the method.
    • with a return value: methods that return values;
    • no return value: voidmethods.
  2. break— interruption of cycles, switch-case blocks.
    • with tags: cycles of various nesting;
    • without labels: switch-case branches of the block; interrupting the loop in which it was called.
  3. continue.
    • with tags: cycles of various nesting;
    • without labels: continuation of the loop in which it was called.
  4. goto.
    • is in the list of keywords, but is not used.
The conclusion from all this is simple: it is better to give preference to the simplest approaches that make the code easier to read. Try not to overload your code with multi-level loops nested inside each other with an abundance of marks, interruptions and continuations.
Comments
TO VIEW ALL COMMENTS OR TO MAKE A COMMENT,
GO TO FULL VERSION