JavaRush /Java-Blog /Random-DE /Sprungoperatoren in Java

Sprungoperatoren in Java

Veröffentlicht in der Gruppe Random-DE
Hallo! Heute sprechen wir über Sprungoperatoren in Java:
  • return
  • break
  • continue
  • goto
Definieren wir zunächst, was es eigentlich ist. Wie Sie wissen, wird ein Programm im Normalfall linear ausgeführt – von oben nach unten, Befehl für Befehl. Der lineare Ablauf eines Programms kann durch sogenannte Kontrollstrukturen verändert werden: zum Beispiel durch Verzweigungen ( if) und Schleifen ( forusw. while). Zusätzlich zu Kontrollkonstrukten kann die lineare Ausführung eines Programms durch Sprunganweisungen verändert werden. Sie sind dafür verantwortlich, die Programmausführung an einen bestimmten Ort umzuleiten, der vom Kontext und der spezifischen Anweisung abhängt. Sprungoperatoren in Java - 1Schauen wir uns jeden der vier Operatoren genauer an.

zurückkehren

Es ist dieser Operator, mit dem sich Neulinge am häufigsten zuerst vertraut machen. Die Anweisung returnbeendet die Methode, in der sie aufgerufen wurde, und die Programmausführung kehrt an die Stelle zurück, von der aus die Methode aufgerufen wurde. Es returngibt zwei Formen:
  1. Beendet sofort die Ausführung der Methode.
  2. Beendet die Ausführung der Methode sofort und gibt als Ergebnis der Methode einen Wert zurück.
Die Syntax für beide Formen lautet:
return;
return value; // где value — некоторое возвращаемое Bedeutung
Methoden, die einen Wert zurückgeben, müssen mindestens einen Operator returnmit einem Rückgabewert haben, der garantiert aufgerufen wird, und dürfen keinen Operator returnohne Rückgabewert haben. Schauen wir uns die folgenden Beispiele an:
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;
    }
}
Bei Methoden, die keinen Wert zurückgeben (Methoden void), ist es akzeptabel, aber nicht erforderlich, mindestens eine Anweisung returnohne Rückgabewert und keine einzige Anweisung returnmit einem Rückgabewert zu haben. Schauen wir uns das anhand der folgenden Beispiele an:
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);
}

// Метод выведет в консоль наибольшее Bedeutung из массива
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);
}

Etiketten

breakBevor ich mir die Operatoren „ and“ und „and“ anschaue continue, möchte ich über Labels in Java sprechen. Dies ist wichtig, da in manchen Situationen die Operatoren breakund continuein Verbindung mit Beschriftungen verwendet werden. Versuchen Sie jedoch zunächst, die Frage zu beantworten, ob dieser Code kompiliert werden kann:
public static void main(String[] args) {
    https://www.google.com/
    System.out.println("Interesting...");
}
Ein Label ist ein benannter Codeabschnitt. Das Etikett selbst bietet keine Funktionalität. Dabei handelt es sich um so etwas wie ein Lesezeichen im Code, das der Programmierer später verwenden möchte. Ein Label im Code wird ganz einfach definiert – durch einen Namen und einen Doppelpunkt. Zum Beispiel:
  • labelName:
  • outerLoop:
  • printing:
  • anyWordYouLike:
Und so sehen die Beschriftungen im Java-Code aus:
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();
    }
}
Die Ausgabe der Methode mainsieht wie folgt aus:
Таблица Умножения
   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
Im obigen Beispiel sind definePrintName, loop1:und loop2:Beschriftungen. loop1:und loop2:„markieren“ Sie zwei Zyklen – extern und intern. Wir werden uns im folgenden Abschnitt mit der Verwendung von Labels befassen. Wenn Sie in der Zwischenzeit die Frage, ob dieser Code kompiliert werden kann, mit „Nein“ beantwortet haben:
public static void main(String[] args) {
      https://www.google.com/
      System.out.println("Interesting...");
  }
Versuchen Sie erneut, die Frage mit der IDE zu beantworten.

brechen

Der Operator breakwird in zwei Fällen verwendet:
  1. Um einen beliebigen Ausführungszweig in einem Switch-Case-Block abzuschließen.
  2. Um die Ausführung einer Schleife zu unterbrechen.
