عند إعلان الخصائص والأساليب والفئات في Java ، يمكن استخدام الكلمة الرئيسية النهائية لتعديلها. المتغير النهائي ثابت ولا يمكن تعيينه إلا مرة واحدة ؛ لا يمكن إعادة كتابة الطريقة النهائية بواسطة فئة فرعية ؛ لا يمكن مورث الفصل النهائي.
1. الأعضاء النهائية
إن الإعلان عن الحقل النهائي يساعد المُحسّن على اتخاذ قرارات تحسين أفضل ، لأنه إذا كان المترجم يعلم أن قيمة الحقل لن تتغير ، فيمكنه أن يقوم بأمان بتخزين القيمة في السجل. يوفر الحقل النهائي أيضًا مستوى إضافيًا من الأمان من خلال جعل برنامج التحويل البرمجي يجبر الحقل على القراءة فقط.
1.1 حول مهمة العضو النهائي
1) في Java ، يمكن تهيئة المتغيرات العادية افتراضيًا. ولكن يجب تهيئة متغيرات النوع النهائي بشكل صريح.
2) يمكن للأعضاء النهائيين تهيئة ولا يمكن تهيئتها إلا مرة واحدة.
3) يجب تهيئة العضو النهائي عند الإعلان (تعيين قيمة مباشرة إلى المتغير النهائي عند تعريفه) أو في المنشئ ، ولا يمكن تهيئته في مكان آخر.
مثال 1 BAT.JAVA
BAT CLASS BAT {Final Double PI = 3.14 ؛ // تعيين int النهائي I عند تعريفه ؛ // لأنه يجب تهيئته في المُنشئ ، لا يمكن تعيين القائمة النهائية <BAT> هنا ؛ // لأنه يجب تهيئته في المنشئ ، لا يمكن تعيين BAT () هنا {i = 100 ؛ list = new LinkedList <BAT> () ؛ } BAT (int II ، قائمة <TR> l) {i = ii ؛ قائمة = ل ؛ } public static void main (string [] args) {bat b = new bat () ؛ B.List.Add (New BAT ()) ؛ // bi = 25 ؛ // B.List = new ArrayList <BAT> () ؛ System.out.println ("i =" + bi + "نوع القائمة:" + b.list.getClass ()) ؛ B = BAT جديد (23 ، ArrayList جديد <BAT> ()) ؛ B.List.Add (New BAT ()) ؛ System.out.println ("i =" + bi + "نوع القائمة:" + b.list.getClass ()) ؛ }}
نتيجة:
i = 100 نوع القائمة: class java.util.linkedListi = 23 نوع القائمة: class java.util.arraylist
هناك سطرين من العبارات في الطريقة الرئيسية التي تم التعليق عليها. إذا قمت بإزالة التعليق ، فلن يتمكن البرنامج من التجميع. هذا يعني أنه بغض النظر عما إذا كانت قيمة i أو نوع القائمة ، بمجرد تهيئة ذلك ، لا يمكن تغييرها. ومع ذلك ، يمكن لـ B تحديد قيمة I أو نوع القائمة عن طريق إعادة تحديد.
1.2 تهيئة غير صالحة للحقل المرجعي النهائي
إنه أمر مزعج بعض الشيء لاستخدام الحقل النهائي بشكل صحيح ، خاصة بالنسبة لمراجع الكائنات التي يمكن لملائمهم إلقاء استثناءات. نظرًا لأنه يجب تهيئة الحقل النهائي مرة واحدة فقط في كل مُنشئ ، إذا كان المنشئ المشار إليه من قبل الكائن النهائي قد يرمي استثناء ، فقد يبلغ المترجم عن خطأ يقول أنه لم يتم تهيئة الحقل. يكون المترجم ذكيًا بشكل عام بما يكفي لتجد أن التهيئة في كل فرع من فرعين رمز Mutex (على سبيل المثال ، إذا ... كتل أخرى) يحدث مرة واحدة فقط ، ولكن عادةً ما يكون "مسامحة" للمحاولة ...
الرمز التالي عادة ما يكون لديه مشاكل.
class thingie {public static thingie getDefaultthingie () {return new thingie () ؛ }} الفئة العامة foo {private thingie thingie ؛ public foo () {try {thingie = new thingie () ؛ } catch (استثناء e) {thingie = thingie.getDefaultthingie () ؛ // error: الحقل النهائي ربما تم تعيين Thingie بالفعل}}}
يمكنك تعديل هذا.
الفئة العامة foo {private for thingie thingie ؛ public foo () {thingie tempthingie ؛ جرب {tempthingie = new thingie () ؛ } catch (استثناء e) {tempthingie = thingie.getDefaultthingie () ؛ } thingie = tempthingie ؛ }}
1.3 حول استخدام العضو النهائي
عندما تحدد متغيرًا في فئة ما ، أضف الكلمة الرئيسية النهائية قبلها ، وهذا يعني أنه بمجرد تهيئة هذا المتغير ، لا يمكن تغييره. معنى الثبات هنا هو أن قيمتها غير قابلة للتغيير للنوع الأساسي ، ولا يمكن تغيير مرجعه بعد الآن لمتغير الكائن. ومع ذلك ، يمكن تعديل الكائنات نفسها ، ولا توفر Java طريقة لجعل أي كائنات ثابتة. هذا القيد يتناسب أيضا في المصفوفات ، والتي هي الأشياء.
مثال 2
Private Final int Val_One = 9 ؛ Final Static Final Val_two = 99 ؛ Final Static Final Val_three = 999 ؛
نظرًا لأن Val_One و Val_Tow هما أنواع بدائية نهائية مع قيم وقت الترجمة ، يمكن استخدام كلاهما كثوابت وقت الترجمة ولا يوجد فرق كبير. Val_three هي طريقة أكثر نموذجية لتحديد الثوابت: تم تعريفها على أنها عامة ، ويمكن استخدامها خارج الحزمة ؛ يُعرّف بأنه ثابت للتأكيد على نسخة واحدة فقط ؛ تم تعريفه على أنه نهائي للإشارة إلى أنه ثابت.
يصبح النهائي المتغير المتغير ثابتًا ، ولكن لا يمكن استخدام هذا "الثابت" إلا داخل هذه الفئة ولا يمكن استخدامه مباشرة خارج الفصل. ومع ذلك ، عندما نستخدم النهائي الثابت العام للاحتفال الثابت ، يصبح هذا الثابت ثابتًا عالميًا (وهو حقل ثابت ونهائي فقط يحتل مساحة تخزين لا يمكن تغييره). علاوة على ذلك ، لا يمكن تعيين الثوابت المحددة بهذه الطريقة إلا قيمًا عند تحديدها ، ولا يمكن استخدامها في مكان آخر.
مثال 3
قيمة الفئة {int i ؛ القيمة العامة (int i) {this.i = i ؛ }} الفئة العامة FinalData {private static random rand = new Random () ؛ معرف السلسلة الخاص ؛ public FinalData (string id) {this.id = id ؛ } private Final int i4 = rand.nextint (20) ؛ ثابت نهائي int i5 = rand.nextint (20) ؛ السلسلة العامة toString () {return id + ":" + "i4:" + i4 + "، i5 =" + i5 ؛ } public static void main (string [] args) {finalData fd1 = new FinalData ("fd1") ؛ System.out.println (FD1) ؛ System.out.println ("إنشاء FinalData جديد") ؛ FinalData fd2 = new FinalData ("fd2") ؛ System.out.println (FD1) ؛ System.out.println (FD2) ؛ }}
نتيجة
FD1: i4: 6 ، i5 = 3 Creating FinalDatafd1: i4: 6 ، i5 = 3fd2: i4: 17 ، i5 = 3
يوضح قسم الأمثلة الفرق بين تحديد القيمة النهائية على أنها ثابتة (I5) وغير قاسية (I4). لن يظهر هذا الاختلاف إلا عند تهيئة القيمة أثناء وقت التشغيل ، لأن المترجم يعامل القيمة المترجمة بالتساوي. (وقد تختفي من التحسين.) سترى هذا الاختلاف عند تشغيل البرنامج. لاحظ أنه في FD1 و FD2 ، لا يمكن تغيير قيمة i5 عن طريق إنشاء كائن FinalData الثاني. هذا لأنه ثابت ، يتم تهيئته في التحميل ، وليس في كل مرة يتم فيها إنشاء كائن جديد.
مثال 4
قيمة الفئة {int i ؛ القيمة العامة (int i) {this.i = i ؛ }} الفئة العامة ... {private value v1 = new value (11) ؛ القيمة النهائية الخاصة v2 = قيمة جديدة (22) ؛ القيمة النهائية الثابتة الخاصة v3 = قيمة جديدة (33) ؛ ...} الفراغ الثابت العام (سلسلة [] args) {... fd1.v2.i ++ ؛ // ok-object ليس ثابتًا! fd1.v1 = قيمة جديدة (9) ؛ // ok-not fd1.v2 = قيمة جديدة (0) ؛ // خطأ: لا يمكن تغيير المرجع fd1.v3 = قيمة جديدة (1) ؛ // خطأ: لا يمكن تغيير المرجع ...} توضح المتغيرات من V1 إلى V3 معنى المراجع النهائية. كما ترون في Main () ، لا يمكنك التفكير في أنه لا يمكنك تغيير قيمته لمجرد أن V2 نهائي. نظرًا لأنه مرجع ، يعني النهائي أنه لا يمكنك توجيه V2 إلى كائن جديد آخر مرة أخرى.
مثال 5
الفئة العامة ... {private Final int [] a = {1،2،3،4،5،6} ؛ ...} main static void main (string [] args) {... لـ (int i = 0 ؛ i <fd1.a.length ؛ i ++) fd1.a [i] ++ ؛ // ok-object ليس ثابتًا! fd1.a = int جديد [3] ؛ // خطأ: لا يمكن تغيير المرجع ...} وجود نفس المعنى للمصفوفة (يمكن أن يغير قيمته ، ولكن لا يمكن أن يشير إلى كائن جديد) ، فإن الصفيف هو مرجع آخر.
1.4 حل حدود المصفوفات النهائية
على الرغم من أنه يمكن إعلان مراجع الصفيف النهائية ، إلا أن عناصر الصفيف لا يمكن. هذا يعني أنه لا توجد الفئات التي تكشف حقول المصفوفة النهائية العامة أو إرجاع المراجع إلى تلك الحقول من خلال أساليبها.
// غير قابل للتغيير - يمكن تعديل مجموعة الدول بواسطة خبيث // callerpublicclass dangerousstates {private final string [] states = new string [] {"Alabama" ، "Alaska" ، "ECT"} ؛ السلسلة العامة [] getStates () {states return ؛ }}
وبالمثل ، على الرغم من أنه يمكن إعلان مرجع الكائن كحقل نهائي ، إلا أن الكائن الذي يشير إليه قد لا يزال قابلاً للتغيير. إذا كنت ترغب في إنشاء كائن ثابت باستخدام الحقل النهائي ، فيجب عليك منع الإشارات إلى المصفوفات أو الكائنات القابلة للتغيير من "الهروب" من فصلك. للقيام بذلك دون الحاجة إلى استنساخ المصفوفة بشكل متكرر ، تتمثل إحدى الطرق السهلة في تحويل الصفيف إلى قائمة.
// immutable - إرجاع قائمة غير قابلة للشفاء بدلاً من ذلك ، فإن PublicClass Safestates {private Final String [] stater = new string [] {"Alabama" ، "Alaska" ، "ECT"} ؛ القائمة النهائية الخاصة stateaslist = new AbstractList () {الكائن العام get (int n) {return States [n] ؛ } size int public () {return States.Length ؛ }} ؛ القائمة العامة getStates () {return StatesAslist ؛ }}
1.5 حول استخدام المعلمات النهائية
استخدام آخر هو تحديد المعلمة في الطريقة النهائية. بالنسبة لمتغيرات الأنواع الأساسية ، لا يكون لهذا أي أهمية عملية ، لأن متغيرات الأنواع الأساسية تمرر القيم عند استدعاء الطريقة ، أي يمكنك تغيير متغير المعلمة في الطريقة دون التأثير على عبارة الاتصال. ومع ذلك ، بالنسبة لمتغيرات الكائنات ، فهي عملية للغاية لأن متغيرات الكائن يتم تمريرها مراجعها عند المرور. وبهذه الطريقة ، سيؤثر تعديل متغيرات الكائن في الطريقة أيضًا على متغيرات الكائن في عبارة الاتصال. عندما لا تحتاج إلى تغيير متغيرات الكائن كمعلمات في الطريقة ، فإن استخدام النهائي بشكل صريح للإعلان سيمنعك من تعديل وتؤثر على طريقة الاتصال.
1.6 حول متغيرات المعلمات في الفئات الداخلية
بالإضافة إلى ذلك ، عند استخدام متغيرات المعلمة في الطريقة في الفئة الداخلية ، يجب إعلان متغير المعلمة هذا النهائي قبل استخدامه.
مثال 6 inclass.java
الفئة العامة inclass {void innerclass (سلسلة نهائية str) {class iclass {iclass () {system.out.println (str) ؛ }} iclass ic = new iClass () ؛ } public static void main (string [] args) {inclass inc = new inclass () ؛ Inc.InnerClass ("Hello") ؛ }} 2. الطريقة النهائية
2.1 استخدام الطريقة النهائية
1) من أجل التأكد من أن سلوك وظيفة معينة يبقى دون تغيير أثناء عملية الميراث ولا يمكن تجاوزه ، يمكن استخدام الطريقة النهائية.
2) جميع الأساليب الخاصة والثابتة في الفصل نهائي بشكل طبيعي.
2.2 الكلمات الرئيسية النهائية والخاصة
يتم تحديد جميع الأساليب الخاصة في الفصل ضمنيًا لتكون نهائية. نظرًا لأنه لا يمكن استخدام الطريقة الخاصة ، لا يمكن الكتابة عليها.
لن يظهر "تجاوز" إلا إذا كانت الطريقة جزءًا من واجهة الفئة الأساسية. وهذا يعني أن الكائن يجب أن يكون قادرًا على تحويله إلى نوعه البدائي واتصل بنفس الطريقة. إذا كانت الطريقة خاصة ، فهي ليست جزءًا من واجهة الفئة الأساسية. إنه مجرد رمز مخفي في الفصل ، ولكن بنفس الاسم. ومع ذلك ، إذا تم إنشاء طريقة وصول جمهور أو محمي أو حزمة بنفس الطريقة في فئة التصدير ، فلن تنتج الطريقة حالة "فقط بنفس الاسم" التي تحدث في الفئة الأساسية. في هذه المرحلة ، لم تتجاوز الطريقة ، فقط أنشأت طريقة جديدة. نظرًا لأنه لا يمكن لمس الطريقة الخاصة ويمكن إخفاءها بشكل فعال ، فلا يجب النظر إلى أي شيء آخر باستثناء وجود الهيكل التنظيمي للفصل الذي ينتمي إليه.
3. الفصل النهائي
عندما يتم تعريف الفصل على أنه نهائي ، لا يمكن ورث الفصل. ولأن الفئة النهائية تحظر الميراث ، يتم تحديد جميع الأساليب في الفصل النهائي ضمنيًا على أنها نهائية لأنه لا يمكن الكتابة فوقها.
يتم استخدام النهائي في الفصول أو الأساليب لمنع الروابط بين الأساليب من كسرها. على سبيل المثال ، افترض أن تنفيذ طريقة الفئة X يفترض أن الطريقة M ستعمل بطريقة ما. إن إعلان X أو M كنهائي سيمنع الفئة المشتقة من إعادة تعريف M بهذه الطريقة ، مما تسبب في عمل X بشكل غير طبيعي. على الرغم من أنه قد يكون من الأفضل تنفيذ X بدون هذه الارتباطات الداخلية ، إلا أن هذا ليس ممكنًا دائمًا ، ويمكن استخدام النهائي أن يمنع التغييرات غير المتوافقة في المستقبل.
ملاحظة: الفرق بين النهائي ، وأخيرا وينتهي