English | 简体中文 | 繁體中文 | Русский язык | Français | Español | Português | Deutsch | 日本語 | 한국어 | Italiano | بالعربية
Java 语言提供了许多修饰符,主要分为以下两类:
访问修饰符
معديف الوصول غير
修饰符用于定义类、方法或变量,通常放在语句的最前面。我们通过下面的实例来说明:
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 种不同的访问权限。
default (即默认,什么也不写): 在同一包内可见,不使用任何修饰符。使用对象:类、接口、变量、方法。
private : 在同一类内可见。使用对象:变量、方法。 注意:不能修饰类(外部类)
public : 对所有类可见。使用对象:类、接口、变量、方法
protected : 对同一包内的类和所有子类可见。使用对象:变量、方法。 注意:不能修饰类(外部类)。
我们可以通过以下表来说明访问权限:
访问控制
修饰符 | 当前类 | 同一包内 | 子孙类(同一包) | 子孙类(不同包) | 其他包 |
---|---|---|---|---|---|
public | Y | Y | Y | Y | Y |
protected | Y | Y | Y | Y/N(说明) | N |
default | Y | Y | Y | N | N |
private | Y | N | N | N | N |
使用默认访问修饰符声明的变量和方法,对同一个包内的类是可见的。接口里的变量都隐式声明为 public static final,而接口里的方法默认情况下访问权限为 public。
如下例所示,变量和方法的声明可以不使用任何修饰符。
package defaultPackage; class Logger { void message(){ System.out.println("This is a message"); } }
这里,Logger类有默认的访问修饰符。并且该类对属于defaultPackage包的所有类都可见。但是,如果我们试图在defaultPackage之外的另一个类中使用Logger类,我们将得到一个编译错误。
私有访问修饰符是最严格的访问级别,所以被声明为 private 的方法、变量和构造方法只能被所属类访问,并且类和接口不能声明为 private。
声明为私有访问类型的变量只能通过类中公共的 getter 方法被外部类访问。
Private 访问修饰符的使用主要用来隐藏类的实现细节和保护类的数据。
下面的类使用了私有访问修饰符:
public class Logger { private String format; public String getFormat() { return this.format; } public void setFormat(String format) { this.format = format; } }
في هذا المثال، هو متغير format في كلاس Logger هو متغير خاص، لذا لا يمكن للكلاسات الأخرى الحصول على قيمة هذا المتغير أو تعديلها. من أجل أن يتمكن الكلاسات الأخرى من تعديل هذا المتغير، تم تعريف طريقتين عامتين: getFormat() (تقوم بإرجاع قيمة format) و setFormat(String) (تقوم بتعيين قيمة format)
يمكن الوصول إلى الكلاسات والطرق والطرق والطابعات المعلنة بـ public من قبل أي كلاس آخر.
إذا كانت عدة كلاسات عامة متوزعة في حزم مختلفة، فإنه يجب استيراد الحزم التي تحتوي على هذه الكلاسات العامة. نظرًا للوراثة للكلاسات، يمكن للكلاسات الوراثية وراثة جميع الطرق والمتغيرات العامة للكلاسات.
استخدمت الطرق التالية الوصول العام:
public static void main(String[] arguments) { // ... }
يجب تعيين طريقة main() في Java كـ عامة، وإلا فإن معالج Java لن يتمكن من تشغيل هذا الكلاس.
تحليل وتوضيح protected يجب أن يتم من خلال النقاط التالية:
الصفحة الأمامية والصفحة الأمامية في نفس الحزمةيمكن الوصول إلى المتغيرات والطرق والمحركات المعلنة بـ protected من قبل أي كلاس آخر في نفس الحزمة؛
الصفحة الأمامية والصفحة الأمامية ليست في نفس الحزمةإذاً، في الصفحة الأمامية، يمكن للصفحة الأمامية مثال الوصول إلى الطرق المحتوية على protected التي ورثتها من الصفحة الأمامية، وليس يمكنها الوصول إلى طرق الصفحة الأمامية مثال بـ protected.
يمكن تزيينها بـ protected المتغيرات، طرق البناء، الطرق الأعضاء،لا يمكن تزيينها ( باستثناء الكلاسات الداخلية)。
لا يمكن إعلان المتغيرات والطرق والطابعات بـ protected.
يمكن للصفحة الأمامية الوصول إلى الطرق والمتغيرات المعلنة بـ protected، مما يتيح حماية الكلاسات غير المتعلقة من استخدام هذه الطرق والمتغيرات.
استخدمت الصفحة الأمامية للصفحات المحتوية على protected كـ ميزة الوصول، حيث تم تعديل طريقة openSpeaker() من قبل الصفحة الأمامية.
class AudioPlayer { protected boolean openSpeaker(Speaker sp) { // تفاصيل التنفيذ } } class StreamingAudioPlayer extends AudioPlayer { protected boolean openSpeaker(Speaker sp) { // تفاصيل التنفيذ } }
إذا تم إعلان طريقة openSpeaker() كـ private، فإن أي كلاس غير AudioPlayer لن يتمكن من الوصول إلى هذه الطريقة.
إذا تم تعريف openSpeaker() كpublic، فإن جميع الفئات ستكون قادرة على الوصول إلى هذه الطريقة.
إذا أردنا أن تكون الطريقة مرئية فقط للفئات الفرعية للفئة الحالية، فإنه يجب إعلان هذه الطريقة كprotected.
الوصول protected هو أكثر أنواع وصول أعضاء الفئة في Java تعقيدًا.
لاحظ قواعد توريث الطرق التالية:
يجب أن تكون الطريقة المعلنة كpublic في الفئة الأب أيضًا كpublic في الفئة الفرعية.
لا يمكن تعريف الطريقة المعلنة كprotected في الفئة الفرعية إلا كprotected أو public، لا يمكن تعريفها كprivate.
لا يمكن توريث الطريقة المعلنة كprivate في الفئة الأب.
لتحقيق بعض الوظائف الأخرى، قدم Java أيضًا العديد من المعديف غير الوصول.
المعديف static، يستخدم لتعدين الطرق والمتغيرات الفئوية.
المعديف final، يستخدم لتعدين الفئات والطرق والمتغيرات، لا يمكن توريث الفئة المعدة final، لا يمكن تعريف الطريقة المعدة final من قبل الفئة التي تعيد تعريفها، ويُعتبر المتغير المعد final متغيرًا ثابتًا وغير قابل للتغيير.
المعديف abstract، يستخدم لإنشاء الفئات التجريبية والطرق التجريبية.
المعديف synchronized وvolatile، يستخدمان بشكل رئيسي في برمجة الأنماط.
متغيرات الثابتة:
المفتاح static يُستخدم لبيان متغيرات ثابتة مستقلة عن الكائن، بغض النظر عن عدد كائنات الفئة التي يتم إنشاؤها، فإن متغيرات الثابتة تحتوي على نسخة واحدة فقط. تُسمى متغيرات الثابتة أيضًا متغيرات الفئة. لا يمكن إعلان متغيرات المحلية كمتغيرات static.
الطرق الثابتة:
المفتاح static يُستخدم لبيان طرق مستقلة عن الكائن. لا يمكن استخدام متغيرات الفئة غير المناسبة في الطرق الثابتة. تستلم الطرق الثابتة البيانات من قائمة المعلمات، ثم تقوم بحساب هذه البيانات.
يمكن الوصول إلى متغيرات الفئة والطرق مباشرة باستخدام classname.variablename و classname.methodname بصورة.
مثالًا، الم修饰ف static يُستخدم لإنشاء طرق الفئة ومتغيرات الفئة.
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("من " + InstanceCounter.getCount() + " instances start"); for (int i = 0; i < 500; ++i){ new InstanceCounter(); } System.out.println("Created " + InstanceCounter.getCount() + " instances"); } }
نتيجة التشغيل للعينة أعلاه كالتالي:
من 0 نموذج إنشاء 500 نموذج
متغيرات final:
يعني final "الأخير، النهائي"، لا يمكن إعادة تعيين المتغير المعدل بـ final. يجب أن يتم تحديد قيمة الابتدائية للمتغير المعدل بـ final.
عادة ما يتم استخدام ميزة final مع ميزة static لإنشاء كوفي الفئة.
public class Test{ final int value = 10; // هو مثال على إعلان الكوفي public static final int BOXWIDTH = 6; static final String TITLE = "Manager"; public void changeValue(){ value = 12; // سيتم إدخال خطأ } }
الطريقة النهائية
يمكن توريث الطريقة النهائية في الفئة الأبوية، ولكن لا يمكن تعديلها من قبل الفئة الفرعية.
الهدف الرئيسي لإعلان الطريقة النهائية هو منع تعديل محتواها.
كما هو موضح في المثال التالي، يتم إعلان الطريقة باستخدام ميزة final.
public class Test{ public final void changeName(){ // جسم الطريقة } }
الفئة النهائية
لا يمكن توريث الفئة النهائية، لا يوجد فئة يمكنها توريث أي خصائص من الفئة النهائية.
public final class Test { // جسم الفئة }
الفئة التجريبية:
لا يمكن استخدام الفئة التجريبية لإنشاء كائنات، الهدف الوحيد لإعلان الفئة التجريبية هو توسيعها في المستقبل.
لا يمكن لفئة واحدة أن تكون مزيجة بـ abstract و final في نفس الوقت. إذا كانت فئة تحتوي على طريقة抽象، فإنه يجب أن يتم إعلانها كفئة抽象ة، وإلا سيحدث خطأ في التجميع.
يمكن للفئة التجريبية أن تحتوي على طرق تجريبية وطرق غير تجريبية.
abstract class Caravan{ private double price; private String model; private String year; public abstract void goFast(); //طريقة تجريبية public abstract void changeColor(); }
الطريقة التجريبية
الطريقة التجريبية هي طريقة لا تحتوي على أي تنفيذ، وتتمكن الفئات الفرعية من تقديم التنفيذ الفعلي لها.
لا يمكن إعلان الطريقة التجريبية كـ final و static.
يجب على كل فئة تُتولد من فئة تجريبية تنفيذ جميع الطرق التجريبية للفئة الأصلية، ما لم تكن الفئة الفرعية أيضًا فئة تجريبية.
إذا كان يحتوي الكائن على عدة طرق تجريبية، فإن الكائن يجب أن يتم إعلانه كفئة تجريبية. يمكن للفئة التجريبية أن لا تحتوي على طرق تجريبية.
يُنتهي بفاصلة محورية إعلان الطريقة التجريبية، مثلًا:public abstract sample();。
public abstract class SuperClass{ abstract void m(); //طريقة تجريبية } class SubClass extends SuperClass{ //تحقيق الطريقة التجريبية void m(){ ...... } }
يُعلن عن طريقة مُزامنة يمكن الوصول إليها في وقت واحد فقط من قبل نواة واحدة. يمكن تطبيق تعديل synchronized على أربعة تعديلات الوصول.
public synchronized void showDetails(){ ...... }
عندما يحتوي الكائن المُسلسل على متغير مُعديل بـ transient، يقوم محرك JVM بتجاهل ذلك المتغير المحدد.
يُضمن هذا التعديل في جملة تعريف المتغير، ويستخدم لمعالجة نوع البيانات للفئات والمتغيرات.
public transient int limit = 55; //ُلن يتم التزامن public int b; //ُالمستدام
يتحقق التعديل volatile من إعادة قراءة قيمة المتغير كل مرة يتم الوصول إليها من قبل نواة، من ذاكرة الشبكة المشتركة. كما أن عند تغيير قيمة المتغير، يتم إجبار النواة على كتابة القيمة المعدلة إلى ذاكرة الشبكة المشتركة. بذلك، في أي لحظة، ستشاهد نواتان مختلفتان نفس القيمة للمتغير نفسه.
قد يكون مرجع العنصر volatile فارغًا.
public class MyRunnable implements Runnable { private volatile boolean active; public void run() { active = true; while (active) // السطر الأول { // الكود } } public void stop() { active = false; // السطر الثاني } }
في العادة، يتم استدعاء طريقة run() في نواة واحدة (في نواة مفتوحة بواسطة Runnable)، وفي نواة أخرى يتم استدعاء طريقة stop(). إذا السطر الأول إذا تم استخدام قيمة active في المخزن المؤقت، فإنه في السطر الثاني عندما يكون قيمة active = false لن يوقف الدوران.
لكن في هذا الكود استخدمنا ميزة volatile لتحسين active، لذا سيقف هذا الدوران.