محمية
دعنا نتحدث عن قضايا حقوق الوصول المحمية. انظر المثال 1 أدناه:
test.java
class myobject {} اختبار الفئة العامة {public static void main (string [] args) {myObject obj = new myobject () ؛ obj.clone () ؛ // خطأ ترجمة. }} استنساخ الطريقة من كائن النوع غير مرئي.
لقد فهمنا بالفعل أن Object.clone () طريقة محمية. هذا يدل على أنه يمكن الوصول إلى الطريقة عن طريق الفئات الفرعية لنفس الحزمة (java.lang) و IT (java.lang.object). إليكم فئة myobject (الميراث الافتراضي لـ java.lang.object).
وبالمثل ، فإن الاختبار هو أيضًا فئة فرعية من java.lang.object. ومع ذلك ، لا يمكن الوصول إلى الطريقة المحمية للكاسورة الفرعية الأخرى في فئة فرعية واحدة ، على الرغم من أن الفئات الفرعية ترثان من نفس فئة الوالدين.
دعونا نلقي نظرة على المثال 2 مرة أخرى:
test2.java
class myObject2 {consuged object clone () remsloSuptupportedException {return super.clone () ؛ }} الفئة العامة test2 {public static void main (string [] args) يلقي clonenotsupportedException {myobject2 obj = new myobject2 () ؛ obj.clone () ؛ // ترجمة موافق. }} هنا ، نقوم بتجاوز طريقة Clone () للفئة الأصل في فئة MyObject2 ، والاتصال بالطريقة Clone () في اختبار فئة آخر ، وتجميع ومرور.
سبب التجميع واضح. عند تجاوز طريقة clone () في فئة myobject2 ، تكون فئة myobject2 وفئة Test2 تحت نفس الحزمة ، لذلك تكون هذه الطريقة المحمية مرئية لفئة Test2.
في هذه المرحلة ، نتذكر العبارات الواردة في الفصل 2.2 في مقالات النسخ الضحلة والعميقة في Java ، ② الكتابة فوق طريقة Clone () للفئة الأساسية في الفئة المشتقة وإعلانها على أنها عامة. الآن أفهم سبب هذه الجملة (من أجل تمكين الفئات الأخرى من استدعاء طريقة Clone () لهذه الفئة ، بعد التحميل الزائد ، يجب تعيين سمة Clone () على الأماكن العامة).
دعونا نلقي نظرة على المثال 3:
Test3.java
حزمة 1class myobject3 {محمية كائن clone () يلقي clonenotsupportedException {return super.clone () ؛ }} package 2public class test3 تمتد myobject3 {public static void main (string args []) {myobject3 obj = new myobject3 () ؛ obj.clone () ؛ // خطأ ترجمة. Test3 tobj = new test3 () ؛ tobj.clone () ؛ // coeft ok. }} هنا أستخدم فئة Test3 لروث myobject3. لاحظ أن هاتين الفئتين لهما حزم مختلفة ، وإلا فإن هذا هو الحال في المثال 2. في فئة Test3 ، استدعاء طريقة clone () لمثيل TOBJ من فئة test3 وتجميعها والتمرير. وأيضًا استدعاء طريقة clone () لمثيل OBJ لفئة myobject3 ، وخطأ التجميع!
نتائج غير متوقعة ، ألا يمكن الوصول إلى الطريقة المحمية بواسطة الفئات الموروثة؟
يجب أن يكون من الواضح أن اختبار الفئة 3 لا يرث myObject3 (بما في ذلك طريقة استنساخه) ، بحيث يمكنك استدعاء طريقة الاستنساخ الخاصة بك في اختبار الفئة 3. ومع ذلك ، فإن الطريقة المحمية للفئة MyObject3 غير مرئية لاختبار الفئة الفرعية المختلفة للكعكة.
إليك ممر آخر من "Java in a Notshell":
يتطلب الوصول المحمي المزيد من المختبر. لنفترض أن الفئة A تعلن عن حقل محمي X ويتم تمديده بواسطة الفئة B ، والتي يتم تعريفها في حزمة مختلفة (هذه النقطة الأخيرة مهمة). يرث الفئة B الحقل المحمي X ، ويمكن أن يصل رمزه إلى هذا الحقل في المثيل الحالي لـ B أو في أي مثيلات أخرى من B التي يمكن أن يشير إليها الرمز. هذا لا يعني ، مع ذلك ، أن مدونة الفئة ب يمكن أن تبدأ في قراءة الحقول المحمية للمثيلات التعسفية لـ A! إذا كان الكائن مثيلًا لـ A ولكنه ليس مثيلًا لـ B ، فمن الواضح أن حقوله ليست موروثة من قبل B ، ولا يمكن لقراءتها من الفئة B قراءتها.
بالمناسبة ، يتم وصف العديد من كتب Java في الصين بشكل عام بهذه الطريقة عند تقديم أذونات الوصول (أشكال مختلفة ومحتوى ثابت):
التحكم في الوصول إلى الطريقة:
ثابت
1. الكلمة الرئيسية ثابتة (تذكر هذه أولاً ، ثم اقرأها لأسفل)
1) الأساليب الثابتة والمتغيرات الثابتة هي كائنات تنتمي إلى فئة معينة ، ولكن ليس إلى فئة.
2) يتم الرجوع مباشرة إلى الإشارات إلى الأساليب الثابتة والمتغيرات الثابتة من خلال أسماء الفصول.
3) لا يمكن استدعاء الأساليب غير الستاطية والمتغيرات غير المنتظمة في الأساليب الثابتة. خلاف ذلك ، لا بأس.
4) تشبه المتغيرات الثابتة المتغيرات العالمية بلغات أخرى في بعض البرامج ، ويمكن الوصول إليها خارج الفصل إذا لم تكن خاصة.
2. متى تستخدم ثابت
عندما نقوم بإنشاء مثيل لفئة (كائن) ، نستخدم عادة الطريقة الجديدة بحيث يتم إنشاء مساحة بيانات هذه الفئة ويمكن استدعاء أساليبها.
ومع ذلك ، في بعض الأحيان نأمل أنه على الرغم من أنه يمكن إنشاء فئة باستخدام كائنات N (من الواضح أن مساحة بيانات هذه الكائنات N مختلفة) ، فإن بعض بيانات هذه الكائنات N هي نفسها ، أي بغض النظر عن عدد الحالات التي لدى الفصل ، فإن البيانات تحتوي على نسخة ذاكرة من هذه الحالات (انظر المثال 1). هذا هو الحال مع المتغيرات الثابتة.
سيناريو آخر هو أنك تريد طريقة لا ترتبط بأي كائن من الفئة التي تحتوي عليها. وهذا يعني ، يمكن استدعاء هذه الطريقة حتى إذا لم يتم إنشاء الكائن. يتمثل أحد الاستخدامات المهمة للطريقة الثابتة في تسميتها دون إنشاء أي كائن (انظر المثال 2). هذا هو الحال مع طريقة ثابتة.
هناك أيضًا استخدام خاص في الطبقات الداخلية. عادة ، لا يُسمح بإعلان فئة طبيعية ثابتة ، بل يمكن للطبقة الداخلية فقط القيام بذلك. في هذا الوقت ، يمكن استخدام هذه الفئة الداخلية المعلنة على أنها ثابتة مباشرة كفئة طبيعية دون الحاجة إلى مثال فئة خارجية (انظر المثال 3). هذا هو الحال مع الطبقات الثابتة.
مثال 1
الطبقة العامة tstatic {static int i ؛ TSTATATION () {i = 4 ؛ } tstatic public (int j) {i = j ؛ } public static void main (String args []) {system.out.println (tstatic.i) ؛ tstatic t = tstatic جديد (5) ؛ // إعلان مرجع الكائن وتثبيته. في هذا الوقت i = 5 system.out.println (ti) ؛ tstatic tt = new tstatic () ؛ // إعلان مرجع الكائن وتثبيته. في هذا الوقت i = 4 system.out.println (ti) ؛ system.out.println (tt.i) ؛ system.out.println (ti) ؛ }}
نتيجة:
05444
يتم إنشاء المتغير الثابت عند تحميل الفصل. طالما وجود الفصل ، يوجد المتغير الثابت. يجب تهيئتها عند تحديدها. في المثال أعلاه ، لم يتم تهيئتها ، لذلك سيتم الحصول على القيمة الأولية الافتراضية 0. لا يمكن تهيئة المتغير الثابت إلا مرة واحدة ، والمتغير الثابت يقبل فقط التهيئة الأخيرة.
في الواقع ، لا تزال هذه مشكلة في مثيلات متعددة تشارك متغيرًا ثابتًا.
مثال 2
لم يعلن أنه ثابت
classa classa {int b ؛ public void ex1 () {} classb {void ex2 () {int i ؛ classa a = new classa () ؛ أنا = أب ؛ // هنا الوصول إلى المتغير العضو B A.Ex1 () من خلال مرجع الكائن ؛ // هنا الوصول إلى وظيفة العضو ex1 من خلال مرجع الكائن}}}
أعلن أنه ثابت
فئة classa {static int b ؛ static void ex1 () {}} classb {void ex2 () {int i ؛ i = classa.b ؛ // هنا الوصول إلى متغير الأعضاء B classa.ex1 () من خلال اسم الفصل ؛ // هنا الوصول إلى وظيفة العضو ex1 من خلال اسم الفصل}} عند استخدام طرق ثابتة ، احرص على أنه لا يمكن استدعاء الأساليب غير الستراتية في الأساليب الثابتة والمرجع المتغيرات الأعضاء غير الاستقليوية (لا يمكن الرجوع إلى هذا أو الفائق بأي شكل من الأشكال في الطرق الثابتة). السبب بسيط للغاية. بالنسبة للأشياء الثابتة ، عندما يقوم JVM بتحميل الفصل ، فإنه يفتح هذه المساحات الثابتة في الذاكرة (بحيث يمكن الرجوع إليها مباشرة من خلال اسم الفصل) ، وفي هذا الوقت ، لم يتم إنشاء الفئة التي توجد بها الأساليب غير المنتظمة والمتغيرات الأعضاء.
لذا ، إذا كنت ترغب في استخدام الأساليب غير المنتظمة والمتغيرات الأعضاء ، فيمكنك إنشاء إنشاء فئة مباشرة حيث توجد الطريقة أو المتغير العضو في الطريقة الثابتة. هكذا يفعل ذلك الفراغ الأساسي العام.
مثال 3
الطبقة العامة staticcls {public static void main (string [] args) {OuterCls.InnerCls oi = new OuterCls.innercls () ؛ // ليست هناك حاجة إلى OuterCls جديدة قبل هذا}} outtercls {public static class innercls {Innercls () {system.out.println ( }}}
نتيجة:
innercls
3. التهيئة الثابتة
ستؤدي المتغيرات التي تحددها الثابتة إلى الأسبقية على أي متغيرات أخرى غير طبيعية ، بغض النظر عن الترتيب الذي تظهر به. يتم استخدام كتلة التعليمات البرمجية الثابتة (تليها قطعة من الكود) لتنفيذ التهيئة المتغيرة الثابتة الصريحة. سيتم تهيئة هذا الرمز إلا مرة واحدة وعندما يتم تحميل الفصل لأول مرة. انظر المثال أدناه.
قيمة الفئة {static int c = 0 ؛ value () {c = 15 ؛ } value (int i) {c = i ؛ } static void inc () {c ++ ؛ }} count count {public static void prt (string s) {system.out.println (s) ؛ } value v = new value (10) ؛ قيمة ثابتة V1 ، v2 ؛ ثابت {prt ("في الكتلة الثابتة من cals count v1.c =" + v1.c + "v2.c =" + v2.c) ؛ v1 = قيمة جديدة (27) ؛ PRT ("في الكتلة الثابتة لـ Cals Count v1.c =" + v1.c + "v2.c =" + v2.c) ؛ v2 = قيمة جديدة () ؛ PRT ("في الكتلة الثابتة لـ Cals Count v1.c =" + v1.c + "v2.c =" + v2.c) ؛ }} الفئة العامة tstaticblock {public static void main (string [] args) {count ct = new count () ؛ count.prt ("في Main:") ؛ count.prt ("ct.c =" + ct.vc) ؛ count.prt ("v1.c =" + count.v1.c + "v2.c =" + count.v2.c) ؛ count.v1.inc () ؛ count.prt ("v1.c =" + count.v1.c + "v2.c =" + count.v2.c) ؛ count.prt ("ct.c =" + ct.vc) ؛ }}
نتيجة:
في الكتلة الثابتة لعدد Calss V1.c = 0 v2.c = 0 في الكتلة الثابتة لعدد Calss V1.c = 27 v2.c = 27 في الكتلة الثابتة من calss count v1.c = 15 v2.c = 15 في main: ct.c = 10v1.c = 10 v2
سواء كانت V أو V1 أو V2 ، فإن متغيرات الأعضاء التي تعمل عليها هي نفس المتغير الثابت C.
في عدد الفئة ، V1 و V2 (القيمة الثابتة V1 ، V2 ؛) ، ثم تهيئة كتلة الكود الثابت (ثابت {}) ، وأخيراً تهيئة V.