JavaRush /Java Blog /Random-IT /Operatori di salto in Java

Operatori di salto in Java

Pubblicato nel gruppo Random-IT
Ciao! Oggi parleremo degli operatori di salto in Java:
  • return
  • break
  • continue
  • goto
Per prima cosa definiamo di cosa si tratta realmente. Come sai, in una situazione normale, un programma viene eseguito in modo lineare, dall'alto verso il basso, comando per comando. Il flusso lineare di un programma può essere modificato dalle cosiddette strutture di controllo: ad esempio rami ( if) e cicli ( for, whileecc.). Oltre ai costrutti di controllo, l'esecuzione lineare di un programma può essere modificata mediante istruzioni di salto. Sono responsabili del reindirizzamento dell'esecuzione del programma in una posizione specifica, che dipende dal contesto e dall'istruzione specifica. Operatori di salto in Java - 1Diamo uno sguardo più da vicino a ciascuno dei quattro operatori.

ritorno

È con questo operatore che i nuovi arrivati ​​spesso acquisiscono familiarità per primi. L'istruzione returntermina il metodo in cui è stata chiamata e l'esecuzione del programma ritorna alla posizione da cui è stato chiamato il metodo. Ha returndue forme:
  1. Termina immediatamente l'esecuzione del metodo.
  2. Termina immediatamente l'esecuzione del metodo e restituisce un valore come risultato del metodo.
La sintassi per entrambe le forme è:
return;
return value; // где value — некоторое возвращаемое meaning
I metodi che restituiscono un valore devono avere almeno un operatore returncon un valore restituito di cui è garantito che venga chiamato e non devono avere un operatore returnsenza un valore restituito. Diamo un'occhiata agli esempi seguenti:
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;
    }
}
Nei metodi che non restituiscono un valore (metodi void), è accettabile, ma non obbligatorio, avere almeno un'istruzione returnsenza valore restituito e non una singola istruzione returncon un valore restituito. Diamo un'occhiata a questo con gli esempi seguenti:
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);
}

etichette

Prima di esaminare gli operatori breakand continue, vorrei parlare delle etichette in Java. Questo è importante perché in alcune situazioni gli operatori breake continuevengono utilizzati insieme alle etichette. Ma prima, prova a rispondere alla domanda se questo codice verrà compilato:
public static void main(String[] args) {
    https://www.google.com/
    System.out.println("Interesting...");
}
Un'etichetta è un pezzo di codice con nome. L'etichetta stessa non fornisce alcuna funzionalità. Questo è qualcosa come un segnalibro nel codice che il programmatore intende utilizzare in seguito. Un'etichetta nel codice viene definita in modo molto semplice: tramite un nome e due punti. Per esempio:
  • labelName:
  • outerLoop:
  • printing:
  • anyWordYouLike:
Ed ecco come appaiono le etichette all'interno del codice 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();
    }
}
L'output del metodo mainsarà il seguente:
Таблица Умножения
   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
Nell'esempio sopra definePrintName, loop1:e loop2:sono etichette. loop1:e loop2:“segnare” due cicli: esterno e interno. Vedremo l'utilizzo delle etichette nella sezione seguente. Nel frattempo, se hai risposto "no" alla domanda se questo codice verrà compilato:
public static void main(String[] args) {
      https://www.google.com/
      System.out.println("Interesting...");
  }
Prova a rispondere di nuovo, utilizzando l'IDE.

rottura

L'operatore breakviene utilizzato in due casi:
  1. Per completare qualsiasi ramo di esecuzione in un blocco switch-case.
  2. Per interrompere l'esecuzione di un loop.
