Final dəyişənlər elan olunarkən onlara mütləq dəyər mənimsədilməlidir və bu ancaq bir dəfə baş verə bilər, final dəyişənlərə 2-ci dəfə dəyər mənimsətmək mümkün deyil. Final static və final instance dəyişənlər üçün dəyər mənimsədilməsi bir az fərqlidir, baxaq.
- final static dəyişənlərə dəyər mənimsədilə bilər:
- elan olunduğu sətirdə;
- static initializer blokda.
- final instance dəyişənlərə dəyər mənimsədilə bilər:
- elan olunduğu sətirdə;
- instance initializer blokda;
- constructor`da.
Constructor tamamlananda bütün final instance dəyişənlərin hamısına mütləq dəyər mənimsədilməlidir. Əgər qeyd olunan halların heç birində dəyər mənimsədilməsə compile xətası baş verəcək.
Local final dəyişənlərə dəyər mənimsədilməsi ilə bağlı isə mütləq məcburiyyət yoxdur. Local dəyişənlər üçün standart qayda var: istifadə olunmadan öncə mütləq initialize olunmalıdır. Local final dəyişənlər də sadəcə bu qaydaya riayət etməlidir, əgər istifadə olunacaqsa, dəyər mənimsədilməlidir, əks halda compile xətası vermir.
public class Finals { // static final variables - sf private static final int sf1; // DOES NOT COMPILE private static final int sf2 = 10; private static final int sf3; private static int s4; static { System.out.println(s4); // 0 sf3 = 100; } // instance final variables - if private final int if1; // DOES NOT COMPILE, bunun xətasını əslində constructorda göstərir private final int if2 = 20; private final int if3; private final int if4; private int i5; { if4 = 200; if2 = 21; // DOES NOT COMPILE } public Finals() { System.out.println(i5); // 0 if3 = 200; } public void method() { // local final variables final int a1; final int a2; final int a3; // unused int b1; int b2; int b3; // unused System.out.println(a1); // DOES NOT COMPILE System.out.println(b1); // DOES NOT COMPILE a2 = 30; System.out.println(a2); b2 = 3; System.out.println(b2); b2 = 300; System.out.println(b2); a2 = 15; // DOES NOT COMPILE } }
Ətraflı bu linkdən baxa bilərsiniz:
İndi maraqlı bir kod nümunəsinə baxacağıq, yuxarıda qeyd edilən qaydalar ödənilmir, amma buna baxmayaraq compile xətası vermir:
class FinalKeywordExample { final boolean bool; // line1 static { System.out.println("static initializer"); } { System.out.println("instance initializer"); } FinalKeywordExample() { throw new RuntimeException(); // line2 } public static void main(String[] args) { FinalKeywordExample i = new FinalKeywordExample(); System.out.println(i.bool); } }
Koddan da gördüyünüz kimi line1-də final bool
dəyişəni yaradılıb və nə elan olunduğu sətirdə, nə instance initializer blokda, nə də constructor`da ona dəyər mənimsədilməyib. Amma buna baxmayaraq compile xətası vermir. Xəta verməməsinin səbəbi isə line2-də RuntimeException
fırladılmasıdır. Əgər line2-ni kommentə salsaq, o zaman line1 compile xətası verəcək və bool
dəyişəninə dəyər mənimsədilməsi tələb ediləcək.
Aşağıdakı nümunə sizi çaşdıra bilər. list
və array
referans dəyişənlərdir, yəni biz listə yeni dəyər əlavə etdikdə, yaxud massivin müvafiq indeksindəki dəyərini başqa dəyərlə əvəz etdikdə, bu final dəyişənə təkrar dəyər mənimsədilməsi hesab olunmur. Referans dəyişənə yeni obyekt mənimsətdikdə artıq compile xətası baş verir:
private static final ArrayList<String> list = new ArrayList<>(); private static final int array[] = {1, 2}; public static void main(String[] args) { list.add("changed"); array[1] = 3; list = new ArrayList<>(); // DOES NOT COMPILE array = new int[]{4, 5}; // DOES NOT COMPILE }
Aşağıdakı nümunə də maraqlı nümunədir, bənzər print ifadəsi main
metodda xəta verir, amma increaseX
metodunda xəta vermir:
public static void main(String[] args) { final int x = 15; increaseX(x); System.out.println(++x); // DOES NOT COMPILE } public static void increaseX(int x){ System.out.println(++x); // prints 16 }
Səbəb Java`nın “pass by value” özəlliyinə görədir, yəni x
dəyişəni main
metodda final dəyişən olsa da, increaseX
metodunda final dəyişən deyil. “pass by value” mövzusu ilə növbəti məqalədə tanış olacağıq.
[topics lang=az]