Der Operator hat zwei Formen: mit Markierungen (Etikett) und ohne. Die Syntax für beide Formen lautet:
break labelName; // Синтаксис оператора с меткой
break; // Синтаксис оператора без метки
In Schaltergehäuseblöcken breakwird der Operator ohne Beschriftung verwendet:
public static void main(String[] args) {
    int dayOfWeekInt = 4;
    String dayOfWeek;
    switch (dayOfWeekInt) {
        case 1:
            dayOfWeek = "Montag";
            break;
        case 2:
            dayOfWeek = "Dienstag";
            break;
        case 3:
            dayOfWeek = "Mittwoch";
            break;
        case 4:
            dayOfWeek = "Donnerstag";
            break;
        case 5:
            dayOfWeek = "Freitag";
            break;
        case 6:
            dayOfWeek = "Samstag";
            break;
        case 7:
            dayOfWeek = "Sonntag";
            break;
        default:
            dayOfWeek = "Неизвестный день";
            break;
    }

    System.out.println("Сегодня " + dayOfWeek);
}
In Schleifen wird eine Anweisung breakverwendet, um weitere Iterationen zu unterbrechen, nachdem bestimmte Bedingungen erfüllt sind. Dies ist häufig der Fall, wenn Sie ein Array oder eine Sammlung von Elementen durchlaufen und darin ein Element finden müssen, das die erforderlichen Bedingungen erfüllt. Betrachten wir dieses Beispiel. Wir haben ein Array und müssen feststellen, ob das Array negative Elemente enthält:
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, потому что
        мы выяснoder то, что нас интересовало,
        и дальнейший перебор элементов не имеет смысла.
        */
       arrayHasNegativeElements = true;
       break;
   }
}
Schauen wir uns dasselbe Beispiel mit verschiedenen Schleifen an. Zyklus 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;
        }
    }
}
Zyklus 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 ++;
    }
}
Zyklus 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);
}
Ein weiteres Beispiel für eine Anweisung breakin Schleifen ist das Unterbrechen einer Endlosschleife, wenn bestimmte Bedingungen erfüllt sind. Hier ist ein Beispiel für ein Programm, das die vom Benutzer eingegebene Zeile anzeigt, bis der Benutzer das Wort „Stopp“ eingibt:
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);
    }
}
Betrachten wir die Verwendung des Operators breakzusammen mit einer Bezeichnung. Ein Interrupt mit Label wird in Fällen mit mehreren, zudem ineinander verschachtelten Zyklen verwendet. In diesem Fall wird einer der Zyklen (oder alle Zyklen) mit einem Label gekennzeichnet. Anschließend breakunterbricht der Bediener zusammen mit der Angabe des Etiketts den gewünschten Zyklus. Betrachten wir ein Beispiel, in dem wir verstehen müssen, ob ein negatives Element vorhanden ist, jedoch nicht im Array, sondern in der 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;
               }
           }
       }
}

Kontinuität

Der Operator continuehat auch zwei Formen – mit und ohne Etikett:
continue; // форма оператора без метки
continue labelName; // форма оператора с меткой
Im Gegensatz zum Operator break, der alle verbleibenden Iterationen der Schleife unterbricht, continueunterbricht der Operator die aktuelle Iteration und veranlasst den Start der nächsten. Sprungoperatoren in Java - 2Dies kann nützlich sein, wenn Sie einige Operationen an Elementen ausführen müssen, die bestimmte Bedingungen erfüllen. Nehmen wir an, wir haben eine Zeichenfolge und möchten die Anzahl der Wörter zählen, die mit dem Buchstaben „m“ beginnen:
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);
}
Nach der Ausführung dieses Codes erscheint in der Konsole folgende Ausgabe:
Кол-во слов, начинающихся с буквы М в предложении: [Мама мыла раму] = 2
Der Operator continuewird zusammen mit der Bezeichnung auch beim Durchlaufen von Elementen verwendet. Stellen wir uns eine Matrix vor, in der wir die Anzahl der Zeilen mit negativen Elementen zählen müssen:
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);
}
Die Ausgabe dieses Codes wird sein:
Rows With Negative Elements Count = 3
Es ist erwähnenswert, dass die Operatoren break, continueund returnauf unterschiedliche Weise verwendet werden können, um die gleiche Funktionalität zu erreichen. Sie können also das letzte Beispiel umschreiben und Folgendes continueverwenden 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);
}
Der Unterschied zwischen breakund continuemit einem Label besteht darin, dass breakdie Iterationen der Schleife, in die es geschrieben wird, abgeschlossen werden. Und continuemit einer Beschriftung wird die aktuelle Iteration des mit der Beschriftung markierten Zyklus übersprungen. In manchen Situationen können Sie das eine durch das andere ersetzen, und die gesamte Funktionalität des Programms bleibt gleich. Wir werden weiter unten darüber sprechen, was am besten zu wählen ist (Spoiler: Lesbarkeit des Codes). Der Operator kann nicht nur durch eine Bezeichnung, sondern auch durch breakersetzt werden . Kurz zuvor müssen Sie die verschachtelte Schleife in eine separate Methode verschieben: continuereturn
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;
}
Es gibt viele Möglichkeiten, dasselbe zu schreiben. Welches soll ich wählen? Bei der industriellen Programmierung wird diese Frage durch die einfache Verständlichkeit des Codes entschieden. Je einfacher es geschrieben ist, desto besser. Je mehr Schleifen verschachtelt sind, desto schwieriger ist es, den Code wahrzunehmen. breakVor allem, wenn die Schleifen mit unterschiedlichen Labels gekennzeichnet sind, die in Interrupts und Fortsetzungen ( und ) verwendet werden continue. Wenn es möglich ist, keine Tags zu verwenden, ist es besser, dies zu tun. Ansonsten versuchen Sie, so klar und schön wie möglich zu schreiben.

