معمل الاستثناءات وتصحيح الأخطاء في جافا
مقدمة
مرحبًا بك في معمل استثناءات جافا وتصحيح الأخطاء! في هذا المعمل، ستتعلم كيفية:
- فهم الأنواع المختلفة من الأخطاء في جافا
- تصحيح أخطاء الكود الخاص بك باستخدام تقنيات بسيطة
- معالجة الاستثناءات (Exceptions) لمنع تعطّل البرنامج
- استخدام كتل try-catch بفعالية
الجزء 1: فهم الأخطاء
ما هي الأخطاء؟
الأخطاء هي مشكلات في الكود الخاص بك تمنعه من العمل بشكل صحيح. توجد ثلاثة أنواع رئيسية:
graph TD
A[Java Errors] --> B[Compile-Time Errors]
A --> C[Runtime Errors]
A --> D[Logical Errors]
B --> E[Detected before running<br/>Program won't compile]
C --> F[Occur while running<br/>Program crashes]
D --> G[Program runs but gives<br/>wrong results]أنواع الأخطاء
| نوع الخطأ | متى يحدث | مثال |
|---|---|---|
| وقت الترجمة (Compile-Time) | قبل تشغيل البرنامج | فاصلة منقوطة مفقودة، متغير غير مُعرَّف |
| وقت التشغيل (Runtime) | أثناء تشغيل البرنامج | القسمة على صفر، فهرس مصفوفة خارج النطاق |
| الخطأ المنطقي (Logical) | يعمل البرنامج لكن النتيجة خاطئة | استخدام x - y بدلاً من x + y |
الجزء 2: الأخطاء الشائعة
أخطاء وقت الترجمة (Compile-Time Errors)
تمنع هذه الأخطاء الكود الخاص بك من الترجمة (Compiling).
1. فاصلة منقوطة مفقودة
int x = 5 // Error: ';' expectedالحل: أضف فاصلة منقوطة في النهاية
int x = 5;2. متغير غير مُعرَّف
System.out.println(myVar); // Error: cannot find symbolالحل: عرّف المتغير أولاً
int myVar = 50;
System.out.println(myVar);3. عدم تطابق النوع (Type Mismatch)
int x = "Hello"; // Error: incompatible typesالحل: استخدم النوع الصحيح
String x = "Hello";أخطاء وقت التشغيل (Runtime Errors)
تحدث هذه الأخطاء أثناء تشغيل البرنامج.
1. القسمة على صفر
int x = 10;
int y = 0;
int result = x / y; // ArithmeticExceptionالمخرج:
Exception in thread "main" java.lang.ArithmeticException: / by zero2. فهرس مصفوفة خارج النطاق
int[] numbers = {1, 2, 3};
System.out.println(numbers[10]); // ArrayIndexOutOfBoundsExceptionالمخرج:
Exception in thread "main" java.lang.ArrayIndexOutOfBoundsException: 10الأخطاء المنطقية (Logical Errors)
هذه الأخطاء هي الأصعب في الاكتشاف لأن البرنامج يعمل دون أن يتعطّل.
int x = 10;
int y = 2;
int result = x - y; // You meant x + y
System.out.println(result); // Prints 8 instead of 12الجزء 3: أساسيات تصحيح الأخطاء (Debugging)
ما هو تصحيح الأخطاء؟
تصحيح الأخطاء (Debugging) هو اكتشاف وإصلاح الأخطاء في الكود الخاص بك.
flowchart LR
A[Code has bug] --> B[Add print statements]
B --> C[Run program]
C --> D[Check output]
D --> E{Found problem?}
E -->|No| B
E -->|Yes| F[Fix bug]
F --> G[Test again]استخدام جُمل الطباعة
أبسط طريقة لتصحيح الأخطاء هي استخدام System.out.println().
int x = 10;
int y = 0;
System.out.println("Before division"); // This prints
System.out.println("x = " + x); // This prints
System.out.println("y = " + y); // This prints
int result = x / y; // Program crashes here
System.out.println("Result: " + result); // Never runsالمخرج:
Before division
x = 10
y = 0
Exception in thread "main" java.lang.ArithmeticException: / by zeroقائمة تحقق تصحيح الأخطاء
✅ اقرأ رسالة الخطأ كاملة
✅ تحقّق من أن جميع المتغيرات مُهيَّأة (Initialized)
✅ اطبع قيم المتغيرات لتتبّع المشكلة
✅ انتبه لأخطاء الانحراف بواحد (Off-by-one) في الحلقات
✅ اختبر بمدخلات مختلفة
الجزء 4: معالجة الاستثناءات (Exception Handling)
ما هي الاستثناءات؟
عند حدوث خطأ، ترمي جافا استثناءً (Exception) (كائن خطأ). دون معالجته، يتعطّل برنامجك.
كتلة try-catch
استخدم try-catch لمعالجة الاستثناءات بسلاسة.
flowchart TD
A[Start] --> B[Execute try block]
B --> C{Error occurs?}
C -->|No| D[Skip catch block]
C -->|Yes| E[Execute catch block]
D --> F[Continue program]
E --> Fالصيغة العامة:
try {
// Code that might cause an error
} catch (Exception e) {
// Code to handle the error
}مثال: معالجة خطأ فهرس المصفوفة
بدون try-catch (يتعطّل البرنامج):
public class Main {
public static void main(String[] args) {
int[] myNumbers = {1, 2, 3};
System.out.println(myNumbers[10]); // Crash!
}
}المخرج:
Exception in thread "main" java.lang.ArrayIndexOutOfBoundsException: 10باستخدام try-catch (يستمر البرنامج):
public class Main {
public static void main(String[] args) {
try {
int[] myNumbers = {1, 2, 3};
System.out.println(myNumbers[10]);
} catch (Exception e) {
System.out.println("Something went wrong.");
}
}
}المخرج:
Something went wrong.الجزء 5: كتلة finally
تُشغَّل كتلة finally دائمًا، سواء حدث خطأ أم لا.
try {
int[] myNumbers = {1, 2, 3};
System.out.println(myNumbers[10]);
} catch (Exception e) {
System.out.println("Something went wrong.");
} finally {
System.out.println("The 'try catch' is finished.");
}المخرج:
Something went wrong.
The 'try catch' is finished.flowchart TD
A[try block] --> B{Error?}
B -->|Yes| C[catch block]
B -->|No| D[Skip catch]
C --> E[finally block]
D --> E
E --> F[Continue]الجزء 6: الكلمة المفتاحية throw
يمكنك إنشاء استثناءاتك الخاصة باستخدام throw.
مثال: التحقق من العمر
public class Main {
static void checkAge(int age) {
if (age < 18) {
throw new ArithmeticException("Access denied - You must be at least 18 years old.");
} else {
System.out.println("Access granted - You are old enough!");
}
}
public static void main(String[] args) {
checkAge(15); // Will throw exception
}
}المخرج:
Exception in thread "main" java.lang.ArithmeticException: Access denied - You must be at least 18 years old.استخدام throw مع try-catch
public class Main {
static void checkAge(int age) {
if (age < 18) {
throw new ArithmeticException("Access denied - You must be at least 18 years old.");
} else {
System.out.println("Access granted - You are old enough!");
}
}
public static void main(String[] args) {
try {
checkAge(15);
} catch (Exception e) {
System.out.println("Error: " + e.getMessage());
}
}
}المخرج:
Error: Access denied - You must be at least 18 years old.الجزء 7: Try-with-Resources
مشكلة الإدارة اليدوية للموارد
عند العمل مع الملفات أو التدفقات (Streams)، تحتاج إلى إغلاقها يدويًا:
import java.io.FileOutputStream;
public class Main {
public static void main(String[] args) {
FileOutputStream fos = null;
try {
fos = new FileOutputStream("output.txt");
fos.write("Hello".getBytes());
} catch (Exception e) {
e.printStackTrace();
} finally {
try {
if (fos != null) fos.close(); // Manual closing
} catch (Exception e) {
e.printStackTrace();
}
}
}
}الحل: try-with-resources
قدّمت جافا 7 صيغة try-with-resources لإغلاق الموارد تلقائيًا.
الصيغة العامة:
try (ResourceType resource = new ResourceType()) {
// Use the resource
}
// Resource is automatically closed hereمثال:
import java.io.FileOutputStream;
public class Main {
public static void main(String[] args) {
try (FileOutputStream fos = new FileOutputStream("output.txt")) {
fos.write("Hello".getBytes());
} catch (Exception e) {
e.printStackTrace();
}
// No need to close fos - Java does it automatically!
}
}موارد متعددة
يمكنك إدارة عدة موارد في وقت واحد:
import java.io.FileWriter;
import java.io.BufferedWriter;
public class Main {
public static void main(String[] args) {
try (FileWriter fw = new FileWriter("output.txt");
BufferedWriter bw = new BufferedWriter(fw)) {
bw.write("Hello World!");
} catch (Exception e) {
e.printStackTrace();
}
// Both resources are automatically closed in reverse order
}
}flowchart LR
A[Open Resource 1] --> B[Open Resource 2]
B --> C[Use Resources]
C --> D[Close Resource 2]
D --> E[Close Resource 1]الفوائد:
- ✅ كود أنظف - لا حاجة لاستدعاءات
close()يدوية - ✅ أكثر أمانًا - تُغلَق الموارد حتى في حال حدوث استثناء
- ✅ تلقائي - تتولّى جافا الإغلاق نيابة عنك
قاعدة عامة: عند العمل مع الملفات، أو التدفقات، أو اتصالات قواعد البيانات، استخدم دائمًا try-with-resources!
تمارين المعمل
التمرين 1: إصلاح أخطاء وقت الترجمة
اعثر على الأخطاء في هذا الكود وأصلحها:
public class Main {
public static void main(String[] args) {
int age = 25
String name
System.out.println("Name: " + name);
System.out.println("Age: " + age);
}
}التمرين 2: معالجة أخطاء وقت التشغيل
عدّل هذا الكود لمعالجة خطأ القسمة على صفر:
public class Main {
public static void main(String[] args) {
int[] numbers = {10, 20, 30};
int divisor = 0;
int result = numbers[0] / divisor;
System.out.println("Result: " + result);
}
}التمرين 3: إنشاء استثناء مخصّص
اكتب برنامجًا:
- يأخذ رقمًا كمدخل
- يرمي استثناءً إذا كان الرقم سالبًا
- يلتقط الاستثناء ويعالجه بشكل صحيح
التمرين 4: استخدام try-with-resources
اكتب برنامجًا:
- ينشئ ملفًا باسم "student.txt"
- يكتب اسمك ورقمك الجامعي في الملف
- يستخدم try-with-resources لضمان إغلاق الملف بشكل صحيح
أنواع الاستثناءات الشائعة
| الاستثناء | السبب |
|---|---|
ArithmeticException | القسمة على صفر |
ArrayIndexOutOfBoundsException | فهرس مصفوفة غير صالح |
NullPointerException | استخدام كائن فارغ (null) |
FileNotFoundException | الملف غير موجود |
NumberFormatException | تحويل غير صالح من نص إلى رقم |
الملخّص
mindmap
root((Java Exceptions<br/>& Debugging))
Error Types
Compile-Time
Runtime
Logical
Debugging
Print Statements
IDE Debugger
Check Variables
Exception Handling
try-catch
finally
throw
Best Practices
try-with-resources
Specific Exceptions
Meaningful Messagesأهم النقاط
- الأخطاء تحدث - حتى للمبرمجين ذوي الخبرة
- صحّح الأخطاء بشكل منهجي - استخدم جُمل الطباعة والمصحِّحات (Debuggers)
- عالِج الاستثناءات - استخدم try-catch لمنع تعطّل البرنامج
- أغلق الموارد - استخدم try-with-resources للملفات والتدفقات
- اختبر بشكل شامل - جرّب مدخلات مختلفة لاكتشاف الأخطاء
الخطوات التالية
- تدرّب على كتابة كتل try-catch لسيناريوهات مختلفة
- تعلّم عن أنواع الاستثناءات المحدَّدة
- استكشف أدوات تصحيح الأخطاء في بيئات التطوير (IntelliJ IDEA، Eclipse، NetBeans)
- ادرس تراتبية (Hierarchy) الاستثناءات في جافا
مصادر إضافية
- توثيق استثناءات جافا: https://docs.oracle.com/javase/tutorial/essential/exceptions/
- تدرّب على تقنيات تصحيح الأخطاء باستخدام بيئة التطوير الخاصة بك
- راجع رسائل الخطأ - غالبًا ما تخبرك بالضبط بمكان الخلل!
حظًا موفقًا في تمارين المعمل! تذكّر: كلما صحّحت الأخطاء أكثر، أصبحت أفضل في اكتشاف المشكلات وإصلاحها بسرعة.