سلام! امروز در مورد عملگرهای پرش در جاوا صحبت خواهیم کرد:
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
، میخواهم در مورد برچسبها در جاوا صحبت کنم. این مهم است زیرا در برخی شرایط، 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
در حلقه ها قطع کردن یک حلقه نامتناهی در صورت تحقق شرایط خاص است. در اینجا نمونه ای از برنامه ای است که خط وارد شده توسط کاربر را تا زمانی که کاربر کلمه "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
. به طور معمول اجرای کد را به بخشی از برنامه که با برچسب مشخص شده است هدایت می کند. اما در جاوا goto
، می توان گفت، این است و نیست. بیایید آن را بفهمیم. لیست کلمات کلیدی در جاوا شامل کلمه goto
. با این حال، این عبارت به عنوان استفاده نشده علامت گذاری شده است. واقعیت این است که جیمز گاسلینگ، خالق زبان جاوا، در ابتدا پشتیبانی از اپراتور را در JVM گنجاند goto
. با این حال، این ویژگی بعدا قطع شد. یکی از دلایل این است که بلوکهای کد حاوی عملگر goto
به اندازه بلوکهای کدی که عملکردهای مشابهی را انجام میدهند اما بدون goto
، اما با رویکردهای جایگزین ( break
، continue
قرار دادن بلوک کد در روشها) قابل خواندن نیستند. در واقع موارد دیگری نیز وجود داشت، مانند:
- مشکل در خواندن و درک کدهای حاوی عملگرها
goto
. - پیچیده بهینه سازی کد برای کامپایلر (و گاهی اوقات حتی غیرممکن)؛
- افزایش احتمال ایجاد خطاهای ظریف در کد.
goto
کاملاً موفقیت آمیز عمل می کند. با این حال، برنامه نویسان از استفاده از آن اجتناب می کنند. دلایل این امر را می توانید در یک مقاله در Habré بخوانید . اما چرا آن را goto
در لیست کلمات رزرو شده رها کنید؟ ساده است: برای آینده. برای مثال، اگر متغیرها، متدها یا کلاسها در کد جاوای توسعهدهندگان در سراسر جهان نامیده شوند goto
، اگر این عبارت در نسخه بعدی جاوا برگردانده شود، همه کدهای قدیمی خراب میشوند. برای جلوگیری از چنین سناریویی، goto
در لیست کلمات کلیدی جاوا باقی می ماند، اما هیچ عملکردی ندارد. شاید روزی goto
او به جمع ما بازگردد، اما احتمال آن کم است.
نتایج
ما به عملگرهای مختلف پرش در جاوا نگاه کرده ایم:return
- تکمیل متد، برگرداندن مقداری از متد.- با مقدار بازگشتی: روش هایی که مقادیر را برمی گرداند.
- بدون مقدار بازگشتی:
void
روش ها.
break
- قطع چرخه ها، بلوک های سوئیچ.- با برچسب ها: چرخه های مختلف تودرتو.
- بدون برچسب: شاخه های جعبه سوئیچ بلوک. قطع کردن حلقه ای که در آن فراخوانی شده است.
continue
.- با برچسب ها: چرخه های مختلف تودرتو.
- بدون برچسب: ادامه حلقه ای که در آن فراخوانی شده است.
goto
.- در لیست کلمات کلیدی قرار دارد، اما استفاده نمی شود.
GO TO FULL VERSION