توفر لغة جافا العديد من المعدلات، والتي تنقسم بشكل أساسي إلى الفئتين التاليتين:
يتم استخدام المعدلات لتحديد الفئات أو الأساليب أو المتغيرات، وعادة ما يتم وضعها في مقدمة البيان. ونوضح ذلك من خلال المثال التالي:
public class className { // ... } private boolean myFlag; static final double weeks = 9.5; protected static final int BOXWIDTH = 42; public static void main(String[] arguments) { // 方法体}
في Java، يمكن استخدام عناصر التحكم في الوصول لحماية الوصول إلى الفئات والمتغيرات والأساليب والمنشئات. تدعم Java 4 حقوق وصول مختلفة.
الافتراضي، والذي يسمى أيضًا الافتراضي، يكون مرئيًا داخل نفس الحزمة ولا يستخدم أي معدلات.
خاص، محدد بواسطة المعدل الخاص، مرئي داخل نفس الفئة.
عام، محدد بواسطة المعدل العام، مرئي لجميع الفئات.
محمي، محدد بواسطة المعدل المحمي، مرئي للفئات وجميع الفئات الفرعية في نفس الحزمة.
تكون المتغيرات والأساليب المعلنة باستخدام معدِّلات الوصول الافتراضية مرئية للفئات الموجودة في نفس الحزمة. يتم الإعلان ضمنيًا عن المتغيرات في الواجهة على أنها public static final
، وتتمتع الأساليب الموجودة في الواجهة بأذونات وصول public
بشكل افتراضي.
مثال:
كما هو موضح في المثال التالي، يمكن الإعلان عن المتغيرات والأساليب دون أية معدلات.
String version = "1.5.1"; boolean processOrder() { return true; }
يعد معدل الوصول الخاص هو مستوى الوصول الأكثر تقييدًا، لذلك لا يمكن الوصول إلى الأساليب والمتغيرات والمنشئات التي تم الإعلان عنها على أنها خاصة إلا من خلال الفئة التي تنتمي إليها، ولا يمكن الإعلان عن الفئات والواجهات على أنها خاصة.
لا يمكن الوصول إلى المتغيرات المعلنة كأنواع وصول خاصة إلا عن طريق الفئات الخارجية من خلال أساليب getter العامة في الفصل.
يتم استخدام معدل الوصول الخاص بشكل أساسي لإخفاء تفاصيل تنفيذ الفصل وحماية بيانات الفصل.
تستخدم الفئة التالية معدّل الوصول الخاص:
public class Logger { private String format; public String getFormat() { return this.format; } public void setFormat(String format) { this.format = format; } }
في المثال، متغير التنسيق في فئة المسجل هو متغير خاص، لذلك لا يمكن للفئات الأخرى الحصول على قيمة المتغير وتعيينها مباشرة. من أجل تمكين الفئات الأخرى من تشغيل هذا المتغير، تم تحديد طريقتين public
: getFormat()
(إرجاع قيمة التنسيق) و setFormat(String)
(تعيين قيمة التنسيق)
يمكن لأي فئة أخرى الوصول إلى الفئات والأساليب والمنشئات والواجهات المعلنة على أنها عامة.
إذا تم توزيع العديد من الفئات العامة التي تصل إلى بعضها البعض في حزم مختلفة، فستحتاج إلى استيراد الحزمة التي توجد بها الفئة العامة المقابلة. بسبب وراثة الفئة، يمكن وراثة جميع الأساليب والمتغيرات العامة للفئة من خلال فئاتها الفرعية.
تستخدم الوظائف التالية التحكم في الوصول العام:
public static void main(String[] arguments) { // ... }
يجب تعيين الأسلوب main() لبرنامج Java إلى عام، وإلا فلن يتمكن مترجم Java من تشغيل الفصل.
يمكن الوصول إلى المتغيرات والأساليب والمنشئات التي تم الإعلان عنها على أنها محمية بواسطة أي فئة أخرى في نفس الحزمة، أو عن طريق الفئات الفرعية في حزم مختلفة.
لا يمكن لمعدلات الوصول المحمية تعديل الفئات والواجهات، ويمكن إعلان أن الأساليب ومتغيرات الأعضاء محمية، ولكن لا يمكن إعلان أن متغيرات الأعضاء وأساليب الأعضاء في الواجهات محمية.
يمكن للفئات الفرعية الوصول إلى الأساليب والمتغيرات المعلنة باستخدام المعدل المحمي، وبالتالي حماية الفئات غير المرتبطة من استخدام هذه الأساليب والمتغيرات.
تستخدم الفئة الأصلية التالية معدل الوصول المحمي، وتتجاوز الفئة الفرعية طريقة openSpeaker() الخاصة بالفئة الأصلية.
class AudioPlayer { protected boolean openSpeaker(Speaker sp) { // 实现细节} } class StreamingAudioPlayer extends AudioPlayer { boolean openSpeaker(Speaker sp) { // 实现细节} }
إذا تم الإعلان عن أسلوب openSpeaker() كخاص، فلن تتمكن الفئات الأخرى غير AudioPlayer من الوصول إلى هذه الطريقة.
إذا تم الإعلان عن openSpeaker() كعام، فيمكن لجميع الفئات الوصول إلى هذه الطريقة.
إذا أردنا فقط أن تكون الطريقة مرئية للفئات الفرعية من فئتها، فقم بإعلان الطريقة على أنها محمية.
يرجى ملاحظة القواعد التالية لوراثة الطريقة:
يجب أن تكون الطرق المعلنة على أنها عامة في الفصل الأصلي أيضًا عامة في الفصل الفرعي.
يتم الإعلان عن الطرق المعلن عنها على أنها محمية في الفئة الأصلية إما على أنها محمية أو عامة في الفئة الفرعية. لا يمكن إعلانها خاصة.
لا يمكن وراثة الأساليب التي تم الإعلان عنها على أنها خاصة في الفئة الأصل.
من أجل تنفيذ بعض الوظائف الأخرى، توفر Java أيضًا العديد من معدلات عدم الوصول.
مُعدِّل ثابت، يُستخدم لإنشاء أساليب الفصل ومتغيرات الفصل.
يتم استخدام المعدل النهائي لتعديل الفئات والأساليب والمتغيرات، ولا يمكن توريث الفئات التي تم تعديلها بواسطة Final، ولا يمكن إعادة تعريف الأساليب المعدلة بواسطة الفئات الموروثة، والمتغيرات المعدلة هي ثوابت ولا يمكن تعديلها.
مُعدِّل تجريدي، يُستخدم لإنشاء فئات مجردة وأساليب مجردة.
تُستخدم المعدلات المتزامنة والمتقلبة بشكل أساسي لبرمجة الخيوط.
المتغيرات الثابتة:
يتم استخدام الكلمة الأساسية الثابتة للإعلان عن المتغيرات الثابتة المستقلة عن الكائنات. وبغض النظر عن عدد الكائنات التي تقوم فئة ما بإنشاء مثيل لها، فهناك نسخة واحدة فقط من المتغيرات الثابتة الخاصة بها. تُعرف المتغيرات الثابتة أيضًا باسم متغيرات الفئة. لا يمكن تعريف المتغيرات المحلية كمتغيرات ثابتة.
الطريقة الثابتة:
يتم استخدام الكلمة الأساسية الثابتة للإعلان عن طرق ثابتة مستقلة عن الكائنات. لا يمكن للطرق الثابتة استخدام المتغيرات غير الثابتة للفئة. تحصل الطرق الثابتة على البيانات من قائمة المعلمات ثم تحسب البيانات.
يمكن الوصول إلى متغيرات وأساليب الفئة مباشرةً باستخدام classname.variablename
و classname.methodname
.
كما هو موضح في المثال التالي، يتم استخدام المعدل الثابت لإنشاء أساليب الفئة ومتغيرات الفئة.
public class InstanceCounter { private static int numInstances = 0; protected static int getCount() { return numInstances; } private static void addInstance() { numInstances++; } InstanceCounter() { InstanceCounter.addInstance(); } public static void main(String[] arguments) { System.out.println("Starting with " + InstanceCounter.getCount() + " instances"); for (int i = 0; i < 500; ++i){ new InstanceCounter(); } System.out.println("Created " + InstanceCounter.getCount() + " instances"); } }
نتائج التحرير لتشغيل المثال أعلاه هي كما يلي:
Started with 0 instances Created 500 instances
المتغيرات النهائية:
يمكن تهيئة المتغيرات النهائية بشكل صريح ولمرة واحدة فقط. لا يمكن أن تشير المراجع إلى الكائنات التي تم إعلانها نهائية إلى كائنات مختلفة. ولكن يمكن تغيير البيانات الموجودة في الكائن النهائي. بمعنى آخر، لا يمكن تغيير مرجع الكائن النهائي، ولكن يمكن تغيير القيمة الموجودة بداخله.
غالبًا ما يتم استخدام المعدل النهائي مع المعدل الثابت لإنشاء ثوابت الفئة.
مثال:
public class Test{ final int value = 10; // 下面是声明常量的实例public static final int BOXWIDTH = 6; static final String TITLE = "Manager"; public void changeValue(){ value = 12; //将输出一个错误} }
يمكن وراثة الطريقة النهائية في الفصل الدراسي بواسطة الفئات الفرعية، لكن لا يمكن تعديلها بواسطة الفئات الفرعية.
الغرض الرئيسي من إعلان الطريقة النهائية هو منع تعديل محتويات الطريقة.
كما هو موضح أدناه، أعلن عن الطريقة باستخدام المعدل النهائي.
public class Test{ public final void changeName(){ // 方法体} }
لا يمكن وراثة الفئات النهائية، ولا يمكن لأي فئة أن ترث أي خصائص للفئة النهائية.
مثال:
public final class Test { // 类体}
فئة مجردة:
لا يمكن استخدام الفئات المجردة لإنشاء مثيل للكائنات. الغرض الوحيد من الإعلان عن فئة مجردة هو توسيع الفئة في المستقبل.
لا يمكن تعديل الفصل بالملخص والنهائي في نفس الوقت. إذا كانت الفئة تحتوي على أساليب مجردة، فيجب الإعلان عن الفئة كفئة مجردة، وإلا سيحدث خطأ في الترجمة.
يمكن أن تحتوي الفئات المجردة على طرق مجردة وطرق غير مجردة.
مثال:
abstract class Caravan{ private double price; private String model; private String year; public abstract void goFast(); //抽象方法public abstract void changeColor(); }
الطريقة المجردة هي طريقة بدون أي تطبيق ويتم توفير التنفيذ المحدد للطريقة بواسطة الفئة الفرعية. لا يمكن إعلان الطرق المجردة نهائية وثابتة.
أي فئة فرعية ترث فئة مجردة يجب أن تطبق جميع الأساليب المجردة للفئة الأصلية، ما لم تكن الفئة الفرعية أيضًا فئة مجردة.
إذا كان الفصل يحتوي على عدة طرق مجردة، فيجب إعلان الفصل مجردًا. لا تحتاج الفئة المجردة إلى احتواء أساليب مجردة.
ينتهي الإعلان عن الطريقة المجردة بفاصلة منقوطة، على سبيل المثال: public Abstract Sample();
مثال:
public abstract class SuperClass{ abstract void m(); //抽象方法} class SubClass extends SuperClass{ //实现抽象方法void m(){ ......... } }
لا يمكن الوصول إلى الطريقة المعلنة باستخدام الكلمة الأساسية المتزامنة إلا من خلال مؤشر ترابط واحد في نفس الوقت. يمكن تطبيق المعدل المتزامن على أربعة معدلات وصول.
مثال:
public synchronized void showDetails(){ ....... }
عندما يحتوي الكائن المتسلسل على متغير مثيل تم تعديله بواسطة عابر، فإن Java Virtual Machine (JVM) يتخطى هذا المتغير المعين.
يتم تضمين هذا المعدل في العبارة التي تحدد المتغير ويستخدم للمعالجة المسبقة لنوع بيانات الفئة والمتغير.
مثال:
public transient int limit = 55; // will not persist public int b; // will persist
في كل مرة يتم فيها الوصول إلى متغير عضو تم تعديله بواسطة مؤشر ترابط، يتم فرض إعادة قراءة قيمة متغير العضو من الذاكرة المشتركة. علاوة على ذلك، عندما يتغير متغير عضو، يضطر الخيط إلى كتابة القيمة المتغيرة مرة أخرى إلى الذاكرة المشتركة. بهذه الطريقة، في أي وقت، يرى خيطان مختلفان دائمًا نفس قيمة متغير العضو.
قد يكون مرجع الكائن المتطاير فارغًا.
مثال:
public class MyRunnable implements Runnable { private volatile boolean active; public void run() { active = true; while (active) // line 1 { // 代码} } public void stop() { active = false; // line 2 } }
بشكل عام، يتم استدعاء أسلوب run() في موضوع واحد ويتم استدعاء أسلوب stop() في موضوع آخر. إذا تم استخدام قيمة نشط في السطر 1 في المخزن المؤقت، فلن تتوقف الحلقة عند تعيين نشط في السطر 2 على خطأ.