JavaRush /Blog Java /Random-FR /Opérateurs de saut en Java

Opérateurs de saut en Java

Publié dans le groupe Random-FR
Bonjour! Aujourd'hui, nous allons parler des opérateurs de saut en Java :
  • return
  • break
  • continue
  • goto
Tout d’abord, définissons ce dont il s’agit réellement. Comme vous le savez, dans une situation normale, un programme est exécuté de manière linéaire - de haut en bas, commande par commande. Le déroulement linéaire d'un programme peut être modifié par ce que l'on appelle des structures de contrôle : par exemple, des branches ( if) et des boucles ( for, whileetc.). En plus des constructions de contrôle, l'exécution linéaire d'un programme peut être modifiée par des instructions de saut. Ils sont chargés de rediriger l'exécution du programme vers un emplacement spécifique, qui dépend du contexte et de l'instruction spécifique. Opérateurs de saut en Java - 1Examinons de plus près chacun des quatre opérateurs.

retour

C'est cet opérateur que les nouveaux arrivants connaissent le plus souvent en premier. L'instruction returntermine la méthode dans laquelle elle a été appelée et l'exécution du programme revient à l'emplacement à partir duquel la méthode a été appelée. Il returna deux formes :
  1. Termine immédiatement l'exécution de la méthode.
  2. Termine immédiatement l'exécution de la méthode et renvoie une valeur comme résultat de la méthode.
La syntaxe des deux formulaires est la suivante :
return;
return value; // где value — некоторое возвращаемое meaning
Les méthodes qui renvoient une valeur doivent avoir au moins un opérateur returnavec une valeur de retour dont l'appel est garanti, et ne doivent pas avoir d'opérateur returnsans valeur de retour. Regardons les exemples ci-dessous :
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;
    }
}
Dans les méthodes qui ne renvoient pas de valeur (methods void), il est acceptable, mais pas obligatoire, d'avoir au moins une instruction returnsans valeur de retour, et pas une seule instruction returnavec une valeur de retour. Regardons cela avec les exemples ci-dessous :
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);
}

Étiquettes

Avant de regarder les opérateurs breaket continue, je voudrais parler des étiquettes en Java. Ceci est important car dans certaines situations, breakles opérateurs continuesont utilisés conjointement avec les étiquettes. Mais d’abord, essayez de répondre à la question de savoir si ce code sera compilé :
public static void main(String[] args) {
    https://www.google.com/
    System.out.println("Interesting...");
}
Une étiquette est un morceau de code nommé. L'étiquette elle-même ne fournit aucune fonctionnalité. C'est quelque chose comme un signet dans le code que le programmeur a l'intention d'utiliser plus tard. Une étiquette dans le code est définie assez simplement - via un nom et deux points. Par exemple:
  • labelName:
  • outerLoop:
  • printing:
  • anyWordYouLike:
Et voici à quoi ressemblent les étiquettes dans le code Java :
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();
    }
}
Le résultat de la méthode mainsera le suivant :
Таблица Умножения
   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
Dans l'exemple ci-dessus definePrintName, loop1:et loop2:sont des étiquettes. loop1:et loop2:"marquer" deux cycles - externe et interne. Nous examinerons l'utilisation des étiquettes dans la section ci-dessous. En attendant, si vous avez répondu « non » à la question de savoir si ce code sera compilé :
public static void main(String[] args) {
      https://www.google.com/
      System.out.println("Interesting...");
  }
Essayez d'y répondre à nouveau en utilisant l'IDE.

casser

L'opérateur breakest utilisé dans deux cas :
  1. Pour terminer n’importe quelle branche d’exécution dans un bloc switch-case.
  2. Pour interrompre l'exécution d'une boucle.
L'opérateur dispose de deux formulaires : avec marquages ​​(étiquette) et sans. La syntaxe des deux formulaires est la suivante :
break labelName; // Синтаксис оператора с меткой
break; // Синтаксис оператора без метки
Dans les blocs de commutation, l'opérateur breakest utilisé sans étiquettes :
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);
}
Dans les boucles, une instruction breakest utilisée pour interrompre d’autres itérations une fois que certaines conditions sont remplies. Cela peut souvent se produire lorsque vous devez parcourir un tableau ou une collection d'éléments et y trouver un élément qui satisfait aux conditions nécessaires. Considérons cet exemple. Nous avons un tableau et nous devons déterminer si le tableau contient des éléments négatifs :
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;
   }
}
Regardons le même exemple avec différentes boucles. Faire du vélo 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;
        }
    }
}
Faire du vélo 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 ++;
    }
}
Faire du vélo 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);
}
Un autre exemple d'instruction breaken boucle consiste à interrompre une boucle infinie lorsque certaines conditions sont remplies. Voici un exemple de programme qui affiche la ligne saisie par l'utilisateur jusqu'à ce que l'utilisateur saisisse le mot « 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);
    }
}
Considérons l'utilisation de l'opérateur breakavec une étiquette. Une interruption avec une étiquette est utilisée dans les cas comportant plusieurs cycles, de plus, imbriqués les uns dans les autres. Dans ce cas, l'un des cycles (ou tous les cycles) est marqué d'une étiquette. Ensuite, l'opérateur, breaken indiquant l'étiquette, interrompt le cycle souhaité. Considérons un exemple dans lequel nous devons comprendre s'il y a un élément négatif, mais pas dans le tableau, mais dans la matrice :
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;
               }
           }
       }
}

continuité

