مرحبًا! سنتحدث اليوم عن عوامل القفز في 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
. ومع ذلك، تم وضع علامة على هذا البيان على أنه غير مستخدم. والحقيقة هي أن جيمس جوسلينج، منشئ لغة Java، قام في البداية بتضمين دعم المشغل في JVM goto
. ومع ذلك، تم قطع هذه الميزة في وقت لاحق. أحد الأسباب هو أن كتل التعليمات البرمجية التي تحتوي على عامل التشغيل goto
لم تكن قابلة للقراءة مثل كتل التعليمات البرمجية التي تؤدي نفس الوظائف ولكن بدون goto
طرق بديلة ( break
،،، continue
وضع كتلة التعليمات البرمجية في الأساليب). وفي الحقيقة كان هناك آخرون مثل:
- صعوبة في قراءة وفهم التعليمات البرمجية التي تحتوي على عوامل تشغيل
goto
؛ - تعقيد عملية تحسين التعليمات البرمجية للمترجم (وأحيانًا مستحيلة)؛
- زيادة احتمالية حدوث أخطاء طفيفة في التعليمات البرمجية.
goto
يعمل بنجاح كبير في بعض لغات البرمجة. ومع ذلك، يتجنب المبرمجون استخدامه. يمكنك أن تقرأ عن أسباب ذلك في مقال واحد على حبري . ولكن لماذا إذن نتركها goto
في قائمة الكلمات المحجوزة؟ الأمر بسيط: للمستقبل. على سبيل المثال، إذا تم استدعاء المتغيرات أو الأساليب أو الفئات في كود Java الخاص بالمطورين في جميع أنحاء العالم goto
، وإذا تم إرجاع هذا البيان في إصدار مستقبلي من Java، فسوف تنكسر جميع التعليمات البرمجية القديمة. لتجنب مثل هذا السيناريو، goto
يظل في قائمة كلمات Java الأساسية، لكنه لا يحمل أي وظيفة. ربما goto
سيعود يوما ما إلى صفوفنا، لكن احتمال ذلك ضعيف.
نتائج
لقد نظرنا إلى مشغلي القفزات المختلفة في Java:return
— إكمال الطريقة، وإرجاع قيمة من الطريقة.- مع قيمة الإرجاع: الأساليب التي ترجع القيم؛
- لا توجد قيمة إرجاع:
void
الأساليب.
break
— انقطاع الدورات، كتل حالة التبديل.- مع العلامات: دورات التعشيش المختلفة؛
- بدون ملصقات: فروع حالة التبديل للكتلة؛ مقاطعة الحلقة التي تم استدعاؤها.
continue
.- مع العلامات: دورات التعشيش المختلفة؛
- بدون تسميات: استمرار الحلقة التي تم استدعاؤها.
goto
.- موجود في قائمة الكلمات الرئيسية، لكنه غير مستخدم.
GO TO FULL VERSION