امروز میخوایم انواع بلاک هارو در جاوا توضیح بدیم و بگیم دقیقا به چه کار میان
خب اول از همه باید بریم سراغ مقدار دهی اولیه ی مقادیر در جاوا.
میدونیم که اگر یک کلاس مثل این داشته باشیم:
public class Sample{ private int i;
private boolean b;
private String s;
}
جاوا میاد خودکار برای ما این متغیر هارو مقدار دهی اولیه میکنه:
تمام مقادیر عددی با صفر , مقادیر بولی با false و ابجکت ها (مثل String و سایر کلاس ها) با null .
اما اگر بخوایم خودمون مقدار دهی کنیم چی؟ میخوایم مقادیر پیشفرض رو تغییر بدیم. باید از سازنده ها استفاده کنیم :
public class Sample{
int i;
String s;
boolean b;
public Sample(){
i=1;
s="empty"
b=true;
}
}
الان دیگه تغییر کرد . حالا یکسری بلاک های دیگه هم داریم برای مقدار دهی اولیه :
static block
non-static block
constructor
خب اخری رو فکر کنم همه باهاش اشنایید .
اما فرض کنید ما سازنده رو overload کردیم(یعنی چند سازنده داریم با امضا های متفاوت).همچنین فرض کنید کلاسی داریم برای نگهداری اطلاعات دانشجو. دانشجو یه کد دانشجویی داره و یه شماره ملی. اگر شماره ملی
به کلاس ما داده شد دیگه نیازی نیست کد دانشجویی رو هم بگیریم چون با همون شماره ملی میتونیم کد دانشجوییش هم پیدا کنیم از طریق پایگاه دادمون(فرض کنید دیگه) و برعکس. همچنین سن دانشجو رو پیشفرض ۱۸ در نظر گرفتیم:
public class Student{
private int studentCode;
private int nationalId;
private int age;
public Register(int studentCode){
this.studentCode=studentCode;
age=18;
}
public Register(int nationalId){
this.nationalId=nationalId;
age=18;
}
}
تا اینجا کد درسته..مشکلی هم نداره . اما صبر کنید. انگار مقدار دهی اولیه ی متغیر age دوجا صورت گرفته و خب این برای تمیزی کد مناسب نیست.فرض کنید فقط سن نبود و متغیر های زیاد تر دیگه ای هم بود.روش جایگزین و تمیز تر چیه؟ استفاده از non-static block ها:
public class Student{
private int studentCode;
private int nationalId;
private int age;
{
age=18;
}
public Register(int studentCode){
this.studentCode=studentCode;
}
public Register(int nationalId){
this.nationalId=nationalId;
}
}
نکته: non-static block همیشه قبل از سازنده اجرا میشه و کاربردش جلوگیری از کد های تکراری در سازنده های overload شده ست .
نکته: میتونیم هرچند تا که دلمون خواست non-static block داشته باشیم!
خب بریم سراغ static block . این یکی یکم قضیه اش فرق داره ولی فلسفه ی همینم مثل سازنده و مثل non static block برای مقدار اولیه دادنه . ولی به متغیر های static:
فرض کنید یک کلاس داریم که داره یک کانکشن به پایگاه داده باز میکنه. مسلما بهینه نیست هر بار که شی از اون کلاس ساخته شد ما بیایم یه کانکشن جدید باز کنیم! کار پر هزینه ایه. باید چیکار کنیم؟ با استفاده از static block یک کد رو فقط یکبار اونم موقع لود شدن کلاس در حافظه اجرا میکنیم(از همین جمله باید بفهمیم استاتیک بلاک قبل از کانستراکتر و non static block اجرا میشه چون قبل ازینکه بتونیم شی بسازیم از یک کلاس باید اول اون کلاس در حافظه لود بشه)!
public class DatabaseConnector{
public static Connection conn;
static{
// init conn
}
}
اگر یه کلاس داشته باشیم (مثل همین بالا ) و بخوایم بدون شی ساختن ازش فقط اونو در حافظه لود کنیم (که مثلا بلوک استاتیکش اجرا شه) به شکل زیر عمل میکنیم:
Class.forName("DatabaseConnector");
و اما کاربردش چیه؟ بعضی کلاس ها یک سری کانفیگ ها دارن و قبل ازینکه شی ازشون ساخته شه باید اون کانفیگ ها انجام بشه مثل Jdbc Driver ها.
راستی..دوباره میتونیم هرچند تا که دلمون خواست static block در کلاسمون داشته باشیم(در این صورت به ترتیب از اولی تا اخری اجرا میشن).
نکته : متغیر های غیر استاتیک رو نمیتونیم در بلاک استاتیک مقدار دهی کنیم!! دلیلش هم واضحه. متغیر های غیر استاتیک وابسته به اشیای کلاس هستند و هربار که شی ایجاد شد یک کپی از اونا میره داخل حافظه. درواقع فقط یکبار قرار نیست ساخته و مقدار دهی بشن! اما متغیر استاتیک فقط موقع لود شدن کلاس در حافظه ساخته میشن و تا اخر برنامه پا برجا میمونن.
نکته: متغیر های static final باید حتما در بلوک استاتیک مقدار دهی بشن(در سازنده و بلوک های غیر استاتیک امکانش وجود نداره).
نکته : در مکانیزم ارث بری جاوا , اولویت اجرا به ترتیب با static block پدر, non static block پدر و constructor پدره. سپس نوبت به همین ترتیب برای کلاس فرزند میرسه.