JavaRush /مدونة جافا /Random-AR /مشغلي القفز في جافا

مشغلي القفز في جافا

نشرت في المجموعة
مرحبًا! سنتحدث اليوم عن عوامل القفز في Java:
  • return
  • break
  • continue
  • goto
أولا، دعونا نحدد ما هو عليه في الواقع. كما تعلم، في الوضع الطبيعي، يتم تنفيذ البرنامج خطيًا - من الأعلى إلى الأسفل، أمرًا تلو الآخر. يمكن تغيير التدفق الخطي للبرنامج من خلال ما يسمى بهياكل التحكم: على سبيل المثال، الفروع ( if) والحلقات ( for، whileوما إلى ذلك). بالإضافة إلى بنيات التحكم، يمكن تعديل التنفيذ الخطي للبرنامج عن طريق عبارات القفز. وهم مسؤولون عن إعادة توجيه تنفيذ البرنامج إلى موقع محدد، والذي يعتمد على السياق والبيان المحدد. مشغلي القفز في جافا - 1دعونا نلقي نظرة فاحصة على كل من المشغلين الأربعة.

يعود

هذا هو المشغل الذي غالبًا ما يتعرف عليه القادمون الجدد أولاً. ينهي البيان returnالطريقة التي تم استدعاؤه بها، ويعود تنفيذ البرنامج إلى الموقع الذي تم استدعاء الطريقة منه. وله returnشكلان:
  1. ينهي على الفور تنفيذ الطريقة.
  2. ينهي تنفيذ الطريقة على الفور ويعيد بعض القيمة كنتيجة لهذه الطريقة.
بناء الجملة لكلا النموذجين هو:
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:
وهذا ما تبدو عليه التسميات داخل كود 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();
    }
}
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يستخدم العامل في حالتين:
  1. لإكمال أي فرع تنفيذ في كتلة حالة التبديل.
  2. لمقاطعة تنفيذ الحلقة.
المشغل له شكلان: مع علامات (ملصق) وبدون. بناء الجملة لكلا النموذجين هو:
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يقاطع المشغل التكرار الحالي ويسبب بدء التكرار التالي. مشغلي القفز في جافا - 2يمكن أن يكون هذا مفيدًا إذا كنت بحاجة إلى إجراء بعض العمليات على العناصر التي تستوفي شروطًا معينة. لنفترض أن لدينا سلسلة نصية ونريد حساب عدد الكلمات التي تبدأ بالحرف "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يكمل تكرارات الحلقة التي تمت كتابتها فيها. وباستخدام الملصق، يتخطى التكرار الحالي للدورة المميزة بالملصق. في بعض المواقف، يمكنك استبدال أحدهما بالآخر، وسيظل كل شيء في وظيفة البرنامج كما هو. سنتحدث عن الأفضل للاختيار (المفسد: إمكانية قراءة الكود) أدناه. يمكن استبدال عامل التشغيل ليس فقط بعلامة، ولكن أيضًا بـ . قبل ذلك مباشرة، تحتاج إلى نقل الحلقة المتداخلة إلى طريقة منفصلة: continuebreakcontinuebreakcontinuereturn
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:
  1. return— إكمال الطريقة، وإرجاع قيمة من الطريقة.
    • مع قيمة الإرجاع: الأساليب التي ترجع القيم؛
    • لا توجد قيمة إرجاع: voidالأساليب.
  2. break— انقطاع الدورات، كتل حالة التبديل.
    • مع العلامات: دورات التعشيش المختلفة؛
    • بدون ملصقات: فروع حالة التبديل للكتلة؛ مقاطعة الحلقة التي تم استدعاؤها.
  3. continue.
    • مع العلامات: دورات التعشيش المختلفة؛
    • بدون تسميات: استمرار الحلقة التي تم استدعاؤها.
  4. goto.
    • موجود في قائمة الكلمات الرئيسية، لكنه غير مستخدم.
الاستنتاج من كل هذا بسيط: من الأفضل إعطاء الأفضلية لأبسط الطرق التي تجعل قراءة الكود أسهل. حاول ألا تفرط في تحميل التعليمات البرمجية الخاصة بك بحلقات متعددة المستويات متداخلة داخل بعضها البعض مع وفرة من العلامات والانقطاعات والاستمرارية.
تعليقات
TO VIEW ALL COMMENTS OR TO MAKE A COMMENT,
GO TO FULL VERSION