你好!今天我們來談談Java中的跳躍運算子:
return
break
continue
goto
if
)和循環(for
等while
)。除了控制結構之外,程式的線性執行還可以透過跳躍語句來修改。它們負責將程式執行重定向到特定位置,這取決於上下文和特定語句。讓我們仔細看看這四個運算符中的每一個。
返回
新人最先熟悉的就是這個操作符。該語句return
終止呼叫它的方法,程式執行返回到呼叫該方法的位置。它return
有兩種形式:
- 立即結束該方法的執行。
- 立即結束該方法的執行並傳回一些值作為該方法的結果。
return;
return value; // где value — некоторое возвращаемое meaning
傳回值的方法必須至少有一個return
有回傳值的運算子保證被調用,並且不能有return
沒有回傳值的運算子。讓我們看看下面的例子:
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;
}
}
在不傳回值的方法 (methods void
) 中,至少有一條不帶回傳值的語句是可以接受的,但不是必需的return
,也不能有一條return
帶有回傳值的語句。讓我們透過下面的例子來看:
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);
}
標籤
在討論break
and運算子之前continue
,我想先談談 Java 中的標籤。這很重要,因為在某些情況下,break
和運算子continue
與標籤結合使用。但首先,試著回答此程式碼是否可以編譯的問題:
public static void main(String[] args) {
https://www.google.com/
System.out.println("Interesting...");
}
標籤是一段命名的程式碼。標籤本身不提供任何功能。這就像程式設計師稍後打算使用的程式碼中的書籤。程式碼中的標籤定義非常簡單 - 透過名稱和冒號。例如:
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();
}
}
此方法的輸出main
如下:
Таблица Умножения
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
在上面的範例中definePrintName
,loop1:
和loop2:
是標籤。 loop1:
並loop2:
「標記」兩個週期—外部和內部。我們將在下面的部分中討論如何使用標籤。同時,如果您對該程式碼是否可以編譯的問題回答“否”:
public static void main(String[] args) {
https://www.google.com/
System.out.println("Interesting...");
}
嘗試使用 IDE 再次回答該問題。
休息
此運算符break
在兩種情況下使用:
- 完成 switch-case 區塊中的任何執行分支。
- 中斷循環的執行。
break labelName; // Синтаксис оператора с меткой
break; // Синтаксис оператора без метки
break
在 switch-case 區塊中,使用的 運算子不帶標籤:
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);
}
在迴圈中,語句break
用於在滿足某些條件後中斷進一步的迭代。當您需要迭代數組或元素集並在其中查找某些滿足必要條件的元素時,通常會發現這種情況。讓我們考慮一下這個例子。我們有一個數組,我們需要判斷該數組是否包含負數元素:
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;
}
}
讓我們看一下具有不同循環的相同範例。循環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;
}
}
}
循環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 ++;
}
}
循環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);
}
循環中語句的另一個範例break
是當滿足某些條件時中斷無限迴圈。下面是一個程式範例,它顯示使用者輸入的行,直到使用者輸入單字「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);
}
}
讓我們考慮將運算符break
與標籤一起使用。帶標籤的中斷用於具有多個週期的情況,而且,一個週期嵌套在另一個週期內。在這種情況下,其中一個循環(或所有循環)都標有標籤。接下來,操作員break
在指示標籤的同時中斷所需的循環。讓我們考慮一個範例,其中我們需要了解是否存在負元素,但不是在數組中,而是在矩陣中:
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;
}
}
}
}
連續性
此運算符continue
也有兩種形式 - 帶標籤和不帶標籤:
continue; // форма оператора без метки
continue labelName; // форма оператора с меткой
與中斷循環的所有剩餘迭代的運算子不同break
,運算子continue
會中斷當前迭代並導致下一個迭代開始。如果您需要對滿足某些條件的元素執行某些操作,這會很有用。假設我們有一個字串,我們想要計算以字母“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);
}
執行此程式碼後,控制台中將輸出以下內容:
Кол-во слов, начинающихся с буквы М в предложении: [Мама мыла раму] = 2
continue
迭代元素時也會使用 運算子和標籤。讓我們想像一個矩陣,其中我們需要計算具有負元素的行數:
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);
}
該程式碼的輸出將是:
Rows With Negative Elements Count = 3
值得一提的是,運算子break
,continue
和return
可以透過不同的方式使用來實現相同的功能。因此,您可以重寫最後一個範例並continue
使用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);
}
break
標籤和continue
標籤 之間的差異在於break
完成寫入標籤的循環的迭代。並continue
帶有標籤,跳過標有標籤的循環的當前迭代。在某些情況下,您可以將其中一個替換為另一個,並且程式功能中的所有內容都將保持不變。我們將在下面討論最好的選擇(劇透:程式碼可讀性)。運算子break
不僅可以用continue
標籤替換,還可以用 替換return
。在此之前,您需要將巢狀循環移至單獨的方法中:
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;
}
寫同樣的東西有很多種方法。選擇哪一個?在工業程式設計中,這個問題是由程式碼的難易度決定的。寫越簡單越好。嵌套循環越多,感知程式碼就越困難。特別是如果循環標有不同的標記,這些標記用於中斷和繼續(break
和continue
)。如果可以不使用標籤,最好還是使用。否則,盡量寫得清楚、漂亮。
去
在某些程式語言中存在運算符goto
。通常,它將程式碼執行重定向到標有標籤的程式的某個部分。但在 Java 中goto
,有人可能會說,它是,但又不是。讓我們弄清楚一下。 Java 中的關鍵字清單包括單字goto
。然而,該語句被標記為未使用。事實上,Java 語言的創建者 James Gosling 最初在 JVM 中包含了對運算子的支援goto
。不過這個功能後來被刪掉了。原因之一是包含運算子的程式碼區塊的goto
可讀性不如執行相同功能但沒有goto
,但採用替代方法(break
、continue
,將程式碼區塊放置在方法中)的程式碼區塊。事實上,還有其他一些,例如:
- 難以閱讀和理解包含運算符的程式碼
goto
; - 使編譯器的程式碼最佳化變得複雜(有時甚至是不可能的);
- 增加在程式碼中產生細微錯誤的可能性。
goto
功能相當成功,這已不是什麼秘密。然而,程式設計師避免使用它。您可以在Habré 的一篇文章中了解原因。但為什麼要把它留goto
在保留字清單中呢?很簡單:為了未來。例如,如果在世界各地開發人員的 Java 程式碼中呼叫變數、方法或類goto
,如果在 Java 的未來版本中傳回此語句,則所有舊程式碼都會崩潰。為了避免這種情況,goto
它保留在 Java 關鍵字清單中,但不帶有任何功能。也許有一天goto
他會回到我們的隊伍中,但這種可能性很低。
結果
我們已經研究了 Java 中的各種跳躍運算子:return
— 方法完成,從方法傳回一個值。- 有回傳值:有傳回值的方法;
- 無回傳值:
void
方法。
break
— 循環中斷、開關盒塊。- 帶標籤:各種嵌套的循環;
- 沒有標籤:區塊的 switch-case 分支;中斷呼叫它的循環。
continue
。- 帶標籤:各種嵌套的循環;
- 沒有標籤:呼叫它的循環的繼續。
goto
。- 位於關鍵字清單中,但未使用。
GO TO FULL VERSION