1. Statik sahələr: necə ilkinləşdirmək?
Statik sahə (static) obyektə deyil, bütöv sinifə məxsusdur. Onun dəyəri həmin sinfin bütün obyektləri üçün tək nüsxədə mövcuddur. Bənzətmə aparsaq — bu, şirkətin bütün əməkdaşları üçün “ümumi kassa” elan etmək kimidir: kim gəlir-gəlməz — kassa hamı üçün birdir.
Elan zamanı ilkinləşdirmə
Statik sahəni ilkinləşdirməyin ən sadə və geniş yayılmış yolu — dəyəri birbaşa elanda təyin etməkdir:
public class User {
private static int userCount = 0; // ilkinləşdirmə məhz burada
// ... qalan kod
}
Belə sahə User sinfi yaddaşa ilk dəfə yüklənəndə ilkinləşdiriləcək.
Statik blokda ilkinləşdirmə
Bəzən daha mürəkkəb ilkinləşdirmə məntiqi tələb olunur — məsələn, fayldan məlumat yükləmək və ya hesablamalar aparmaq. Bu halda statik ilkinləşdirmə bloku istifadə olunur:
public class Config {
public static String configPath;
static {
// Bu blok sinif yüklənərkən YALNIZ BİR dəfə icra olunacaq
configPath = System.getenv("APP_CONFIG_PATH");
if (configPath == null) {
configPath = "/etc/app/default.conf";
}
System.out.println("Konfiqurasiya yolu ilkinləşdirildi: " + configPath);
}
}
Statik blok nə vaxt işə düşür?
- Sinfə ilk müraciət zamanı (məsələn, ilk obyekt yaradılarkən və ya istənilən statik metod/sahə çağırılarkən).
- Hər sinif üçün yalnız bir dəfə icra olunur.
Statik sahələrə çıxışın xüsusiyyətləri
- Statik sahələrə sinifin adı vasitəsilə müraciət edilir: User.userCount.
- Obyekt vasitəsilə də müraciət etmək olar, lakin bu, pis üslub sayılır (kodu oxuyanı çaşdıra bilər).
Nümunə:
User u1 = new User();
User u2 = new User();
System.out.println(User.userCount); // doğrudur
System.out.println(u1.userCount); // işləyir, amma məsləhət görülmür!
2. final sahələr: nə zaman və necə ilkinləşdirmək?
final — bu modifikator “Bu sahəyə yalnız bir dəfə dəyər verilə bilər və sonra dəyişməyəcək” deməkdir. İlkinləşdirmədən sonra sahənin dəyəri dəyişməz olur: obyekt üçün bu, onun sabit xüsusiyyəti, sinif üçünsə (əgər sahə statikdirsə) — ümumi konstantadır.
İstifadə nümunələri:
- Konstantalar (məsələn, PI).
- Obyektin yaradıldıqdan sonra dəyişməməli unikal identifikatoru.
final sahələrin ilkinləşdirilməsi tələbləri
Java-da sərt qayda var: hər bir final sahə mütləq ya elanda, ya da sinfin hər bir konstruktorunda ilkinləşdirilməlidir.
Elan zamanı ilkinləşdirmə
public class Circle {
public static final double PI = 3.1415926535; // sinif konstantı
private final String id = "CIRCLE"; // obyekt konstantı
}
Konstruktorda ilkinləşdirmə
Bəzən final sahənin dəyəri yalnız obyekt yaradılan zaman məlum olur:
public class User {
private final int id;
public User(int id) {
this.id = id; // final sahəni konstruktorda təyin edirik
}
}
Vacibdir: əgər sinifin bir neçə konstruktoru varsa, final sahə onların hər birində ilkinləşdirilməlidir!
Kombinə olunmuş nümunə
public class Token {
private final String value;
private final long timestamp;
public Token(String value) {
this.value = value;
this.timestamp = System.currentTimeMillis();
}
}
Yanlış ilkinləşdirmə zamanı kompilyasiya xətaları
Əgər siz final sahəni ilkinləşdirməyi unutsanız, kompilyator proqramı yığmağa imkan verməyəcək:
public class Broken {
private final int x; // ilkinləşdirilməyib
public Broken() {
// x təyin olunmur!
}
}
// Xəta: variable x might not have been initialized
3. static və final kombinasiyası: sinif konstantlarının elan edilməsi
Çox tez-tez public static final dəsti ilə qarşılaşırıq. Java-da sinif konstantaları belə elan olunur — proqramın işləməsi boyu dəyişməyən və yalnız bir dəfə təyin edilən dəyərlər. Bu konstantalar bütöv sinfə məxsusdur və onun bütün obyektləri üçün eynidir.
Sintaksis və nümunə
public class MathUtils {
public static final double PI = 3.1415926535;
public static final String APP_NAME = "MyApp";
}
İzah:
- public — hər yerdə əlçatandır.
- static — ayrı obyektə yox, bütöv sinifə məxsusdur.
- final — ilkinləşdirmədən sonra dəyişdirilə bilməz.
İstifadə
double area = MathUtils.PI * r * r;
System.out.println(MathUtils.APP_NAME);
Qayda: konstant adları adətən BÖYÜK_HƏRFLƏRLƏ_VƏ_ALT_XƏTİLƏ yazılır.
4. Kod nümunələri: statik və final sahələrin ilkinləşdirilməsinin variantları
Nümunə 1: Konstanta ilə sadə sinif
public class Constants {
public static final int DAYS_IN_WEEK = 7;
public static final String COMPANY = "OOO Romashka";
}
Nümunə 2: Statik blokda ilkinləşdirilmiş statik sahə
public class AppConfig {
public static final String DEFAULT_PATH;
static {
// Mürəkkəb məntiq icra etmək olar
String env = System.getenv("APP_PATH");
if (env != null) {
DEFAULT_PATH = env;
} else {
DEFAULT_PATH = "/usr/local/app";
}
}
}
Nümunə 3: Obyektin final sahəsi, konstruktorda ilkinləşdirmə
public class User {
private static int nextId = 1;
private final int id;
private String name;
public User(String name) {
this.id = nextId++;
this.name = name;
}
public int getId() {
return id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
}
İstifadə:
User u1 = new User("Ivan");
User u2 = new User("Mariya");
System.out.println(u1.getId()); // 1
System.out.println(u2.getId()); // 2
Nümunə 4: final sahənin səhv ilkinləşdirməsi zamanı xəta
public class BadExample {
private final int number;
public BadExample() {
// number ilkinləşdirilməyib!
}
}
// Kompilyasiya xətası: variable number might not have been initialized
5. Statik və final sahələrlə işləyərkən ən yaxşı təcrübələr
public static final-dan yalnız həqiqi konstantalar üçün istifadə edin
Əgər dəyər gələcəkdə dəyişə bilərsə (məsələn, əməkdaşların siyahısı), onu final etməyin! Konstantalar həqiqətən dəyişməz olmalıdır.
public static final int MAX_USERS = 1000; // yaxşı
public static final String[] USERS = new String[100]; // pis!
İstinadın özü USERS dəyişməsə də, massiv daxilini dəyişmək olar. Bu, gözlənilməz xətalara səbəb ola bilər.
Mürəkkəb ilkinləşdirmə üçün statik bloklardan istifadə edin
Əgər konstantanı sadə mənimsətmə ilə ifadə etmək olmursa (məsələn, hesablamalar və ya fayldan oxuma tələb olunursa), statik blokdan istifadə edin.
Statik sahələrdən sui-istifadə etməyin
Statik sahələr qlobal dəyişənlərdir. Onların həddindən artıq çox olması çətin aşkarlanan xətalara və kodun mürəkkəb dəstəyinə gətirib çıxara bilər.
Dəyişən obyektləri public static final etməyin
Obyekt dəyişəndirsə, onu publik və final etməyin. Bu, hamı üçün onun daxilinə çıxış açır və kimsə mütləq bundan istifadə edəcək.
6. Statik və final sahələrin ilkinləşdirilməsində tipik səhvlər
Səhv № 1: İlkinləşdirilməmiş final sahə. Əgər final sahəni ya elanda, ya da bütün konstruktorlarda ilkinləşdirməyi unutsanız, kompilyator xəta verəcək. Məsələn, sinfin iki konstruktoru varsa və onlardan birində siz final sahəyə dəyər verməyi unutsanız — xəta olacaq.
Səhv № 2: final sahənin dəyərinin dəyişdirilməsi. İlkinləşdirmədən sonra final sahənin dəyərini dəyişməyə cəhd kompilyasiya xətasına səbəb olacaq.
public class Demo {
private final int x = 5;
public void change() {
x = 10; // Xəta: cannot assign a value to final variable x
}
}
Səhv № 3: Publik dəyişən static final sahələr. Əgər dəyişən obyekt (String[], int[] və s.) public static final edilsə, istənilən kod onun tərkibini dəyişə bilər. Bu, enkapsulyasiyanı pozur və çətin aşkarlanan bəlalara səbəb ola bilər.
Səhv № 4: Statik blokda qeyri-statik sahələrdən istifadə. Statik blokda qeyri-statik sahələrə müraciət etmək olmaz, çünki onlar hələ ilkinləşdirilməyib (və bu mərhələdə ümumiyyətlə mövcud deyil).
Səhv № 5: İlkinləşdirmənin gözlənilməz ardıcıllığı. Statik blokda siz kodda aşağıda elan edilən statik sahələrə müraciət edirsinizsə, ola bilər ki, onlar hələ ilkinləşdirilməyib. Onlardan istifadə etməyi planlaşdırırsınızsa, statik sahələri həmişə statik bloklardan əvvəl elan edin.
GO TO FULL VERSION