راهنمای مبتدی برای تلاش و گرفتن در جاوا

در این راهنما:
- چیست
try
وتcatch
در جاوا؟ - نحوه استفاده از چندگانه
catch
بلوک هایی برای رسیدگی به خطاهای مختلف - نحوه استفاده از
finally
محاصره کردن - اشتباهات رایج در رسیدگی به استثنا (و نحوه جلوگیری از آنها)
- زمان شروع به شکستن (و رفع) کد خود!
جاوا عالی است … تا زمانی که چیزی پیش نرود.
یک خطای غیر منتظره ، و کل برنامه شما خراب می شود. اما اگر بتوانید این اتفاق را متوقف کنید چه می شود؟
این جایی است که try
وت catch
وارد شوید. آنها به شما اجازه می دهند قبل از اینکه برنامه خود را از بین ببرد ، خطاها را برطرف کنید و همه چیز را به راحتی انجام دهید.
در این راهنما ، یاد می گیرید که چگونه خطاها را به روش صحیح بدست آورید-بنابراین اشکال زدایی کمتر شبیه یک بازی حدس می زند و بیشتر شبیه حل مسئله واقعی است.
بیایید شیرجه بزنیم.
sidenote: اگر با موضوعات موجود در این راهنما دست و پنجه نرم می کنید ، احساس می کنید می توانید از آموزش کمی بیشتر استفاده کنید ، یا فقط می خواهید برخی از پروژه های چشمگیر جاوا را برای نمونه کارها خود بسازید ، چکمه برنامه نویسی جاوا را بررسی کنید.
به روز شده برای سال 2025 ، اصول برنامه نویسی جاوا را از همه راه از مبتدی کامل گرفته تا مهارت های پیشرفته یاد خواهید گرفت.
با این وجود ، شما قادر خواهید بود یادگیری خود را با بیش از 80 تمرین و 18 آزمونه تقویت کنید. این تنها دوره ای است که شما باید از مبتدی برنامه نویسی کامل بروید تا بتوانید به عنوان یک توسعه دهنده پس زمینه استخدام شوید!
با این کار ، بیایید وارد این آموزش 5 دقیقه ای شویم …
تلاش و گرفتن در جاوا چیست؟
مهم نیست که توسعه دهندگان جاوا کد خود را بنویسند ، خطاها اتفاق می افتد. برخی از اشتباهات برنامه نویسی ، مانند تقسیم صفر یا فراموش کردن برای شروع یک متغیر ، ناشی می شوند. برخی دیگر از کنترل توسعه دهنده مانند پرونده های گمشده ، اتصالات اینترنتی ناموفق یا ورودی کاربر بد خارج نیستند.
جاوا این خطاها را به دو نوع طبقه بندی می کند:
-
استثنائات بدون بررسی – این اشتباهاتی در کد شما است که باید برطرف شود. مثال:
NullPointerException
-
استثنائات بررسی شده -این خرابی های خارجی است که حتی در کد خوب نوشته شده نیز می تواند اتفاق بیفتد. مثال: پرونده یافت نشد ، خطاهای شبکه و غیره
از آنجا که استثنائات بررسی شده غیرقابل اجتناب است ، جاوا به توسعه دهندگان نیاز دارد تا خودشان را اداره کنند ، زیرا اگر گرفتار نشوند ، این برنامه خراب می شود.
این دقیقاً همان چیزی است که try
وت catch
برای ما می توانیم فرض کنیم خطاها اتفاق می افتد و راه حل های مهندس از قبل. بنابراین اگر مشکل X رخ می دهد ، به جای تصادف ، y را انجام دهید.
یا از نظر جاوا:
بیایید try
برای اجرای این کار ، و اگر یک استثنا در حال وقوع است ، catch
آن را و در عوض این کار را انجام دهید.
به عنوان مثال
تصور کنید که در حال ساخت یک ماشین حساب هستید که دو شماره را تقسیم می کند. همه چیز خوب کار می کند تا زمانی که کسی به عنوان مخرج وارد صفر شود و همه چیز را خراب می کند:
public class NoTryCatch {
public static void main(String[] args) {
int result = 10 / 0; // Error: Division by zero!
System.out.println("This will never run.");
}
}
در اینجا می توانیم ببینیم که جاوا تقسیم را با صفر تشخیص می دهد ، این کار را نمی داند ، و بنابراین ArithmeticException
، و برنامه را بلافاصله خاموش می کند.
البته مشکل این است که کاربر تصوری ندارد که چه اشتباهی رخ داده است زیرا هشدار ما از "This will never run."
هرگز حتی چاپ نمی شود! خراب کردن برنامه باعث می شود که آنها از آگاهی از خطای آنها آگاهی داشته باشند.
حال تصور کنید که این اتفاق در یک برنامه بانکی آنلاین رخ داده است. اگر معامله ای انجام نشود ، شما نمی خواهید کل سیستم خراب شود یا کاربر فکر کند پول آنها از بین رفته است.
درعوض ، شما می خواهید برنامه خطا را بدست آورد و به درستی رسیدگی کند ، مانند این:
public class TryCatchExample {
public static void main(String[] args) {
try {
int result = 10 / 0;
System.out.println("This won't run.");
} catch (ArithmeticException e) {
System.out.println("Oops! You can't divide by zero.");
}
System.out.println("Try again.");
}
}
این بار ، به جای اینکه برنامه را خراب کند ، جاوا به آن پرش می کند catch
بلوک ، جایی که ما با چاپ خطا را کنترل می کنیم "Oops! You can't divide by zero."
پس از رسیدگی به استثنا ، اعدام از گذشته حرکت می کند catch block
وت "Try again"
چاپ شده است این یک تفاوت بزرگ است.
اکنون ، کاربر حداقل می داند به جای اینکه در تاریکی بماند چه اشتباهی رخ داده است. مهمتر از همه ، این برنامه در حال اجرا است تا آنها بتوانند دوباره امتحان کنند.
به خاطر داشته باشید که این در واقع وضعیتی نیست که نیاز به تلاش و گرفتن داشته باشد. این صرفاً برای نشان دادن مکانیسم است. Arithmeticexception در واقع یک استثناء نشده است. اگر این یک استثناء بررسی شده بود ، باید آن را اداره کنیم.
tl ؛ دکتر
این قدرت است try
وت catch
بشر خطاها اتفاق می افتد و شما نمی توانید جلوی آن را بگیرید. اما کاری که شما می توانید انجام دهید این است که تصمیم بگیرید که چگونه برنامه شما باید هنگام انجام کار پاسخ دهد.
حالا که هدف از آن را درک کردید try
وت catch
، بیایید عمیق تر برویم و به موقعیت های دیگری نگاه کنیم ، مانند اینکه اگر چندین کار به یکباره اشتباه انجام شود چه می کنید؟ …
نحوه استفاده از چندین بلوک صید برای رسیدگی به خطاهای مختلف
خطاها به ندرت در انزوا اتفاق می افتد. بسته به ورودی ، محیط یا فقط بدشانسی ، یک بلوک کد واحد می تواند به روش های مختلفی شکست بخورد.
به عنوان مثال
بیایید بگوییم یک برنامه اعداد را تقسیم می کند و به یک آرایه دسترسی می یابد.
هر دو می توانند اشتباه کنند. جاوا اولین خطایی را که با آن روبرو می شود پرتاب می کند و بلافاصله اجرای آن را متوقف می کند. خطای دوم حتی هرگز رخ نمی دهد. چگونه می توانیم این کار را انجام دهیم ، می توانیم چنین کاری انجام دهیم:
public class NoTryCatch {
public static void main(String[] args) {
try {
int[] numbers = {1, 2, 3};
int result = 10 / 0; // Error: Division by zero!
System.out.println(numbers[5]); // Error: Out of bounds!
} catch (Exception e) {
System.out.println("Problem: " + e.getMessage());
}
}
}
پس از 10 / 0
یک عملیات نامعتبر است ، جاوا پرتاب می کند ArithmeticException
و تصادفات این یعنی خط بعدی – System.out.println(numbers[5]);
– هرگز اجرا نمی شود. با این حال ، اگر ما اولین مشکل را نداشتیم ، می توانستیم ArrayIndexoutOfBoundSexception را داشته باشیم. هر دوی این موارد استثنائی هستند و توسط بلوک صید ما اداره می شوند.
چرا این موضوع مهم است؟
اگر می توانیم چندین خطای داشته باشیم ، ممکن است بخواهیم آنها را متفاوت اداره کنیم. به همین دلیل چندین بلوک صید عالی هستند. آنها به طور خاص به ما می گویند که چه اشتباهی رخ داده است و می تواند اقدامات دقیقی انجام دهد.
بنابراین چگونه این کار را انجام دهیم؟
ما می توانیم هر دو استثنا را به طور جداگانه با استفاده از چندگانه کنترل کنیم catch
بلوک ها
public class MultipleCatchExample {
public static void main(String[] args) {
try {
int[] numbers = {1, 2, 3};
int result = 10 / 0; // ArithmeticException
System.out.println(numbers[5]); // ArrayIndexOutOfBoundsException
} catch (ArithmeticException e) {
System.out.println("Math error: " + e.getMessage());
} catch (ArrayIndexOutOfBoundsException e) {
System.out.println("Invalid array index!");
}
}
}
اکنون ، جاوا خطای اول را تشخیص می دهد (10 / 0)
و به مربوطه می پرید catch
بلوک ، چاپ:
Math error: / by zero
از آنجا که یک استثناء اجرا را در داخل متوقف می کند try
بلوک ، خط دوم (numbers[5])
هرگز اجرا نمی شود – درست مثل گذشته.
تفاوت؟ این برنامه اکنون هنگام اشتباه ، خطای دقیقی دارد. و ما می دانیم که کدام خطا پرتاب شده است. همچنین ، هر چیزی که ما واقعاً نمی توانیم تصور کنیم در این مرحله ، مانند NullPointerException در آن بلوک ، دیگر نیز گرفتار نمی شوند.
به عنوان مثال
بیایید بگوییم تغییر می کنیم 10 / 0
به 10 / 2
، بنابراین بخش دیگر شکست نمی خورد.
public class FixedFirstError {
public static void main(String[] args) {
try {
int[] numbers = {1, 2, 3};
int result = 10 / 2; // Fixed: No more division by zero
System.out.println(numbers[5]); // Still causes an error!
} catch (ArithmeticException e) {
System.out.println("Math error: " + e.getMessage());
} catch (ArrayIndexOutOfBoundsException e) {
System.out.println("Invalid array index!");
}
}
}
اکنون که این بخش کار می کند ، جاوا به اجرای خود ادامه می دهد و می رسد numbers[5]
، که خارج از مرز است. این بار ، آن را پرتاب می کند ArrayIndexOutOfBoundsException
، که توسط دوم گرفتار است catch
بلوک ، چاپ:
Invalid array index!
دقیقاً به همین دلیل چند catch
بلوک ها وجود دارند – بنابراین ما می توانیم به جای برخورد با همه آنها به همان روش ، هر شکست بالقوه را به صورت جداگانه انجام دهیم.
نحوه استفاده از بلوک نهایتا
تا کنون ، ما دیده ایم که چگونه try
وت catch
استثنائات را کنترل کنید و از خراب شدن برنامه خود جلوگیری کنید. اما اگر همیشه نیاز به اجرای کد داشته باشید مهم نیست که چه اتفاقی می افتد؟
بیایید بگوییم برنامه شما پرونده ای را باز می کند ، محتویات آن را می خواند و سپس آن را می بندد. اگر پرونده از دست رفته باشد ، خطایی رخ می دهد. اما آیا خطایی وجود دارد یا خیر ، برای جلوگیری از نشت منابع ، هنوز هم باید پرونده را ببندید.
خوب ، اینجاست finally
بلوک وارد می شود.
در finally
بلوک بعد از try
بلوک – مهم نیست که در داخل آن اتفاق می افتد. چه یک استثنا پرتاب شود یا همه چیز به طور کامل کار کند ، کد داخل finally
همیشه اجرا می شود. (خوب … تقریباً همیشه ، به جز اگر چیزی مانند System.exit (0) تماس بگیرید ؛ در بلوک صید ، که یک الزام بسیار رایج نخواهد بود.)
به عنوان مثال
در اینجا می توانیم استفاده کنیم finally
برای بستن یک شی اسکنر که در حال خواندن یک پرونده است.
import java.io.File;
import java.io.FileNotFoundException;
import java.util.Scanner;
public class FinallyExample {
public static void main(String[] args) {
Scanner scanner = null; // This has to go outside of the try for scope in the finally block
try {
File file = new File("data.txt");
scanner = new Scanner(file);
System.out.println(scanner.nextLine());
} catch (FileNotFoundException e) {
System.out.println("File not found.");
} finally {
if (scanner != null) {
scanner.close();
System.out.println("Scanner closed.");
}
}
}
}
اینجا چه اتفاقی می افتد؟
- در
try
تلاش برای باز کردن پرونده و خواندن خط اول آن - اگر پرونده وجود نداشته باشد ، جاوا پرتاب می کند
FileNotFoundException
، وcatch
چاپ های بلوک"File not found"
- در
finally
بلوک بدون توجه به چه اتفاقی می افتد و اسکنر را برای آزاد کردن منابع سیستم می بندد
حتی اگر خطایی رخ دهد ، اسکنر همیشه بسته خواهد شد.
چرا این مفید است؟
به این دلیل که بسیاری از شرایط پس از اجرای برخی از کد ها نیاز به تمیز کردن کارها دارند ، از جمله:
- بسته شدن پرونده پس از خواندن یا نوشتن (حتی اگر خطایی رخ دهد)
- جدا کردن از یک پایگاه داده برای آزاد کردن منابع
- آزاد کردن حافظه یا اتصالات شبکه بنابراین برنامه شما با گذشت زمان کند نمی شود
بدون finally
، شما باید کد پاکسازی را در هر دو تکرار کنید try
وت catch
بلوک ها – که ناکارآمد و آسان است. اما finally
پاکسازی را تضمین می کند همیشه اتفاق می افتد ، چه خطایی رخ دهد یا خیر ، برنامه شما را قابل اطمینان تر و کارآمدتر می کند.
sidenote: ما تا پایان این راهنمای مبتدی با مفهوم منابع آزمایشی سر و کار نخواهیم داشت ، اما اغلب منابع هستند
*autocloseable*.
این بدان معنی است که آنها می توانند به طور خودکار با یک نحو امتحان ویژه بسته شوند و نیاز به یک را از بین ببرندfinally
بلوک به زودی این را خواهید دید! فقط به خواندن ادامه دهید.
اگر بیانیه بازگشت وجود داشته باشد چه می شود؟
یک چیز مفید برای دانستن این است که finally
همیشه اجرا می شود ، حتی اگر a return
بیانیه در داخل استفاده می شود try
یا catch
بشر
public class FinallyWithReturn {
public static void main(String[] args) {
System.out.println(testMethod());
}
public static String testMethod() {
try {
return "Try block executed.";
} finally {
System.out.println("Finally block executed.");
}
}
}
حتی اگر try
بلوک یک مقدار را برمی گرداند ، جاوا از روش خارج نمی شود تا finally
بلوک در حال اجرا است. این یعنی این چاپ:
Finally block executed.
Try block executed.
این تضمین می کند که کد پاکسازی در داخل finally
همیشه اجرا می شود ، مهم نیست که چه چیزی.
حالا که ما پوشانده ایم try
با catch
وت finally
، بیایید به برخی از اشتباهات رایج که توسعه دهندگان هنگام رسیدگی به استثنائات انجام می دهند ، و چگونگی جلوگیری از آنها نگاه کنیم.
اشتباهات رایج در رسیدگی به استثنا (و نحوه جلوگیری از آنها)
با استفاده از try
وت catch
برای رسیدگی به خطاها در جاوا ضروری است ، اما سوء استفاده از آنها آسان است. اگر استثنائات را به درستی انجام ندهید ، می توانید اشکالات واقعی را پنهان کنید ، اشکال زدایی را سخت تر کنید یا حتی موارد جدیدی را معرفی کنید.
بیایید رایج ترین اشتباهاتی را که توسعه دهندگان مرتکب می شوند – طی کنیم – و چگونه می توان کارها را به روش صحیح انجام داد.
اشتباه شماره 1. گرفتن هر استثنا بدون استفاده صحیح از آن
یکی از بزرگترین اشتباهاتی که توسعه دهندگان جاوا مرتکب می شوند ، گرفتن استثنائات بدون اینکه واقعاً آنها را اداره کند. فقط به این دلیل که برنامه شما خراب نمی شود به این معنی نیست که به درستی در حال اجرا است.
به عنوان مثال
برخی از توسعه دهندگان کد خود را در یک می بندند try-catch
بلوک اما در صورت بروز خطا اقدام نکنید. در عوض ، آنها ترک می کنند catch
مسدود کردن یک پیام مبهم را که به اشکال زدایی کمک نمی کند ، خالی کنید.
public class BadExample {
public static void main(String[] args) {
try {
int result = 10 / 0;
} catch (Exception e) {
// Doing nothing here!
}
System.out.println("Program continues...");
}
}
در نگاه اول ، این ممکن است خوب به نظر برسد زیرا این برنامه خراب نمی شود. اما به همین دلیل این یک ایده بد است:
- این خطا کاملاً نادیده گرفته می شود که هیچ پیامی ، ورود به سیستم وجود ندارد ، هیچ نشانه ای از اشتباه است
- این برنامه در حالت ناشناخته اجرا می شود ، که به طور بالقوه منجر به شکست های حتی بیشتر می شود
- شما در اینجا استثناء نوع را می گیرید ، به این معنی که انواع استثناء نادیده گرفته می شود
- اشکال زدایی غیرممکن می شود زیرا هیچ اطلاعاتی در مورد آنچه اشتباه رخ داده است وجود ندارد یا در کجا اتفاق افتاده است
تصور کنید که این اتفاق در یک برنامه مالی رخ داده است. اگر هنگام پردازش پرداخت خطایی رخ دهد اما بی صدا نادیده گرفته شود ، کاربران ممکن است هرگز بدانند که معامله آنها شکست خورده است و بعداً نمی توانید دلیل آن را پیدا کنید.
چگونه آن را اصلاح کنیم
اگر یک استثنا را می گیرید ، مطمئن شوید که واقعاً آن را اداره می کنید. این می تواند به معنای ورود به خطا ، اطلاع رسانی به کاربر ، آزمایش مجدد یک عملیات یا خاموش کردن لطف باشد – اما هرگز آن را کاملاً نادیده نمی گیرد.
حداقل ، خطا را وارد کنید تا بدانید چه اتفاقی افتاده است:
public class BetterExample {
public static void main(String[] args) {
try {
int result = 10 / 0;
} catch (ArithmeticException e) {
System.out.println("Error: Division by zero occurred.");
e.printStackTrace(); // Prints full error details for debugging
}
}
}
در این مثال:
- این برنامه به جای عدم موفقیت در سکوت ، اطلاعات مفیدی را ثبت می کند
- در
e.printStackTrace();
روش جزئیات خطای کامل را چاپ می کند ، و این باعث می شود مشکل مشکل آسان شود. در برنامه های واقعی ، این احتمالاً با ورود واقعی جایگزین شده است - ما هنوز این استثنا را می گیریم ، اما می فهمیم چه اشتباهی رخ داده است
اشتباه شماره 2. استثنائات بیش از حد عمومی
در ابتدا ، گرفتن هر ممکن exception
به استثنای ممکن است یک شبکه ایمنی خوب به نظر برسد. از این گذشته ، تضمین می کند که این برنامه به طور غیر منتظره سقوط نمی کند ، درست است؟
اما در واقعیت ، گرفتن همه استثنائات از این طریق خطاهای خاص را پنهان می کند و اشکال زدایی را بسیار سخت تر می کند.
به عنوان مثال
public class BadGenericCatch {
public static void main(String[] args) {
try {
int result = 10 / 0;
} catch (Exception e) { // Too broad!
System.out.println("An error occurred.");
}
}
}
چرا این بد است؟
- این همه استثنائات را جلب می کند ، حتی مواردی که انتظار آن را نداشتید
- پیام خطا به ما نمی گوید چه اشتباهی رخ داده است – می تواند هر چیزی باشد!
- اگر یک استثناء جدی دیگر اتفاق بیفتد (به عنوان مثال ، nullpointerexception) ، ممکن است هرگز آن را متوجه شوید
بنابراین به جای گرفتن همه چیز ، فقط باید استثنائاتی را که انتظار دارید بدست آورید.
public class BetterSpecificCatch {
public static void main(String[] args) {
try {
int result = 10 / 0;
} catch (ArithmeticException e) {
System.out.println("Math error: " + e.getMessage());
}
}
}
- خطاها را معنی دار نگه می دارد – “خطای ریاضی: / توسط صفر” بسیار مفیدتر از “خطایی بود”
- از پنهان کردن مسائل مهم جلوگیری می کند – استثنائات غیر منتظره دیگر برای اشکال زدایی قابل مشاهده است
- استفاده از استثناء بهتر را تضمین می کند – هر شماره به طور مناسب انجام می شود ، نه به طور کلی
اشتباه شماره 3. به جای رفع علت اصلی ، استفاده از استثنائات بدون بررسی را استفاده کنید
استثنائات بدون بررسی هنگامی اتفاق می افتد که چیزی در کد شما اشتباه باشد – مانند تلاش برای دسترسی null
ارزش بر خلاف استثنائات بررسی شده (که ناشی از مشکلات خارجی مانند پرونده های گمشده است) ، استثنائات بدون بررسی ، یک اشکال را نشان می دهد که باید برطرف شود ، نه گرفتار.
اما برخی از توسعه دهندگان جاوا سوء استفاده را امتحان می کنند و به عنوان میانبر می گیرند. آنها به جای رفع مشکل واقعی ، کد را در یک بلوک امتحان می کنند تا جلوی خراب شدن برنامه را بگیرند. این مسئله واقعی را پنهان می کند و اشکال زدایی را سخت تر می کند و منجر به رفتار غیرقابل پیش بینی می شود.
به عنوان مثال
تمرین بد: صید NullPointerException
به جای جلوگیری از آن
public class WrongUsage {
public static void main(String[] args) {
try {
String text = null;
System.out.println(text.length()); // This throws NullPointerException
} catch (NullPointerException e) {
System.out.println("Oops, something went wrong.");
}
}
}
در نگاه اول ، این ممکن است یک رفع سریع به نظر برسد – برنامه خراب نمی شود. اما در واقعیت ، این فقط به جای حل آن ، مسئله عمیق تری را پوشش می دهد.
مسئله واقعی نیز از این قاعده مستثنی نیست – text
است ، null
در وهله اول
گرفتن NullPointerException
چیزی را برطرف نمی کند – این فقط مانع از عدم موفقیت برنامه می شود. بنابراین اگر در اینجا به Try-Catch اعتماد کنید ، به جای اینکه به درستی به آن بپردازید ، خطای منطقی را پنهان می کنید.
چگونه آن را اصلاح کنیم
به جای گرفتن خطا ، بررسی کنید که آیا شیء است null
قبل از استفاده از آن:
public class CorrectUsage {
public static void main(String[] args) {
String text = null;
if (text != null) {
System.out.println(text.length());
} else {
System.out.println("Text is null, can't get length.");
}
}
}
اکنون ، به جای گرفتن یک استثنا ، ما در وهله اول از وقوع آن جلوگیری می کنیم.
اشتباه شماره 4. با استفاده از try
وت catch
وقتی if
بیانیه بهتر است
برخی از توسعه دهندگان جاوا برای استفاده از موقعیت های قابل پیش بینی ، مانند بررسی ورودی کاربر ، از تلاش بیش از حد استفاده می کنند. در حالی که رسیدگی به استثنا برای شکست های غیر منتظره عالی است ، بهترین ابزار برای منطق برنامه عادی نیست.
اگر می توانید قبل از وقوع خطایی ، شرایط را بررسی کنید ، این تقریباً همیشه بهتر از گرفتن یک استثنا پس از واقعیت است.
به عنوان مثال
عمل بد: استفاده از try-catch
برای اعتبار سنجی ورودی
public class BadValidation {
public static void main(String[] args) {
String input = "abc";
try {
int number = Integer.parseInt(input);
System.out.println("You entered: " + number);
} catch (NumberFormatException e) {
System.out.println("Invalid input!");
}
}
}
در نگاه اول ، این ممکن است یک روش منطقی برای گرفتن ورودی بد به نظر برسد – اگر کاربر وارد چیزی شود که یک شماره نیست ، این برنامه خراب نمی شود.
اما این رویکرد ناکارآمد است. چرا؟ از آنجا که برنامه از قبل می داند که ورودی ممکن است نامعتبر باشد – باید قبل از تلاش برای تبدیل آن ، بررسی کند.
چرا این بد است؟
- رسیدگی به استثنا باید برای خرابی های غیر منتظره باشد ، نه موارد قابل پیش بینی مانند اعتبارسنجی ورودی
- خطاهای تجزیه شده قابل پیشگیری هستند – چرا می توانید در ابتدا اعتبار خود را برای استثنا صبر کنید؟
- تأثیر عملکرد –
try-catch
بلوک ها نسبت به بررسی های شرایط ساده کندتر هستند ، به خصوص اگر بارها در حلقه ها استفاده شود
چگونه آن را اصلاح کنیم
try-catch
باید آخرین راه حل شما باشد ، نه اولین انتخاب شما. اگر می توانید قبل از وقوع خطایی از خطا جلوگیری کنید (مانند اعتبارسنجی ورودی کاربر) ، همیشه یک رویکرد بهتر است. استفاده کردن try-catch
برای شکست های غیر منتظره واقعی ، نه جریان برنامه عادی.
به عنوان مثال
به جای انتظار برای استثنا ، بررسی کنید که آیا ورودی قبل از تبدیل آن معتبر است:
public class CorrectValidation {
public static void main(String[] args) {
String input = "abc";
if (input.matches("\\d+")) { // Checks if input contains only digits
int number = Integer.parseInt(input);
System.out.println("You entered: " + number);
} else {
System.out.println("Invalid input! You should have entered a number.");
}
}
}
اکنون ، ما فقط سعی می کنیم اگر بدانیم معتبر است ، شماره را تجزیه کنیم.
اشتباه شماره 5. عدم بستن منابع به درستی (و تکیه بر سرانجام وقتی که نیازی به آن ندارید)
پیش از این ، ما چگونه پوشش دادیم finally
بلوک تضمین می کند پاکسازی مهم نیست که چه چیزی باشد. اما یک اشتباه رایج بسیاری از توسعه دهندگان جاوا ، فراموش کردن منابع به طور کلی – به ویژه هنگام کار با پرونده ها ، پایگاه داده ها یا اتصالات شبکه است.
اگر بعد از استفاده از آن منبع را ببندید ، برنامه شما می تواند حافظه را نشت ، کند شدن یا حتی خرابی. این ممکن است فوراً آشکار نباشد ، اما با گذشت زمان ، منابع بدون محاصره ایجاد می شوند ، حافظه سیستم را مصرف می کنند و باعث رفتار غیرقابل پیش بینی می شوند.
به عنوان مثال
یک اشتباه معمولی باز کردن یک منبع در داخل است try
بلوک اما آن را در finally
بلوک
import java.io.File;
import java.io.FileNotFoundException;
import java.util.Scanner;
public class BadFileHandling {
public static void main(String[] args) {
Scanner scanner = null;
try {
scanner = new Scanner(new File("data.txt"));
System.out.println(scanner.nextLine());
scanner.close();
} catch (FileNotFoundException e) {
System.out.println("File not found.");
}
// Scanner never gets closed!
}
}
در نگاه اول ، این ممکن است یک اتفاق بزرگ به نظر نرسد. اما اگر خطایی قبل از آن رخ دهد scanner.close()
نامیده می شود ، اسکنر باز می ماند. هنگامی که این اتفاق به طور مکرر اتفاق می افتد-مثلاً در یک حلقه یا یک فرآیند طولانی مدت-جمع آوری منابع ، سنبله های استفاده از حافظه و عملکرد رنج می برد.
بهترین راه حل: به جای آن از منابع آزمایشی استفاده کنید
از جاوا 7 ، try-with-resources
بهترین راه برای مدیریت خودکار منابع است. به جای اینکه نگران بسته شدن منابع به صورت دستی باشید ، به جاوا اجازه می دهید آن را برای شما انجام دهد.
import java.io.File;
import java.io.FileNotFoundException;
import java.util.Scanner;
public class TryWithResourcesExample {
public static void main(String[] args) {
try (Scanner scanner = new Scanner(new File("data.txt"))) {
System.out.println(scanner.nextLine());
} catch (FileNotFoundException e) {
System.out.println("File not found.");
}
// No need for a finally block—Java automatically closes the scanner.
}
}
این رویکرد باعث می شود اسکنر باشد همیشه به محض خروج بلوک امتحان بسته شود، چه یک استثنا اتفاق می افتد یا نه. شما نیازی ندارید finally
مسدود کردن ، و هیچ خطری برای فراموش کردن منابع وجود ندارد.
چه موقع هنوز باید از آن استفاده کنید؟
try-with-resources
بهترین راه برای رسیدگی به منابع اتوکلوزی مانند پرونده ها و اتصالات پایگاه داده است. اما مواردی وجود دارد که finally
هنوز هم مفید است
(برخی از اشیاء پیاده سازی نمی کنند AutoCloseable
، به این معنی که نمی توان از آنها استفاده کرد try-with-resources
بشر اگر اینگونه باشد ، finally
گزینه Fallback شماست)
همچنین در صورت نیاز به تمیز کردن کارهای غیر تأمین کننده ، مانند تنظیم مجدد متغیرهای جهانی یا نوشتن پیام های ورود به سیستم ، مفید است.
به عنوان مثال
در اینجا چگونه است finally
می تواند به عنوان یک راه حل پشتیبان استفاده شود:
import java.io.File;
import java.io.FileNotFoundException;
import java.util.Scanner;
public class FinallyExample {
public static void main(String[] args) {
Scanner scanner = null;
try {
scanner = new Scanner(new File("data.txt"));
System.out.println(scanner.nextLine());
} catch (FileNotFoundException e) {
System.out.println("File not found.");
} finally {
if (scanner != null) {
scanner.close();
System.out.println("Scanner closed.");
}
}
}
}
در اینجا ، حتی اگر یک استثنا پرتاب شود ، finally
بلوک تضمین می کند که اسکنر به درستی بسته شود. به اندازه تمیز نیست try-with-resources
، اما بهتر از باز کردن منابع است.
tl ؛ دکتر
فراموش کردن منابع پاکسازی یک اشتباه رایج است که می تواند منجر به کندی ، تصادفات و نشت حافظه شود.
بنابراین:
- اگر با پرونده ها ، پایگاه داده ها یا اتصالات شبکه کار می کنید ، از آن استفاده کنید
try-with-resources
هر زمان ممکن این پاک تر ، ایمن تر است و خطر فراموشی را برای بستن دستی به صورت دستی از بین می برد - اگر
try-with-resources
گزینه ای نیست ، پس afinally
بلوک بهترین انتخاب بعدی شماست. تضمین می کند که پاکسازی اتفاق می افتد ، حتی اگر خطایی رخ دهد
زمان شروع به شکستن (و رفع) کد خود!
حالا که می فهمید try
با catch
وت finally
، بهترین راه برای یادگیری آزمایش است.
یک برنامه بنویسید ، خطاهای زور را اتفاق بیفتد و ببینید که استثنائات مختلف چگونه رفتار می کنند. با استفاده از چندین مورد ، خطاهای خاص را بگیرید catch
بلوک ها ، و اضافه کردن finally
برای تمیز کردن منابع ، بلوک.
خطاهای منطقی را به جای اینکه فقط آنها را گرفتار کنید ، برطرف کنید و همیشه استثنائات را به گونه ای انجام دهید که اشکال زدایی را آسان تر کند.
هرچه بیشتر تمرین کنید ، در نوشتن کد جاوا پایدار و ضد خطا بهتر خواهید شد.
حالا ، بروید مقداری کد را بشکنید – بنابراین می توانید آن را برطرف کنید!
PS
به یاد داشته باشید ، اگر می خواهید دانش جاوا خود را سریع دنبال کنید و تا آنجا که ممکن است تمرین دستی داشته باشید ، پس از آن چکمه برنامه نویسی جاوا را بررسی کنید.
به روز شده برای سال 2025 ، اصول برنامه نویسی جاوا را از همه راه از مبتدی کامل گرفته تا مهارت های پیشرفته یاد خواهید گرفت.
با این وجود ، شما قادر خواهید بود یادگیری خود را با بیش از 80 تمرین و 18 آزمونه تقویت کنید. این تنها دوره ای است که شما باید از مبتدی برنامه نویسی کامل بروید تا بتوانید به عنوان یک توسعه دهنده پس زمینه استخدام شوید!
بعلاوه ، پس از پیوستن ، این فرصت را خواهید داشت که در جامعه Discord خصوصی ما ، سایر دانشجویان و متخصصان DevOps کار کنید.