L'operatore ha due forme: con marcature (etichetta) e senza. La sintassi per entrambe le forme è:
break labelName; // Синтаксис оператора с меткой
break; // Синтаксис оператора без метки
Nei blocchi di interruttori l'operatore breakviene utilizzato senza etichette:
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);
}
Nei cicli, un'istruzione breakviene utilizzata per interrompere ulteriori iterazioni dopo che sono soddisfatte determinate condizioni. Questo può essere spesso trovato quando è necessario scorrere un array o una raccolta di elementi e trovare qualche elemento al suo interno che soddisfi le condizioni necessarie. Consideriamo questo esempio. Abbiamo un array e dobbiamo determinare se l'array contiene elementi negativi:
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;
   }
}
Diamo un'occhiata allo stesso esempio con loop diversi. 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);
}
Un altro esempio di istruzione breakin loop è interrompere un loop infinito quando vengono soddisfatte determinate condizioni. Ecco un esempio di un programma che visualizza la riga inserita dall'utente finché l'utente non inserisce la parola "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);
    }
}
Consideriamo l'utilizzo dell'operatore breakinsieme a un'etichetta. Un'interruzione con etichetta viene utilizzata nei casi con più cicli, per di più annidati uno nell'altro. In questo caso uno dei cicli (o tutti i cicli) è contrassegnato da un'etichetta. Successivamente l'operatore, breakcontestualmente all'indicazione dell'etichetta, interrompe il ciclo desiderato. Consideriamo un esempio in cui dobbiamo capire se c'è un elemento negativo, ma non nell'array, ma nella 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'operatore continueha anche due moduli: con e senza etichetta:
continue; // форма оператора без метки
continue labelName; // форма оператора с меткой
A differenza dell'operatore break, che interrompe tutte le restanti iterazioni del ciclo, l'operatore continueinterrompe l'iterazione corrente e fa iniziare quella successiva. Operatori di salto in Java - 2Ciò può essere utile se è necessario eseguire alcune operazioni su elementi che soddisfano determinate condizioni. Diciamo di avere una stringa e di voler contare il numero di parole che iniziano con la lettera "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);
}
Dopo aver eseguito questo codice ci sarà il seguente output nella console:
Кол-во слов, начинающихся с буквы М в предложении: [Мама мыла раму] = 2
L'operatore continueinsieme all'etichetta viene utilizzato anche durante l'iterazione sugli elementi. Immaginiamo una matrice in cui dobbiamo contare il numero di righe con elementi negativi:
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);
}
L'output di questo codice sarà:
Rows With Negative Elements Count = 3
Vale la pena dire che gli operatori break, continuee returnpossono essere utilizzati in modi diversi per ottenere la stessa funzionalità. Quindi, puoi riscrivere l'ultimo esempio e continueutilizzare 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 differenza tra breake continuecon un'etichetta è ciò che breakcompleta le iterazioni del ciclo in cui è scritta. E continuecon un'etichetta, salta l'iterazione corrente del ciclo contrassegnato con l'etichetta. In alcune situazioni, puoi sostituirne uno con l'altro e tutto nella funzionalità del programma rimarrà lo stesso. Parleremo di cosa è meglio scegliere (spoiler: leggibilità del codice) di seguito. L'operatore breakpuò essere sostituito non solo con continueun'etichetta, ma anche con return. Poco prima è necessario spostare il ciclo annidato in un metodo separato:
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;
}
Molti modi per scrivere la stessa cosa. Quale scegliere? Nella programmazione industriale, questo problema è deciso dalla facilità di comprensione del codice. Più è scritto in modo semplice, meglio è. Più cicli sono annidati, più difficile è percepire il codice. Soprattutto se i loop sono contrassegnati con etichette diverse, che vengono utilizzate nelle interruzioni e nelle continuazioni ( breake continue). Se è possibile non utilizzare i tag è meglio farlo. Altrimenti, prova a scrivere nel modo più chiaro e bello possibile.

vai a

In alcuni linguaggi di programmazione è presente un operatore goto. In genere reindirizza l'esecuzione del codice ad alcune parti del programma contrassegnate da un'etichetta. Ma in Java goto, si potrebbe dire, lo è e non lo è. Scopriamolo. L'elenco delle parole chiave in Java include la parola goto. Tuttavia, questa istruzione è contrassegnata come non utilizzata. Il fatto è che James Gosling, il creatore del linguaggio Java, inizialmente incluse il supporto per l'operatore nella JVM goto. Tuttavia, questa funzionalità è stata successivamente eliminata. Uno dei motivi è che i blocchi di codice contenenti l'operatore gotonon erano leggibili come i blocchi di codice che eseguivano le stesse funzioni ma senza goto, ma con approcci alternativi ( break, continue, inserendo il blocco di codice nei metodi). Ce n'erano infatti altri, come:
  • difficoltà nella lettura e comprensione del codice che contiene operatori goto;
  • complicare l'ottimizzazione del codice per il compilatore (e talvolta addirittura impossibile);
  • aumentando la probabilità di creare errori sottili nel codice.
Non è un segreto per molti che in alcuni linguaggi di programmazione l'operatore gotofunzioni con successo. Tuttavia, i programmatori evitano di usarlo. Puoi leggere le ragioni di ciò in un articolo su Habré . Ma allora perché lasciarlo gotonell'elenco delle parole riservate? È semplice: per il futuro. Se, ad esempio, vengono chiamate variabili, metodi o classi nel codice Java degli sviluppatori di tutto il mondo goto, se questa istruzione viene restituita in una futura versione di Java, tutto il vecchio codice si romperà. Per evitare uno scenario del genere, gotorimane nell'elenco delle parole chiave Java, ma non presenta alcuna funzionalità. Forse un giorno gototornerà tra noi, ma la probabilità che ciò accada è bassa.

Risultati

Abbiamo esaminato vari operatori di salto in Java:
  1. return— completamento del metodo, restituendo un valore dal metodo.
    • con un valore restituito: metodi che restituiscono valori;
    • nessun valore restituito: voidmetodi.
  2. break— interruzione dei cicli, blocco dei quadri.
    • con tag: cicli di annidamento vario;
    • senza etichette: rami del quadro del blocco; interrompendo il ciclo in cui è stato chiamato.
  3. continue.
    • con tag: cicli di annidamento vario;
    • senza etichette: continuazione del ciclo in cui è stato chiamato.
  4. goto.
    • è nell'elenco delle parole chiave, ma non viene utilizzato.
La conclusione di tutto ciò è semplice: è meglio dare la preferenza agli approcci più semplici che facilitano la lettura del codice. Cerca di non sovraccaricare il tuo codice con cicli multilivello annidati uno dentro l'altro con abbondanza di segni, interruzioni e continuazioni.
Commenti
TO VIEW ALL COMMENTS OR TO MAKE A COMMENT,
GO TO FULL VERSION