L'opérateur continuedispose également de deux formulaires - avec et sans étiquette :
continue; // форма оператора без метки
continue labelName; // форма оператора с меткой
Contrairement à l'opérateur break, qui interrompt toutes les itérations restantes de la boucle, l'opérateur continueinterrompt l'itération en cours et provoque le démarrage de la suivante. Opérateurs de saut en Java - 2Cela peut être utile si vous devez effectuer certaines opérations sur des éléments qui satisfont certaines conditions. Disons que nous avons une chaîne et que nous voulons compter le nombre de mots commençant par la lettre « 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);
}
Après avoir exécuté ce code, la sortie suivante apparaîtra dans la console :
Кол-во слов, начинающихся с буквы М в предложении: [Мама мыла раму] = 2
L'opérateur continueainsi que l'étiquette sont également utilisés lors de l'itération sur des éléments. Imaginons une matrice dans laquelle nous devons compter le nombre de lignes avec des éléments négatifs :
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);
}
Le résultat de ce code sera :
Rows With Negative Elements Count = 3
Il faut dire que les opérateurs break, continueet returnpeuvent être utilisés de différentes manières pour obtenir la même fonctionnalité. Ainsi, vous pouvez réécrire le dernier exemple et continueutiliserbreak :
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 différence entre breaket continueavec une étiquette est ce qui breakcomplète les itérations de la boucle dans laquelle elle est écrite. Et continueavec une étiquette, saute l'itération en cours du cycle marqué par l'étiquette. Dans certaines situations, vous pouvez remplacer l'un par l'autre et toutes les fonctionnalités du programme resteront les mêmes. Nous parlerons ci-dessous de ce qu’il est préférable de choisir (spoiler : lisibilité du code). L'opérateur breakpeut être remplacé non seulement par continuepar une étiquette, mais également par return. Juste avant cela, vous devez déplacer la boucle imbriquée dans une méthode distincte :
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;
}
Il y a plein de façons d'écrire la même chose. Lequel choisir ? En programmation industrielle, cette question est résolue par la facilité de compréhension du code. Plus c’est écrit simplement, mieux c’est. Plus il y a de boucles imbriquées, plus il est difficile de percevoir le code. Surtout si les boucles sont marquées avec des étiquettes différentes, qui sont utilisées dans les interruptions et les continuations ( breaket continue). S'il est possible de ne pas utiliser de balises, il vaut mieux le faire. Sinon, essayez d’écrire aussi clairement et joliment que possible.

aller à

Dans certains langages de programmation, il existe un opérateur goto. Généralement, il redirige l'exécution du code vers une partie du programme marquée d'une étiquette. Mais en Java goto, pourrait-on dire, c'est le cas et ce n'est pas le cas. Voyons cela. La liste des mots-clés en Java inclut le mot goto. Cependant, cette déclaration est marquée comme non utilisée. Le fait est que James Gosling, le créateur du langage Java, a initialement inclus la prise en charge de l'opérateur dans la JVM goto. Cependant, cette fonctionnalité a été supprimée par la suite. L'une des raisons est que les blocs de code contenant l'opérateur goton'étaient pas aussi lisibles que les blocs de code qui remplissaient les mêmes fonctions mais sans goto, mais avec des approches alternatives ( break, continue, en plaçant le bloc de code dans des méthodes). Il y en avait en effet d’autres, comme :
  • difficulté à lire et à comprendre le code contenant des opérateurs goto;
  • compliquer l'optimisation du code pour le compilateur (et parfois même impossible) ;
  • augmentant la probabilité de créer des erreurs subtiles dans le code.
Ce n'est un secret pour beaucoup que dans certains langages de programmation, l'opérateur gotofonctionne avec beaucoup de succès. Cependant, les programmeurs évitent de l’utiliser. Vous pouvez en découvrir les raisons dans un article sur Habré . Mais pourquoi alors le laisser gotosur la liste des mots réservés ? C'est simple : pour l'avenir. Si, par exemple, des variables, des méthodes ou des classes sont appelées dans le code Java des développeurs du monde entier goto, si cette instruction est renvoyée dans une future version de Java, tout l'ancien code sera interrompu. Pour éviter un tel scénario, gotoil reste dans la liste des mots-clés Java, mais n'emporte aucune fonctionnalité. Peut-être qu'un jour gotoil reviendra dans nos rangs, mais la probabilité que cela se produise est faible.

Résultats

Nous avons examiné différents opérateurs de saut en Java :
  1. return— achèvement de la méthode, renvoyant une valeur de la méthode.
    • avec une valeur de retour : méthodes qui renvoient des valeurs ;
    • aucune valeur de retour : voidméthodes.
  2. break— interruption des cycles, blocs de boîtiers de commutation.
    • avec balises : cycles d'imbrications diverses ;
    • sans étiquettes : branches d'interrupteur du bloc ; interrompant la boucle dans laquelle il a été appelé.
  3. continue.
    • avec balises : cycles d'imbrications diverses ;
    • sans étiquettes : continuation de la boucle dans laquelle il a été appelé.
  4. goto.
    • est dans la liste des mots-clés, mais n'est pas utilisé.
La conclusion de tout cela est simple : il vaut mieux privilégier les approches les plus simples qui facilitent la lecture du code. Essayez de ne pas surcharger votre code avec des boucles à plusieurs niveaux imbriquées les unes dans les autres avec une abondance de marques, d'interruptions et de continuations.
Commentaires
TO VIEW ALL COMMENTS OR TO MAKE A COMMENT,
GO TO FULL VERSION