فهم كيفية تنفيذ العمليات وتكرار التعليمات بكفاءة
بعد أن اكتسبنا المهارات الأساسية في التعامل مع البيانات وإدخالها وإخراجها، حان الوقت لنتعلم كيف نجعل برامجنا أكثر ذكاءً وكفاءة. في هذه الوحدة، سنستكشف مفهومين أساسيين في البرمجة: **العوامل (Operators)** و**الحلقات (Loops)**. العوامل تمكننا من إجراء عمليات متنوعة على البيانات، بينما تسمح لنا الحلقات بتكرار تنفيذ أجزاء من الكود بكفاءة عالية.
فهم العوامل والحلقات ضروري لبناء أي برنامج معقد أو تفاعلي، حيث أنها تُعد اللبنات الأساسية للمنطق والتحكم في سير البرنامج.
بنهاية هذه الوحدة، ستكون قادرًا على:
**العوامل (Operators)** في Java هي رموز خاصة نستخدمها لتنفيذ عمليات معينة على القيم أو المتغيرات. تُستخدم هذه العوامل لمعالجة البيانات وإنشاء التعبيرات والتحكم في تدفق البرنامج.
مثلاً: + للجمع، - للطرح، * للضرب، وغيرها.
يمكن تقسيم العوامل في جافا إلى مجموعات رئيسية بناءً على نوع العملية التي تقوم بها:
إضافة إلى ذلك، توجد عوامل أخرى مهمة سنتعرف عليها لاحقًا مثل العامل الشرطي ?: والعامل instanceof.
تُستخدم هذه العوامل لتنفيذ العمليات الرياضية الأساسية.
فيما يلي أشهرها مع أمثلة:
| اسم العامل | الرمز | مثال | الشرح |
|---|---|---|---|
| الجمع | `+` | `a + b` | يجمع قيمة `a` مع `b`. |
| الطرح | `-` | `a - b` | يطرح `b` من `a`. |
| الضرب | `*` | `a * b` | يضرب القيمتين. |
| القسمة | `/` | `a / b` | يقسم `a` على `b`. (إذا كانا عددين صحيحين، فالناتج سيكون عددًا صحيحًا) |
| باقي القسمة | `%` | `a % b` | يعطي الباقي عند قسمة `a` على `b`. |
| الزيادة (بعدية) | `a++` | `a++` | يزيد قيمة `a` بمقدار 1 بعد استخدام قيمتها الحالية في التعبير. |
| الزيادة (قبلية) | `++a` | `++a` | يزيد قيمة `a` بمقدار 1 قبل استخدام قيمتها في التعبير. |
| النقصان (بعدية) | `a--` | `a--` | ينقص قيمة `a` بمقدار 1 بعد استخدام قيمتها الحالية في التعبير. |
| النقصان (قبلية) | `--a` | `--a` | ينقص قيمة `a` بمقدار 1 قبل استخدام قيمتها في التعبير. |
| الجمع الأحادي | `+a` | `+a` | لا يغيّر القيمة لكن يُظهر الإشارة الموجبة (نادراً ما يستخدم). |
| الطرح الأحادي | `-a` | `-a` | يغيّر إشارة القيمة إلى سالبة. |
public class ArithmeticOperatorsExample {
public static void main(String[] args) {
int a = 10;
int b = 3;
System.out.println("a + b = " + (a + b)); // Output: 13
System.out.println("a - b = " + (a - b)); // Output: 7
System.out.println("a * b = " + (a * b)); // Output: 30
System.out.println("a / b = " + (a / b)); // Output: 3 (integer division)
System.out.println("a % b = " + (a % b)); // Output: 1
int x = 5;
System.out.println("x++ = " + (x++)); // Output: 5 (x becomes 6)
System.out.println("x is now: " + x); // Output: 6
int y = 5;
System.out.println("++y = " + (++y)); // Output: 6 (y becomes 6)
System.out.println("y is now: " + y); // Output: 6
}
}
تُستخدم هذه العوامل للمقارنة بين القيم، ويكون ناتجها دائمًا قيمة منطقية (true أو false). تُستخدم بشكل شائع في الجمل الشرطية والحلقات.
| اسم العامل | الرمز | مثال | الشرح |
|---|---|---|---|
| يساوي | `==` | `(a == b)` | صحيح إذا كانت القيمتان متساويتين. |
| لا يساوي | `!=` | `(a != b)` | صحيح إذا كانت القيمتان مختلفتين. |
| أكبر من | `>` | `(a > b)` | صحيح إذا كانت `a` أكبر من `b`. |
| أصغر من | `<` | `(a < b)` | صحيح إذا كانت `a` أصغر من `b`. |
| أكبر أو يساوي | `>=` | `(a >= b)` | صحيح إذا كانت `a` أكبر أو تساوي `b`. |
| أصغر أو يساوي | `<=` | `(a <= b)` | صحيح إذا كانت `a` أصغر أو تساوي `b`. |
public class ComparisonOperatorsExample {
public static void main(String[] args) {
int x = 10;
int y = 5;
System.out.println("x == y: " + (x == y)); // Output: false
System.out.println("x != y: " + (x != y)); // Output: true
System.out.println("x > y: " + (x > y)); // Output: true
System.out.println("x < y: " + (x < y)); // Output: false
System.out.println("x >= y: " + (x >= y)); // Output: true
System.out.println("x <= y: " + (x <= y)); // Output: false
}
}
تُستخدم هذه العوامل لدمج أكثر من شرط منطقي أو لعكس قيمة شرط. ناتجها دائمًا قيمة منطقية (true أو false).
| اسم العامل | الرمز | مثال | الشرح |
|---|---|---|---|
| AND (منطقي) | `&&` | `(a && b)` | صحيح فقط إذا كان الشرطان (أو التعبيران المنطقيان) صحيحين معًا. |
| OR (منطقي) | `||` | `(a || b)` | صحيح إذا كان أحد الشرطين (أو كلاهما) صحيحًا. خاطئ فقط إذا كان كلاهما خاطئًا. |
| NOT (منطقي) | `!` | `!a` | يعكس القيمة المنطقية (إذا كانت `true` تصبح `false` والعكس). |
public class LogicalOperatorsExample {
public static void main(String[] args) {
boolean isStudent = true;
boolean hasGoodGrades = false;
int age = 20;
// AND (&&)
System.out.println("isStudent && hasGoodGrades: " + (isStudent && hasGoodGrades)); // Output: false
// OR (||)
System.out.println("isStudent || hasGoodGrades: " + (isStudent || hasGoodGrades)); // Output: true
// NOT (!)
System.out.println("!isStudent: " + (!isStudent)); // Output: false
// دمج الشروط
System.out.println("(age > 18 && isStudent): " + (age > 18 && isStudent)); // Output: true
}
}
تتعامل هذه العوامل مع الأعداد على شكل بتات ثنائية (0 و 1)، وتُستخدم عادة في البرمجة المنخفضة المستوى، عند التعامل مع الذاكرة، أو في تشفير البيانات. تتطلب فهماً جيداً لكيفية تمثيل الأرقام في النظام الثنائي.
| اسم العامل | الرمز | مثال | الشرح |
|---|---|---|---|
| Bitwise AND | `&` | `a & b` | يُرجع `1` إذا كان كلا البتين المقابلين `1`، وإلا `0`. |
| Bitwise OR | `|` | `a | b` | يُرجع `1` إذا كان أي من البتين المقابلين `1`، وإلا `0`. |
| Bitwise XOR | `^` | `a ^ b` | يُرجع `1` إذا كان البتان المقابلان مختلفين، وإلا `0`. |
| Bitwise NOT (Complement) | `~` | `~a` | يقلب جميع البتات (0 تصبح 1 و 1 تصبح 0). |
| إزاحة لليسار (Signed Left Shift) | `<<` | `a << 2` | يُزح البتات لليسار بمقدار معين (هنا 2)، ويضيف أصفارًا من اليمين. يعادل الضرب في قوة 2. |
| إزاحة لليمين (Signed Right Shift) | `>>` | `a >> 2` | يُزح البتات لليمين بمقدار معين (هنا 2)، ويحتفظ بإشارة الرقم (يملأ من اليسار بإشارة البت الأخير). يعادل القسمة على قوة 2. |
| إزاحة لليمين مع ملء بالأصفار (Unsigned Right Shift) | `>>>` | `a >>> 2` | يُزح البتات لليمين ويملأ الفراغ من اليسار بأصفار، بغض النظر عن إشارة الرقم. |
public class BitwiseOperatorsExample {
public static void main(String[] args) {
int a = 5; // Binary: 0101
int b = 3; // Binary: 0011
System.out.println("a & b = " + (a & b)); // Output: 1 (Binary: 0001)
System.out.println("a | b = " + (a | b)); // Output: 7 (Binary: 0111)
System.out.println("a ^ b = " + (a ^ b)); // Output: 6 (Binary: 0110)
System.out.println("~a = " + (~a)); // Output: -6 (Binary: 1010, two's complement)
System.out.println("a << 1 = " + (a << 1)); // Output: 10 (Binary: 1010)
System.out.println("a >> 1 = " + (a >> 1)); // Output: 2 (Binary: 0010)
int negativeNum = -10; // Binary (example): 1111...11110110 (using two's complement)
System.out.println("negativeNum >> 1 = " + (negativeNum >> 1)); // Output: -5 (sign preserved)
System.out.println("negativeNum >>> 1 = " + (negativeNum >>> 1)); // Output: 2147483643 (fills with zero, changes sign for negative numbers)
}
}
تُستخدم لإعطاء قيم للمتغيرات. بعضها يجمع بين عملية حسابية والإسناد، مما يجعل الكود أكثر اختصاراً ووضوحاً.
| اسم العامل | الرمز | مثال | الشرح |
|---|---|---|---|
| إسناد أساسي | `=` | `a = b` | يعين قيمة `b` إلى `a`. |
| جمع مع إسناد | `+=` | `a += b` | يكافئ `a = a + b`. يضيف `b` إلى `a` ثم يخزن الناتج في `a`. |
| طرح مع إسناد | `-=` | `a -= b` | يكافئ `a = a - b`. يطرح `b` من `a` ويخزن الناتج. |
| ضرب مع إسناد | `*=` | `a *= b` | يكافئ `a = a * b`. يضرب القيمتين ويخزن الناتج. |
| قسمة مع إسناد | `/=` | `a /= b` | يكافئ `a = a / b`. يقسم `a` على `b` ويخزن الناتج. |
| باقي القسمة مع إسناد | `%=` | `a %= b` | يكافئ `a = a % b`. يخزن باقي القسمة في `a`. |
| إزاحة يسار مع إسناد | `<<=` | `a <<= 2` | يكافئ `a = a << 2`. يزح البتات لليسار ويخزن الناتج. |
| إزاحة يمين مع إسناد | `>>=` | `a >>= 2` | يكافئ `a = a >> 2`. يزح البتات لليمين ويخزن الناتج. |
| AND مع إسناد | `&=` | `a &= b` | يكافئ `a = a & b`. يحسب Bitwise AND ويخزن الناتج. |
| XOR مع إسناد | `^=` | `a ^= b` | يكافئ `a = a ^ b`. يحسب Bitwise XOR ويخزن الناتج. |
| OR مع إسناد | `|=` | `a |= b` | يكافئ `a = a | b`. يحسب Bitwise OR ويخزن الناتج. |
public class AssignmentOperatorsExample {
public static void main(String[] args) {
int x = 10;
int y = 5;
x += y; // x = x + y; x becomes 15
System.out.println("x after +=: " + x); // Output: 15
x -= y; // x = x - y; x becomes 10
System.out.println("x after -=: " + x); // Output: 10
x *= y; // x = x * y; x becomes 50
System.out.println("x after *=: " + x); // Output: 50
x /= y; // x = x / y; x becomes 10
System.out.println("x after /=: " + x); // Output: 10
}
}
يُستخدم كبديل مختصر لجملة `if-else` لتعيين قيمة لمتغير بناءً على شرط واحد.
الصيغة:
النتيجة = (الشرط) ? القيمة_إذا_صح : القيمة_إذا_خطأ;
public class TernaryOperatorExample {
public static void main(String[] args) {
int score = 75;
String result = (score >= 60) ? "ناجح" : "راسب";
System.out.println("النتيجة: " + result); // Output: ناجح
int num = 10;
String type = (num % 2 == 0) ? "زوجي" : "فردي";
System.out.println("الرقم " + num + " هو: " + type); // Output: الرقم 10 هو: زوجي
}
}
يُستخدم للتحقق مما إذا كان الكائن (Object) ينتمي إلى كلاس معين أو واجهة (interface) أم لا. يُرجع true إذا كان الكائن من النوع المحدد، و false بخلاف ذلك.
public class InstanceofExample {
public static void main(String[] args) {
String myString = "Hello Java";
Integer myInteger = 123;
System.out.println("myString instanceof String: " + (myString instanceof String)); // Output: true
System.out.println("myInteger instanceof Integer: " + (myInteger instanceof Integer)); // Output: true
System.out.println("myInteger instanceof Object: " + (myInteger instanceof Object)); // Output: true (Integer هو كائن من Object)
System.out.println("myString instanceof Integer: " + (myString instanceof Integer)); // Output: false
}
}
بعد فهم العوامل التي تساعدنا على كتابة الشروط والتعبيرات المنطقية، ننتقل إلى **الحلقات (Loops)**، وهي آلية أساسية في البرمجة تُستخدم لتكرار تنفيذ مجموعة من التعليمات البرمجية أكثر من مرة.
أهمية الحلقات تكمن في أنها تغنيك عن كتابة نفس الكود مرارًا وتكرارًا، مما يجعل الكود أقصر، أكثر قابلية للصيانة، وأقل عرضة للأخطاء. على سبيل المثال: إذا أردت طباعة الأرقام من 1 إلى 100، يمكنك استخدام حلقة بدلًا من كتابة 100 سطر كود منفصل.
الأوامر في العادة تتنفذ بتسلسل وراء بعضها. ولكن الحلقات تجعل سهم تنفيذ الأوامر يقف عندها، فيقوم بتنفيذ الأوامر التي بداخلها عدة مرات، و بعد أن يخرج من الحلقة يعود و يكمل تنفيذ باقي الأوامر الموجودة بعدها.
عندما تتنفذ الحلقة، فإن الأوامر الموضوعة فيها تنفذ بشكل منفصل عن باقي الأوامر الموجودة في البرنامج. أي يمكنك اعتبار أن جميع أوامر الحلقة توضع في مكان خاص في الذاكرة، هذا المكان يسمى **`scope` (نطاق)**. بعد أن تتنفذ جميع أوامر الحلقة في هذا الـ `scope`، يتم مسح الـ `scope` كلياً من الذاكرة، و هذه العملية تسمى **`Destroy` (إتلاف)**.
توفر Java ثلاثة أنواع رئيسية من الحلقات، كل منها مناسب لحالات استخدام معينة:
| اسم الحلقة | دواعي الإستخدام |
|---|---|
| For Loop | تستخدم الحلقة for في حال كان **عدد المرات التي سيعاد فيها تنفيذ الكود معروفاً** مسبقاً (مثلاً: كرر 10 مرات، اطبع الأرقام من 1 إلى 50). |
| While Loop | يفضل استخدام الحلقة while في حال كان **عدد المرات التي سيعاد فيها تنفيذ الكود غير معروف** مسبقاً، وتعتمد على تحقق شرط معين للاستمرار في التكرار (مثلاً: كرر طالما المستخدم لم يضغط على "خروج"). |
| Do-While Loop | تُشبه حلقة while، حيث يفضل استخدامها في حال كان عدد المرات التي سيعاد فيها تنفيذ الكود غير معروف، ولكنها تضمن أن يتم **تنفيذ الكود داخل الحلقة مرة واحدة على الأقل** قبل التحقق من الشرط. |
نستخدم جمل التحكم Control Statements للتحكم في سير تنفيذ الحلقات، وتُستخدم أيضًا مع جملة الشرط switch (التي سنتعرف عليها لاحقًا).
| جملة التحكم | تعريفها |
|---|---|
| Break Statement | تُستخدم في الحلقات وفي الجملة switch. بمجرد أن تُنفذ الجملة break، فإنها توقف الـ `scope` (النطاق) بأكمله وتخرج منه وتمسحه من الذاكرة، ثم ينتقل تنفيذ البرنامج إلى الكود الذي يلي الحلقة أو جملة `switch`. |
| Continue Statement | تُستخدم مع الحلقات فقط. نستخدمها لتجاوز تنفيذ جزء معين من الكود داخل التكرار الحالي للحلقة والانتقال مباشرة إلى التكرار التالي. إذاً، نستخدمها لتجاوز جزء من كود الـ `scope` الحالي فقط، دون الخروج من الحلقة كليًا. |
سنشرح الجملة break بالتفصيل مع الجملة switch في الوحدة القادمة، وسنقدم أمثلة عملية لكل من `break` و `continue` عند شرح الحلقات بأنواعها.
هذه التمارين ستساعدك على تطبيق المفاهيم التي تعلمتها في هذه الوحدة:
اكتب برنامج جافا يطلب من المستخدم إدخال طول وعرض مستطيل (أعداد عشرية). قم بحساب مساحة ومحيط المستطيل باستخدام العوامل الحسابية المناسبة، ثم اطبع النتائج على الكونسول. تأكد من استخدام `Scanner` ومعالجة الأخطاء المحتملة.
import java.util.Scanner;
import java.util.InputMismatchException;
public class RectangleCalculator {
public static void main(String[] args) {
Scanner input = new Scanner(System.in);
// اكتب الكود هنا
input.close();
}
}
اكتب برنامج يطلب من المستخدم إدخال عمره ودرجة حرارته. بناءً على هذه المدخلات، اطبع رسالة على الكونسول:
import java.util.Scanner;
import java.util.InputMismatchException;
public class HealthCheck {
public static void main(String[] args) {
Scanner input = new Scanner(System.in);
// اكتب الكود هنا
input.close();
}
}
اكتب برنامج يطلب من المستخدم إدخال رقم. استخدم العامل الشرطي (`?:`) لتحديد ما إذا كان الرقم زوجياً أم فردياً، ثم اطبع النتيجة. (تلميح: استخدم عامل باقي القسمة `%`).
import java.util.Scanner;
import java.util.InputMismatchException;
public class EvenOddChecker {
public static void main(String[] args) {
Scanner input = new Scanner(System.in);
// اكتب الكود هنا
input.close();
}
}
في هذه الوحدة، استكشفنا عالم **العوامل (Operators)** في Java، حيث تعلمنا كيفية استخدامها لإجراء عمليات حسابية ومنطقية ومعالجة البتات وإسناد القيم. كما تعرفنا على العوامل الشرطية و instanceof التي تزيد من مرونة الكود.
بعد ذلك، انتقلنا إلى فهم **الحلقات (Loops)**، وهي أدوات قوية لتكرار التعليمات البرمجية بكفاءة، مما يوفر الجهد ويحسن من قراءة الكود وصيانته. تعرفنا على الأنواع الرئيسية للحلقات: `for`، `while`، و `do-while`، بالإضافة إلى جمل التحكم `break` و `continue` التي تمنحنا تحكماً دقيقاً في سير التكرار.
هذه المفاهيم تُعد أساساً جوهرياً لأي مبرمج، فهي تمكنك من بناء منطق برنامجك والتحكم في تدفقه. في الوحدة القادمة، سنتعمق في **جمل التحكم الشرطية (If-Else, Switch)**، والتي ستسمح لبرامجك باتخاذ قرارات معقدة بناءً على الشروط، مما يزيد من ذكاء برامجك وقدرتها على الاستجابة لسيناريوهات مختلفة.