gehe zu

In einigen Programmiersprachen gibt es einen Operator goto. Typischerweise leitet es die Codeausführung zu einem Teil des Programms um, der mit einem Label gekennzeichnet ist. Aber in Java gotokönnte man sagen, dass es so ist und nicht. Lass es uns herausfinden. Die Liste der Schlüsselwörter in Java enthält das Wort goto. Diese Anweisung ist jedoch als nicht verwendet gekennzeichnet. Tatsache ist, dass James Gosling, der Schöpfer der Java-Sprache, ursprünglich die Unterstützung für den Operator in die JVM aufgenommen hat goto. Diese Funktion wurde jedoch später gestrichen. Einer der Gründe dafür ist, dass Codeblöcke, die den Operator enthielten, gotonicht so gut lesbar waren wie Codeblöcke, die dieselben Funktionen ausführten, jedoch ohne goto, aber mit alternativen Ansätzen ( break, continue, Platzieren des Codeblocks in Methoden). Es gab tatsächlich noch andere, wie zum Beispiel:
  • Schwierigkeiten beim Lesen und Verstehen von Code, der Operatoren enthält goto;
  • was die Codeoptimierung für den Compiler erschwert (und manchmal sogar unmöglich macht);
  • Dadurch erhöht sich die Wahrscheinlichkeit, dass subtile Fehler im Code entstehen.
Für viele ist es kein Geheimnis, dass der Operator in manchen Programmiersprachen gotorecht erfolgreich funktioniert. Allerdings vermeiden Programmierer die Verwendung. Die Gründe dafür können Sie in einem Artikel auf Habré nachlesen . Aber warum sollte man es dann gotoauf der Liste der reservierten Wörter belassen? Ganz einfach: für die Zukunft. Wenn beispielsweise im Java-Code von Entwicklern auf der ganzen Welt Variablen, Methoden oder Klassen aufgerufen werden und gotodiese Anweisung in einer zukünftigen Java-Version zurückgegeben wird, wird der gesamte alte Code beschädigt. Um ein solches Szenario zu vermeiden, gotoverbleibt es in der Liste der Java-Schlüsselwörter, verfügt jedoch über keine Funktionalität. Vielleicht gotowird er eines Tages in unsere Reihen zurückkehren, aber die Wahrscheinlichkeit dafür ist gering.

Ergebnisse

Wir haben uns verschiedene Sprungoperatoren in Java angesehen:
  1. return– Abschluss der Methode, Rückgabe eines Werts von der Methode.
    • mit einem Rückgabewert: Methoden, die Werte zurückgeben;
    • kein Rückgabewert: voidMethoden.
  2. break— Zyklenunterbrechung, Schaltkastensperre.
    • mit Tags: Zyklen verschiedener Verschachtelungen;
    • ohne Beschriftung: Schaltergehäusezweige des Blocks; Unterbricht die Schleife, in der es aufgerufen wurde.
  3. continue.
    • mit Tags: Zyklen verschiedener Verschachtelungen;
    • ohne Labels: Fortsetzung der Schleife, in der sie aufgerufen wurde.
  4. goto.
    • steht in der Liste der Schlüsselwörter, wird aber nicht verwendet.
Die Schlussfolgerung aus all dem ist einfach: Es ist besser, den einfachsten Ansätzen den Vorzug zu geben, die die Lesbarkeit des Codes erleichtern. Versuchen Sie, Ihren Code nicht mit ineinander verschachtelten mehrstufigen Schleifen mit einer Fülle von Markierungen, Unterbrechungen und Fortsetzungen zu überladen.
Kommentare
TO VIEW ALL COMMENTS OR TO MAKE A COMMENT,
GO TO FULL VERSION