שלום! היום נדבר על מפעילי קפיצה ב-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;
}
}
בשיטות שאינן מחזירות ערך (שיטות 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
ו 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
משמש בשני מקרים:
- להשלמת כל ענף ביצוע בבלוק מתג-מקרה.
- כדי להפריע לביצוע של לולאה.
break labelName; // Синтаксис оператора с меткой
break; // Синтаксис оператора без метки
בבלוק-מקרה מתג, המפעיל break
משמש ללא תוויות:
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
בלולאות היא לקטוע לולאה אינסופית כאשר מגיעים לתנאים מסוימים. הנה דוגמה לתוכנית המציגה את השורה שהזין המשתמש עד שהמשתמש יזין את המילה "עצור":
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
. בדרך כלל זה מפנה מחדש את ביצוע הקוד לחלק כלשהו של התוכנית המסומן בתווית. אבל בג'אווה goto
, אפשר לומר, זה כן וזה לא. בוא נבין את זה. רשימת מילות המפתח ב-Java כוללת את המילה goto
. עם זאת, הצהרה זו מסומנת כלא בשימוש. העובדה היא שג'יימס גוסלינג, היוצר של שפת ג'אווה, כלל בתחילה תמיכה במפעיל ב-JVM goto
. עם זאת, תכונה זו הופסקה מאוחר יותר. אחת הסיבות היא שבלוקים של קוד המכילים את האופרטור goto
לא היו קריאים כמו בלוקים של קוד שביצעו את אותן פונקציות אך ללא goto
, אלא עם גישות חלופיות ( break
, continue
, הצבת בלוק הקוד בשיטות). היו, למעשה, אחרים, כגון:
- קושי בקריאה והבנת קוד המכיל אופרטורים
goto
; - מסבך אופטימיזציה של קוד עבור המהדר (ולפעמים אפילו בלתי אפשרי);
- הגדלת הסבירות ליצירת שגיאות עדינות בקוד.
goto
מתפקד בצורה מוצלחת למדי. עם זאת, מתכנתים נמנעים משימוש בו. אתה יכול לקרוא על הסיבות לכך במאמר אחד על Habré . אבל למה אם כן להשאיר אותו goto
ברשימת המילים השמורות? זה פשוט: לעתיד. אם, למשל, משתנים, מתודות או מחלקות נקראים , בקוד Java של מפתחים בכל העולם goto
, אם ההצהרה הזו תוחזר בגרסה עתידית של Java, כל הקוד הישן ישבר. כדי להימנע מתרחיש כזה, goto
הוא נשאר ברשימת מילות המפתח של Java, אך אינו נושא פונקציונליות כלשהי. אולי מתישהו goto
הוא יחזור לשורותינו, אבל הסבירות לכך נמוכה.
תוצאות
בדקנו מפעילי קפיצה שונים ב-Java:return
- השלמת השיטה, החזרת ערך מהשיטה.- עם ערך החזרה: שיטות המחזירות ערכים;
- אין ערך החזרה:
void
שיטות.
break
- הפרעה של מחזורים, בלוקים של מתגים.- עם תגיות: מחזורי קינון שונים;
- ללא תוויות: ענפי מתג של הבלוק; קוטע את הלולאה שבה נקראה.
continue
.- עם תגיות: מחזורי קינון שונים;
- ללא תוויות: המשך הלולאה שבה היא נקראה.
goto
.- נמצא ברשימת מילות המפתח, אך אינו בשימוש.
GO TO FULL VERSION