JavaRush /وبلاگ جاوا /Random-FA /پس نهایی ...
Алексей
مرحله

پس نهایی ...

در گروه منتشر شد
یک کلمه کلیدی در جاوا وجود دارد - final. می توان آن را برای کلاس ها، متدها، متغیرها (از جمله آرگومان های متد) اعمال کرد. بنابراین نهایی ... - 1برای یک کلاس، این بدان معنی است که کلاس نمی تواند زیر کلاس هایی داشته باشد، یعنی. ارث ممنوع است. این هنگام ایجاد immutableاشیاء (تغییرناپذیر) مفید است، برای مثال کلاسی Stringکه به عنوان اعلان شده است final.
public final class String{
}

class SubString extends String{ //Compilation error
}
همچنین لازم به ذکر است که اصلاح کننده را نمی توان برای کلاس های انتزاعی (با کلمه کلیدی abstract) اعمال کرد، finalزیرا اینها مفاهیم متقابل انحصاری هستند. برای یک متد 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");
    }
}
برای متغیرهای نوع اولیه، این بدان معناست که پس از تخصیص، مقدار قابل تغییر نیست. برای متغیرهای مرجع، این بدان معنی است که وقتی یک شی تخصیص داده می شود، مرجع آن شی را نمی توان تغییر داد. مهم است! پیوند را نمی توان تغییر داد، اما وضعیت شی را می توان تغییر داد. با جاوا 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، تبدیل شدن به یک توسعه دهنده جاوا و بدست آوردن یک شغل جالب و با درآمد خوب است. بنابراین، بیایید شروع کنیم.
  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
         */
    }
}
لطفاً توجه داشته باشید که اگر بخواهیم متغیر نهایی یک نوع اولیه را به این روش تغییر دهیم، هیچ چیز جواب نمی دهد. پیشنهاد می‌کنم خودتان را در این مورد متقاعد کنید: برای مثال یک کلاس جاوا با final intیک فیلد ایجاد کنید و سعی کنید مقدار آن را از طریق Reflection API تغییر دهید. همگی موفق باشید!
نظرات
TO VIEW ALL COMMENTS OR TO MAKE A COMMENT,
GO TO FULL VERSION