الحقول والدوال الساكنة (Static)
الحقول والدوال الساكنة (Static)
كل حقل ودالة كتبتهما حتى الآن ينتميان إلى كائن بعينه — لكل كائن BankAccount رصيده الخاص، واستدعاء deposit() على كائن لا يمسّ الآخرين. لكن في بعض الأحيان تحتاج إلى بيانات أو سلوك ينتمي إلى الصنف نفسه، مشتركًا بين كل الكائنات. هذا بالضبط ما تمنحك إياه الكلمة المفتاحية static.
الأعضاء المرتبطة بالكائن مقابل الأعضاء المرتبطة بالصنف
الفرق بسيط لكنه مهم:
- عضو مرتبط بكائن (Instance) — لكل كائن نسخته الخاصة. يتم الوصول إليه عبر مرجع الكائن (
account.balance). - عضو ساكن (Static / Class) — نسخة واحدة مشتركة بين كل الصنف. يُصَل إليه عبر اسم الصنف (
BankAccount.totalAccounts).
تخيّل الأمر هكذا: قد يتتبّع صنف Car عدد السيارات التي صُنعت. هذا العدد لا ينتمي لـسيارة واحدة — بل ينتمي لمفهوم السيارة بالكامل.
الحقول الساكنة (Static Fields)
تُعلن الحقل الساكن بإضافة الكلمة static قبل النوع:
بغضّ النظر عن عدد كائنات BankAccount الموجودة، فإن totalAccounts هو عدد صحيح واحد في الذاكرة. إنشاء كائن جديد يزيده للجميع.
الدوال الساكنة (Static Methods)
تُستدعى الدالة الساكنة على الصنف لا على كائن. ولأنه لا يوجد كائن ضمنيًا، لا تستطيع الدالة الساكنة الوصول إلى حقول الكائن أو استدعاء دواله — فلا يوجد مرجع this.
لقد استخدمت الدوال الساكنة طوال الوقت في Java: Math.sqrt() وInteger.parseInt() ونقطة الدخول public static void main(String[] args) كلها دوال ساكنة.
main ساكنة؟ تحتاج الآلة الافتراضية (JVM) إلى استدعاء main دون إنشاء كائن أوّلًا. تتيح الخاصية الساكنة للبيئة التشغيلية استدعاء الدالة مباشرةً على الصنف — دون الحاجة إلى مُنشئ.
الثوابت عبر static final
الثابت هو قيمة لا تتغيّر أبدًا. في Java، تُعلن الثوابت بـ static final وتُسمّى بالأحرف الكبيرة مع الشرطة السفلية UPPER_SNAKE_CASE وفق التقليد المتعارف عليه:
static— نسخة واحدة للصنف، لا إهدار للذاكرة لكل كائن.final— لا يمكن إعادة تعيين القيمة بعد التهيئة.
Circle.PI تُخبر القارئ بما تعنيه القيمة. بينما كتابة 3.14159 متناثرةً في عشرات الدوال خطر صيانة — فإذا احتجت يومًا تغيير الدقة، فعليك إيجاد كل موضع وتعديله.
كتل التهيئة الساكنة (Static Initializer Blocks)
أحيانًا يحتاج الحقل الساكن إلى أكثر من تعيين بسيط للتهيئة — مثل بناء جدول بحث. استخدم كتلة التهيئة الساكنة:
تُنفَّذ الكتلة مرة واحدة عندما تُحمَّل الصنف لأول مرة من قِبل JVM — قبل إنشاء أي كائن.
الأخطاء الشائعة
this أو حقول الكائن. إذا استدعيت دالة كائن من سياق ساكن، يُشير المُصرِّف فورًا إلى الخطأ: "non-static method cannot be referenced from a static context". هذا من أكثر أخطاء المبتدئين شيوعًا في Java.
a1.getTotalAccounts() تبدو كأنها تستدعي شيئًا على a1، لكنها تقرأ قيمة الصنف المشتركة. استخدم دائمًا اسم الصنف (BankAccount.getTotalAccounts()) لتوضيح القصد.
متى تستخدم static؟
- دوال مساعدة / أدوات — حسابات خالصة بلا حالة (مثل
Math.abs()). - الثوابت — قيم متماثلة لكل مستخدمي الصنف.
- عدادات أو ذاكرات تخزين مؤقت على مستوى الصنف — بيانات تنتمي للنوع لا لكائن.
- دوال المصنع (Factory Methods) — دوال ساكنة تبني كائنات وتُعيدها (ستأتي لاحقًا).
تجنّب جعل كل شيء ساكنًا لمجرد تجنّب إنشاء كائنات. الإفراط في استخدام static يُضعف البرمجة الكائنية — يكسر التغليف، يُصعّب الاختبار، ويُدخل حالة مشتركة خفية يمكن أن تُسبب أخطاءً دقيقة.
الخلاصة
الحقول والدوال الساكنة تنتمي إلى الصنف لا إلى كائنات بعينها. استخدم static للعدادات المشتركة، والدوال المساعدة، والثوابت (static final). تُهيّئ كتل التهيئة الساكنة حالةً ساكنة مركّبة عند تحميل الصنف. ابقِ استخدام static محدودًا — الجأ إليه حين يعود المفهوم فعلًا للنوع، لا حين تريد فقط تخطّي إنشاء كائن.