أول برنامج وبنية الكود الأساسية
كل برنامج جافا يبدأ من مكان واحد: الكلاس والميثود الرئيسي. لنفهم الشكل العام أولًا.
تخيّل أن برنامج جافا مثل مدرسة: المدرسة هي class (الكلاس)، وداخلها يوجد مكان محدد يبدأ منه اليوم الدراسي وهو main (الميثود الرئيسي). عندما تشغّل البرنامج، جافا تبحث عن main وتبدأ منه مباشرة.
لا تحاول فهم كل كلمة الآن — تعرّف على الشكل العام أولًا ومع كل تمرين ستتضح الصورة أكثر. والأهم: اقرأ الكود سطرًا سطرًا من الأعلى إلى الأسفل كأنك تقرأ وصفة طبخ: نفّذ هذا السطر، ثم انتقل للذي تحته.
public class Hello { public static void main(String[] args) { System.out.println("Hello World!"); }}
ماذا يعني كل سطر؟
- public class Helloننشئ صندوقًا (كلاس) اسمه Hello. يجب أن يطابق اسم الملف: Hello.java
- { }الأقواس المعقوفة تحدد حدود الكلاس وحدود كل جزء داخله.
- public static void main(...)هذه هي الميثود الرئيسي — نقطة بداية البرنامج. جافا تبدأ التنفيذ من أول سطر داخلها.
- public static voidثلاث كلمات تسبق دائمًا كلمة main — معناها الدقيق موضوع متقدم، فاحفظ هذا الشكل كما هو في كل برنامج تكتبه.
- String[] argsمعلومة جاهزة تكتب بين القوسين كما هي — لن نحتاج تغييرها في هذه الورشة، فلا تشغل بالك بها.
- System.out.println(...)أمر الطباعة: اعرض ما بداخل الأقواس على الشاشة ثم انزل سطرًا جديدًا.
- ;كل أمر في جافا ينتهي بفاصلة منقوطة. نسيانها أشهر خطأ عند المبتدئين!
جرب بنفسك — اضغط على أي سطر لترى دوره
public class Hello {public static void main(String[] args) { System.out.println("Hello World!"); }}
ماذا يحدث عند الضغط على «تشغيل»؟
- تبحث جافا عن main وتقف عند أول سطر داخل أقواسها { }.
- تنفّذ الأسطر واحدًا تلو الآخر من الأعلى إلى الأسفل — لا تتخطى أي سطر.
- عند الوصول إلى القوس الختامي } ينتهي البرنامج وتظهر المخرجات.
ميثود الطباعة
نافذتك لرؤية ما يحدث داخل البرنامج — كل ما تطبعه يظهر على الشاشة.
لدينا شكلان رئيسيان من ميثود الطباعة:
- System.out.println(...) — تطبع النص ثم تنزل سطرًا جديدًا (ln اختصار line).
- System.out.print(...) — تطبع النص وتبقى في نفس السطر.
| الميثود | تنزل سطرًا جديدًا؟ | مثال على المخرجات |
|---|---|---|
| println("Hello") | نعم — كل استدعاء في سطر مستقل | Hello⏎ |
| print("Hello") | لا — تلتصق بطبعة الاستدعاء التالي | Hello (no newline) |
شغّل هذا المثال وقارن الطريقتين على نفس الكلمات — الفرق يظهر بوضوح في عدد الأسطر:
public class PrintVsPrintln { public static void main(String[] args) { // println: each word on its own line System.out.println("Hello"); System.out.println("World"); // print: both words stick on one line System.out.print("Hello"); System.out.print(" World"); }}
public class PrintDemo { public static void main(String[] args) { System.out.println("Hello"); System.out.print("I am a student"); System.out.println(" in the Java workshop"); System.out.println("The result of 2 + 3 is: " + (2 + 3)); }}
توقّع قبل أن تشغّل
اقرأ الكود أعلاه وحاول تخمين ماذا سيظهر على الشاشة قبل الضغط على «▶ تشغيل» — ثم قارن توقعك بالنتيجة.
- كل println تبدأ سطرًا جديدًا — فتظهر Hello في سطر مستقل.
- أما print فتبقى في مكانها — لذلك تلتصق "I am a student" و" in the Java workshop" معًا في السطر الثاني.
- الجملة الأخيرة تدمج نصًا مع ناتج عملية حسابية بإشارة +: "The result of 2 + 3 is: " + (2 + 3) فتطبع: The result of 2 + 3 is: 5
الدمج: التصاق النصوص بإشارة +
عندما تضع إشارة + بين قيمتين يفحص جافا طرفيها: إذا كان أحدهما نصًا فلن يحسب شيئًا — بل يلصق القيمتين جنبًا إلى جنب في نص واحد. وإذا كان الطرفان أرقامًا فعلًا، يجمعهما حسابًا. وعند تتابع عدة إشارات + يُقرأ التعبير من اليسار إلى اليمين، فيبدأ الالتصاق من أول إشارة يكون أحد طرفيها نصًا. لهذا تستطيع بناء جملة كاملة من قطع صغيرة:
شاهد الدمج خطوة بخطوة في الدرس 3·1
| التعبير | الناتج | لماذا؟ |
|---|---|---|
| "مرحبا " + "سارة" | مرحبا سارة | نص + نص يلتصقان مباشرة |
| "العمر: " + 17 | العمر: 17 | الرقم يُحوَّل تلقائيًا إلى نص ثم يُلصق |
| "17" + 5 | 175 | النص أولًا — لصق لا جمع! |
| 5 + "17" | 517 | يُقرأ من اليسار: يلتصق 5 بالنص قبل أي حساب |
| 1 + 2 + "a" | 3a | الطرفان الأولان رقمان فيُجمعان أولًا (3)، ثم يلتصق النص — الالتصاق يبدأ عند أول نص فقط |
| "الناتج: " + (2 + 3) | الناتج: 5 | الأقواس تجبر الحساب على الانتهاء قبل الالتصاق |
public class MergeDemo { public static void main(String[] args) { String name = "Sara"; int age = 17; System.out.println("Name: " + name); // Name: Sara System.out.println("Next year: " + (age + 1)); // Next year: 18 — الأقواس جمعت أولًا System.out.println("Without brackets: " + age + 1); // Without brackets: 171 — التصاق! System.out.println("Sum = " + (2 + 3) + " not " + 2 + 3); // Sum = 5 not 23 }}
إنشاء المتغيرات
المتغير صندوق عليه ملصق اسم — تخزن فيه قيمة وتغيّرها وقتما تشاء.
في لعبتك المفضلة مثلًا، نقاطك ورصيدك واسم شخصيتك كلها متغيرات يحدّثها البرنامج أثناء اللعب. ولصنع «الصندوق» نحدد ثلاثة أشياء بالترتيب: نوع البيانات (ماذا يخزن؟)، ثم الاسم (كيف نناديه؟)، ثم القيمة (ماذا نضع فيه؟). وتجدر الإشارة أن علامة = هنا تعني «ضع فيه» وليست مساواة رياضية كما في الرياضيات.
اقرأ هذا السطر كأنه جملة عربية: int age = 17; تعني: «أنشئ صندوقًا نوعه int اسمه age وضع فيه الرقم 17». أما السطر الخامس في المثال بالأسفل (age = 18;) فيعني فقط: «خذ صندوق age الموجود وضع فيه قيمة جديدة».
public class Variables { public static void main(String[] args) { int age = 17; // a box for whole numbers String name = "Sara"; // a box for text double gpa = 4.75; // a box for decimal numbers age = 18; // changing the variable's value System.out.println("Name: " + name); System.out.println("Age: " + age); System.out.println("GPA: " + gpa); }}
قواعد تسمية المتغيرات
- يبدأ الاسم بحرف (مثل age) أو _ أو $، ولا يبدأ برقم أبدًا.
- بدون مسافات داخل الاسم: استخدم studentName بدلًا من student name.
- لا تستخدم كلمات محجوزة في جافا مثل class أو public.
- لا تعرّف نفس الاسم مرتين في البرنامج — لكل صندوق اسم واحد فقط.
- اختر اسمًا يصف المحتوى: age أفضل من x.
| الاسم | الحكم | السبب |
|---|---|---|
| studentName | ✓ ممتاز | يصف المحتوى ويتبع نمط camelCase: كلمة أولى صغيرة، وكبير أول حرف مما يليها |
| 1name | ✗ مرفوض | يبدأ برقم — الأسماء يجب أن تبدأ بحرف أو _ أو $، وسيرفضه المترجم بخطأ |
| s_n | ✗ غير معبّر | مقبول نحويًا لكنه غير مقروء — من يقرأه لن يفهم أنه اسم الطالب |
الكلمات المحجوزة — أسماء لا يجوز استخدامها
لغة جافا «احتفظت» لنفسها بمجموعة كلمات لتبني بها جملها — لكل منها مهمة محددة في البرنامج، ولا يجوز أن تستخدمها اسمًا لمتغير أو ميثود. لاحظ أنك رأيت كل هذه الكلمات بالفعل في أمثلة الدروس:
هذه هي الكلمات التي تحتاجها في الورشة — أما جافا الكاملة ففيها نحو 50 كلمة محجوزة إضافية ستقابلها تدريجيًا.
منشئ المتغير — ابنِ الجملة بنفسك
قبل أن تكتب الكود حرًّا، تدرّب على ترتيب البنية هنا: اختر النوع، اكتب اسمًا، اكتب قيمة تطابق النوع، ثم اضغط «ابنِ الجملة». سيصحح لك المنشئ أي خطأ فورًا.
تدرّب قبل التمرين — ثلاثة أسئلة سريعة
String name = "Sara"; int age = 17; age = 18; System.out.println(name + " " + age);
المتغير الثابت (final)
أحيانًا نريد صندوقًا يُغلق بقفل — قيمة تُكتب مرة واحدة ولا تتغير أبدًا.
نضيف الكلمة المحجوزة final قبل تعريف المتغير. القيمة تُعيَّن مرة واحدة فقط، وأي محاولة لتغييرها لاحقًا تُنتج خطأ في الترجمة — وهذا يحمينا من الأخطاء غير المقصودة.
تخيّل أن برنامجك يستخدم سعر التذكرة في عشرة أسطر مختلفة — لو عرّفته ثابتًا باسم TICKET_PRICE، فعند تغيّر السعر تعدّله في مكان واحد، ويمنعك جافا من تغييره بالخطأ في مكان آخر.
لماذا لا نكتفي بمجرد «عدم تغييره»؟
قد تقول: سأعرّف المتغير عاديًا وأتعهد أنا ألا أغيّره! لكن البرامج الكبيرة تُكتب على أسابيع وتُعدَّل بأيدٍ كثيرة — والتعهد وحده ينكسر. final تحوّل القاعدة من «اتفاق» إلى ضمان يفرضه المترجم نفسه: لو خالفها أحد — حتى أنت بعد ستة أشهر — يتوقف البرنامج برسالة خطأ واضحة قبل أن يعمل، فيُكتشف الخطأ فورًا بدل أن يسبب نتائج خفية خاطئة.
public class Constants { public static void main(String[] args) { final double PI = 3.14159; // constant: its value never changes final int DAYS_IN_WEEK = 7; double radius = 5.0; double area = PI * radius * radius; // circle area // PI = 3.14; ← error! cannot change a constant System.out.println("Days in a week: " + DAYS_IN_WEEK); System.out.println("Circle area: " + area); }}
متى نستخدم الثوابت؟
- قيم ثابتة معروفة: PI، عدد أيام الأسبوع، سرعة الضوء.
- قيم تحدد مرة واحدة في بداية البرنامج ولا يجوز لأحد تعديلها بالخطأ — مثل سعر التذكرة أو الحد الأقصى للاعبين MAX_PLAYERS.
- قيم «سياسة» قد تتغير مع الوقت لكنها ثابتة أثناء تشغيل البرنامج: نسبة الضريبة TAX_RATE، درجة النجاح PASSING_GRADE، رسالة ترحيب موحدة.
جرّب كسر القفل بنفسك
في المثال أعلاه يوجد سطر معلّق: // PI = 3.14; ← error! — افتح «✎ تعديل»، واحذف علامتي التعليق // من بدايته واضغط «▶ تشغيل». سيمنعك المترجم برسالة تقول إن PI ثابت لا يتغيّر، وستشاهد السطر المخالف مظللًا بالأحمر في المحرر — هذا بالضبط ما تعنيه الحماية: الخطأ يُقفل في مكانه قبل أن يصل إلى شاشة الطالب.
final int PRICE = 5;
int qty = 3;
System.out.println("Total: " + (PRICE * qty));أنواع بيانات المتغيرات
لكل صندوق حجم ومادة — اختيار النوع الصحيح يوفر الذاكرة ويمنع الأخطاء.
| النوع | ما يخزنه | مثال |
|---|---|---|
| int | أرقام صحيحة بدون كسور | int age = 17; |
| double | أرقام عشرية (بكسور) | double price = 9.99; |
| char | حرف واحد فقط بين علامتين تنصيص مفردتين | char grade = 'A'; |
| boolean | قيمة منطقية: صواب أو خطأ | boolean passed = true; |
| String | نص (كلمة أو جملة) بين علامتين تنصيص مزدوجتين | String name = "Sara"; |
كيف أختار النوع الصحيح؟
اسأل نفسك هذا السؤال عن القيمة التي تريد تخزينها، والإجابة تحدد النوع مباشرة:
- رقم صحيح بدون كسور (عمر، عدد طلاب)؟ ← int
- رقم فيه كسر (سعر، معدل، طول)؟ ← double
- حرف واحد فقط (تقدير، درجة)؟ ← char
- الجواب نعم أو لا فقط؟ ← boolean
- أي شيء آخر: اسم، كلمة، جملة كاملة؟ ← String
بطاقات الأنواع — اقلبها للتعرف عليها
int age = 17;double price = 9.99;char grade = 'A';boolean passed = true;String name = "Sara";public class DataTypes { public static void main(String[] args) { int students = 32; double height = 1.72; char grade = 'A'; boolean isEnrolled = true; String course = "Java Basics"; System.out.println("Students: " + students); System.out.println("Height: " + height + " m"); System.out.println("Grade: " + grade); System.out.println("Enrolled in course? " + isEnrolled); System.out.println("Course name: " + course); // try the difference between a number-like String and a real number: System.out.println("Text with a number glued on: " + "17" + 5); // result: 175 System.out.println("Number actually added: " + (17 + 5)); // result: 22 }}
تحدي: أين الخطأ؟
في كل مقطع خطأ واحد مخبأ لن يمرّ البرنامج معه. اقرأ الكود بتمعّن واضغط على السطر المخالف.
المقطع ١: هذا البرنامج لن يُترجم. أين الخطأ؟
قارن نهايات الأسطر في البرنامج: بعضها يحتاج إشارة ختامية نسيتها هنا.
المقطع ٢: خطأ في نوع البيانات. أين؟
تذكّر الفرق بين علامتي التنصيص في الدرس الخامس.
المقطع ٣: البرنامج لن يُترجم من الأساس. أين الخطأ؟
اسأل نفسك: ماذا تعني الكلمة التي قبل نوع المتغير في السطر الثالث؟
اقرأ الخطأ
المهارة الأهم عند المبتدئين: قراءة رسالة الخطأ قبل الهرعة لتغيير الكود. في المقطعين التاليين البرنامج لن يعمل — مهمتك أولًا أن تترجم رسالة الخطأ العربية (أي سطر؟ ما نوع الخطأ؟) قبل أن تصلحه بنفسك.
المقطع ١: شغّل الكود كما هو واقرأ الرسالة بتمعّن — في أي سطر توقّف المترجم؟ وماذا كان يتوقع أن يرى؟
public class Bug1 { public static void main(String[] args) { int age = 16 System.out.println("My age: " + age); }}
المقطع ٢: هذا البرنامج يستخدم متغيرًا قبل أن يُعرَّف — شغّله ولاحظ أي سطر تشتكي منه الرسالة.
public class Bug2 { public static void main(String[] args) { System.out.println(score); int score = 10; }}
تمارين الوحدة ١
تمارين على دروس الوحدة الأولى (بنية الكود، الطباعة، المتغيرات، الثوابت، الأنواع). كل تمرين أمامه كود ناقص: اضغط «✎ تعديل»، اكتب الكود المطلوب مكان التعليقات، اضغط «✔ حفظ» ثم «▶ تشغيل» — وقارن نتيجتك بالهدف المكتوب أسفل كل تمرين.
أمامك برنامج يطبع بطاقة تعريف طالب، لكن تعريف المتغيرات الثلاثة ناقص. أكملها: اسم الطالب name كنص، وعمره age كرقم صحيح، ومعدله gpa كرقم عشري.
public class Exercise1 { public static void main(String[] args) { // 1) define a String variable name with your name // 2) define an int variable age with your age // 3) define a double variable gpa with your GPA System.out.println("Name: " + name); System.out.println("Age: " + age); System.out.println("GPA: " + gpa); }}
Name: (your name) Age: (your age) GPA: (your GPA)
سعر لتر الوقود ثابت ويساوي 2.05. أكمل البرنامج: عرّف الثابت LITER_PRICE باستخدام final، ثم احسب تكلفة تعبئة 40 لترًا في المتغير total (السعر مضروبًا في عدد اللترات).
public class Exercise2 { public static void main(String[] args) { // 1) define the constant LITER_PRICE = 2.05 using final int liters = 40; // 2) compute the total cost in a double variable total System.out.println("Total cost: " + total + " SAR"); }}
Total cost: 82.0 SAR
أكمل سطرين: عرّف متغيرًا منطقيًا isOnline قيمته true، ومتغيرًا من نوع char اسمه level قيمته 'B'.
public class Exercise3 { public static void main(String[] args) { // 1) define a boolean variable isOnline with the value true // 2) define a char variable level with the value 'B' System.out.println("Online? " + isOnline); System.out.println("Level: " + level); }}
Online? true Level: B
الميثود الرئيسي فارغ تمامًا! اكتب بنفسك ثلاث جمل طباعة تُخرج الجملة التالية في سطر واحد — استخدم print للجزأين الأولين وprintln للأخيرة.
public class Exercise4 { public static void main(String[] args) { // write 3 print statements that output the sentence on one line }}
My name is Laila and I am 15 years old