هناك كلمة أساسية في Java - final. يمكن تطبيقه على الفئات والأساليب والمتغيرات (بما في ذلك وسائط الطريقة). نهائي جدا... - 1بالنسبة للفئة، هذا يعني أن الفئة لا يمكن أن تحتوي على فئات فرعية، أي. الميراث حرام . يعد هذا مفيدًا عند إنشاء immutableكائنات (غير قابلة للتغيير)، على سبيل المثال فئة Stringتم تعريفها على أنها final.
public final class String{
}

class SubString extends String{ //Compilation error
}
تجدر الإشارة أيضًا إلى أنه لا يمكن تطبيق المُعدِّل على الفئات المجردة (باستخدام الكلمة الأساسية abstractfinalلأن هذه مفاهيم متنافية. للطريقة finalتعني أنه لا يمكن تجاوزها في الفئات الفرعية. يكون هذا مفيدًا عندما نريد عدم تجاوز التنفيذ الأصلي.
public class SuperClass{
    public final void printReport(){
        System.out.println("Report");
    }
}

class SubClass extends SuperClass{
    public void printReport(){  //Compilation error
        System.out.println("MyReport");
    }
}
بالنسبة لمتغيرات النوع البدائي، هذا يعني أنه بمجرد تعيين القيمة، لا يمكن تغييرها. بالنسبة للمتغيرات المرجعية، هذا يعني أنه بمجرد تعيين كائن، لا يمكن تغيير المرجع إلى ذلك الكائن. انه مهم! لا يمكن تغيير الارتباط، ولكن يمكن تغيير حالة الكائن. مع Java 8 ظهر المفهوم - effectively final. ينطبق فقط على المتغيرات (بما في ذلك وسيطات الطريقة). النقطة المهمة هي أنه على الرغم من الغياب الواضح للكلمة الأساسية final، فإن قيمة المتغير لا تتغير بعد التهيئة. بمعنى آخر، يمكنك استبدال كلمة لمثل هذا المتغير finalدون حدوث خطأ في الترجمة. effectively finalيمكن استخدام المتغيرات داخل الفئات المحلية ( Local Inner Classes)، والفئات المجهولة ( Anonymous Inner Classes)، والتدفقات (Stream API).
public void someMethod(){
    // In the example below, both a and b are effectively final, since the values ​​are set once:
    int a = 1;
    int b;
    if (a == 2) b = 3;
    else b = 4;
    // c is NOT effectively final because value changes
    int c = 10;
    c++;

    Stream.of(1, 2).forEach(s-> System.out.println(s + a)); //Ок
    Stream.of(1, 2).forEach(s-> System.out.println(s + c)); //Compilation error
}
الآن دعونا نجري مقابلة صغيرة. بعد كل شيء، الهدف من الحصول على دورة JavaRush هو أن تصبح مطور Java وتحصل على وظيفة مثيرة للاهتمام وذات أجر جيد. لذلك، دعونا نبدأ.
  1. ماذا يمكنك أن تقول عن المصفوفة عندما يتم الإعلان عنها final؟

  2. ومن المعروف أن الفئة Stringهي immutable، يتم الإعلان عن الفئة final، ويتم تخزين قيمة السلسلة في مصفوفة char، والتي تم وضع علامة عليها بالكلمة الأساسية final.

public final class String
    implements java.io.Serializable, Comparable<String>, CharSequence {
    /** The value is used for character storage. */
    private final char value[];
هل من الممكن استبدال قيمة كائن String(دون تغيير المرجع إلى الكائن)؟ هذه أسئلة المقابلة الحقيقية. وكما تظهر الممارسة، يجيب الكثيرون عليهم بشكل غير صحيح. من المهم جدًا فهم استخدام الكلمة الأساسية final، خاصة بالنسبة للمتغيرات المرجعية. بينما كنت تفكر، استطرادا سريعا لفريق JavaRush. يرجى إضافة كتلة في محرر النصوص الخاص بك تسمح لك بإخفاء المحتوى، وعند النقر عليها، قم بإظهار هذا المحتوى. الإجابات:
  1. لأن المصفوفة عبارة عن كائن، مما finalيعني أنه بعد تعيين مرجع للكائن، لم يعد من الممكن تغييره، ولكن يمكن تغيير حالة الكائن.

    final int[] array = {1,2,3,4,5};
    array[0] = 9;	//ok, because change the contents of the array - {9,2,3,4,5}
    array = new int[5]; //compile error
  2. نعم يمكنك ذلك. المفتاح هو فهم استخدام الكلمة الشائكة finalمع الأشياء. يستخدم ReflectionAPI لاستبدال القيمة.

import java.lang.reflect.Field;

class B {
    public static void main(String[] args) throws Exception {
        String value = "Old value";
        System.out.println(value);

        //Get the value field in the String class
        Field field = value.getClass().getDeclaredField("value");
        //Let's change it
        field.setAccessible(true);
        //Set new value
        field.set(value, "JavaRush".toCharArray());

        System.out.println(value);

        /* Вывод:
         * Old value
         * JavaRush
         */
    }
}
يرجى ملاحظة أننا إذا حاولنا تغيير المتغير النهائي لنوع بدائي بهذه الطريقة، فلن ينجح شيء. أقترح عليك أن تقنع نفسك بهذا: قم بإنشاء فئة Java، على سبيل المثال، باستخدام final intحقل وحاول تغيير قيمتها عبر Reflection API. حظا موفقا للجميع!