سؤال

جئت عبر التعليمات البرمجية التالية في قاعدة التعليمات البرمجية أعمل على:

public final class ConfigurationService {
    private static final ConfigurationService INSTANCE = new ConfigurationService();
    private List providers;

    private ConfigurationService() {
        providers = new ArrayList();
    }

    public static void addProvider(ConfigurationProvider provider) {
        INSTANCE.providers.add(provider);
    }

    ...

INSTANCE أعلن كما final. وبعد لماذا يمكن إضافة الكائنات إلى INSTANCEب لا ينبغي أن يبطل استخدام نهائي. (لا).

أفترض أن الإجابة يجب أن تفعل شيئا مع المؤشرات والذاكرة ولكن أود أن أعرف بالتأكيد.

هل كانت مفيدة؟

المحلول

final ببساطة يجعل الكائن المرجعي غير قابل للتغيير. الكائن الذي يشير إليه ليس ثابتا عن طريق القيام بذلك. INSTANCE لا يمكن أن تشير أبدا إلى كائن آخر، ولكن الكائن الذي يشير إليه قد يغير الحالة.

نصائح أخرى

كونك نهائيا ليس هو نفسه غير قابل للتغيير.

final != immutable

ال final يتم استخدام الكلمة الأساسية للتأكد من عدم تغيير المرجع (أي، المرجع الذي لا يمكن استبداله به جديد)

ولكن، إذا كانت السمة ذاتية تعد قابلة للتعديل فلا بأس في فعل ما وصفته للتو.

على سبيل المثال

class SomeHighLevelClass {
    public final MutableObject someFinalObject = new MutableObject();
}

إذا كنا مثيل لهذه الفئة، فلن نتمكن من تعيين قيمة أخرى إلى السمة someFinalObject لأنه هو أخير.

لذلك هذا غير ممكن:

....
SomeHighLevelClass someObject = new SomeHighLevelClass();
MutableObject impostor  = new MutableObject();
someObject.someFinal = impostor; // not allowed because someFinal is .. well final

ولكن إذا كان الكائن الخاص به هو قابل للتغيير مثل هذا:

class MutableObject {
     private int n = 0;

     public void incrementNumber() {
         n++;
     }
     public String toString(){
         return ""+n;
     }
}  

بعد ذلك، قد يتم تغيير القيمة الواردة بواسطة كائن قابل للتغيير.

SomeHighLevelClass someObject = new SomeHighLevelClass();

someObject.someFinal.incrementNumber();
someObject.someFinal.incrementNumber();
someObject.someFinal.incrementNumber();

System.out.println( someObject.someFinal ); // prints 3

هذا له نفس التأثير الذي نشرته:

public static void addProvider(ConfigurationProvider provider) {
    INSTANCE.providers.add(provider);
}

أنت هنا لا تتغير قيمة المثلية، تقوم بتعديل حالتها الداخلية (VIA، PROVEDERS.ADD)

إذا كنت ترغب في منع أن يتم تغيير تعريف الفصل مثل هذا:

public final class ConfigurationService {
    private static final ConfigurationService INSTANCE = new ConfigurationService();
    private List providers;

    private ConfigurationService() {
        providers = new ArrayList();
    }
    // Avoid modifications      
    //public static void addProvider(ConfigurationProvider provider) {
    //    INSTANCE.providers.add(provider);
    //}
    // No mutators allowed anymore :) 
....

ولكن، قد لا تجعل الكثير من المعنى :)

بالمناسبة، عليك أيضا مزامنة الوصول إليها أساسا لنفس السبب.

المفتاح لسوء الفهم هو في عنوان سؤالك. انها ليست هدف وهو نهائي، إنه عامل. وبعد لا يمكن تغيير قيمة المتغير، ولكن البيانات الموجودة داخلها.

تذكر دائما أنه عندما تعلن متغير نوع مرجعي، فإن قيمة هذا المتغير هو مرجع وليس كائن.

أخير يعني فقط عدم تغيير المرجع. لا يمكنك إعادة تعيين المثيل إلى مرجع آخر إذا تم الإعلان عنه نهائيا. الحالة الداخلية للكائن لا تزال قابلة للتغيير.

final ConfigurationService INSTANCE = new ConfigurationService();
ConfigurationService anotherInstance = new ConfigurationService();
INSTANCE = anotherInstance;

سوف رمي خطأ تجميع

مرة final تم تعيين متغير، فإنه يحتوي دائما على نفس القيمة. اذا كان final يحمل المتغير إشارة إلى كائن، ثم قد يتم تغيير حالة الكائن عن طريق العمليات على الكائن، لكن المتغير سيشير دائما إلى نفس الكائن. هذا ينطبق أيضا على صفائف، لأن الصفائف هي كائنات؛ اذا كان final يحمل المتغير مرجعا إلى صفيف، ثم قد يتم تغيير مكونات الصفيف حسب العمليات على الصفيف، لكن المتغير سيشير دائما إلى نفس الصفيف.

مصدر

إليك دليل صنع كائن ثابت.

النهائي وغير القابل للتغيير ليس بنفس الشيء. النهائي يعني أن المرجع لا يمكن إعادة تعيينه حتى لا تستطيع القول

INSTANCE = ...

يعني غير ثابت أن الكائن نفسه لا يمكن تعديله. مثال على هذا هو java.lang.String صف دراسي. لا يمكنك تعديل قيمة السلسلة.

ليس لدى Java مفهوم عدم القدرة المدمجة في اللغة. لا توجد طريقة للاحتفال بطرق مختلفة. وبالتالي فإن اللغة ليس لديها طريقة لفرض كائن غير قابل للاستخدام.

مرخصة بموجب: CC-BY-SA مع الإسناد
لا تنتمي إلى StackOverflow
scroll top