count
فیلد در Counter
کلاس ثابت است، به این معنی است که می توانید متغیر را با عبارت زیر ارجاع دهید: Counter.count
. 
private
فیلدها فقط در کلاسی که در آن اعلان شده اند در دسترس هستند. و protected
فیلدها برای همه کلاس های داخل یک بسته و همچنین برای همه زیر کلاس های آنها خارج از بسته در دسترس هستند. فرض کنید Counter
کلاس یک متد استاتیک دارد increment()
که وظیفه آن افزایش count
میدان است. برای فراخوانی این روش می توانید از Counter.increment()
. Counter
برای دسترسی به یک فیلد یا متد استاتیک نیازی به ایجاد نمونه ای از کلاس نیست . این تفاوت اساسی بین متغیرها و متدهای استاتیک (کلاس) و متغیرها و متدهای غیراستاتیک (نمونه) است. یک نکته مهم فراموش نکنید که اعضای ثابت کلاس مستقیماً متعلق به کلاس هستند، نه هیچ نمونه ای از کلاس. یعنی مقدار متغیر استاتیک برای همه اشیا count
یکسان خواهد بود . Counter
در این مقاله، جنبههای اساسی استفاده از اصلاحکننده استاتیک در جاوا و همچنین برخی از ویژگیهایی که به شما در درک مفاهیم کلیدی برنامهنویسی کمک میکنند، بررسی خواهیم کرد.
آنچه هر برنامه نویسی باید در مورد اصلاح کننده استاتیک در جاوا بداند.
در این بخش به جنبه های اصلی استفاده از روش ها، فیلدها و کلاس های استاتیک می پردازیم. بیایید با متغیرها شروع کنیم.-
شما نمی توانید به اعضای غیر ایستا یک کلاس در یک زمینه ایستا، مانند یک متد یا بلوک استاتیک دسترسی پیدا کنید. کامپایل کد زیر با خطا مواجه می شود:
public class Counter { private int count; public static void main(String args []) { System.out.println(count); // Compile time error } }
این یکی از رایج ترین اشتباهات برنامه نویسان جاوا، به خصوص تازه کارها است. از آنجایی که
main
روش ثابت است وcount
متغیر نیست، استفاده ازprintln
متد داخلmain
متد باعث ایجاد "خطای زمان کامپایل" می شود. -
thread safe
برخلاف متغیرهای محلی، فیلدها و متدهای استاتیک در جاوا نیستند . در عمل، این یکی از شایع ترین علل مشکلات امنیتی در برنامه نویسی چند رشته ای است. با توجه به اینکه هر نمونه از یک کلاس به یک کپی از یک متغیر استاتیک ارجاع می دهد، چنین متغیری باید توسط کلاس محافظت یا "قفل" شود. بنابراین، هنگام استفاده از متغیرهای استاتیک، از درست بودن آنها اطمینان حاصل کنیدsynchronized
تا از مشکلاتی مانندrace conditions
. -
روش های استاتیک یک مزیت عملی دارند زیرا نیازی به ایجاد یک شی جدید در هر بار فراخوانی آنها نیست. یک متد استاتیک را می توان با استفاده از نام کلاسی که آن را اعلام می کند فراخوانی کرد. به همین دلیل این روش ها برای
factory
روش ها وutility
روش ها عالی هستند. کلاسjava.lang.Math
مثال فوق العاده ای است: تقریباً تمام متدهای آن ثابت هستند. کلاس های کاربردی جاواfinal
به همین دلیل علامت گذاری شده اند. -
نکته مهم دیگر این است که نمی توانید
@Override
روش های استاتیک ( ) را نادیده بگیرید. اگر چنین متدی را در یک اعلان کنیدsubclass
، یعنی متدی با همان نام و امضا، فقط متد the راsuperclass
به جای رد کردن آن، "پنهان" میکنید. این پدیده به نام شناخته می شودmethod hiding
. این بدان معناست که اگر یک متد استاتیک در هر دو کلاس والد و فرزند اعلام شود، متد فراخوانی شده همیشه بر اساس نوع متغیر در زمان کامپایل خواهد بود. بر خلاف روش overriding، چنین متدهایی هنگام اجرای برنامه اجرا نمی شوند. بیایید یک مثال را در نظر بگیریم:class Vehicle { public static void kmToMiles(int km) { System.out.println("Inside the parent class / static method"); } } class Car extends Vehicle { public static void kmToMiles(int km) { System.out.println("Inside the child class / static method"); } } public class Demo { public static void main(String args []) { Vehicle v = new Car(); v.kmToMiles(10); } }
خروجی کنسول:
در داخل کلاس والد / متد استاتیک
کد به وضوح نشان می دهد که علیرغم اینکه شیء a است
Car
، متد استاتیک درVehicle
کلاس فراخوانی می شود، زیرا متد در زمان کامپایل فراخوانی شده است. و توجه داشته باشید که هیچ خطای کامپایل وجود ندارد! -
علاوه بر این، به غیر از کلاس های سطح بالا، می توانید کلاس ها را ثابت اعلام کنید. چنین کلاس هایی به نام شناخته می شوند
nested static classes
. آنها برای ایجاد انسجام بهتر مفید هستند. یک مثال قابل توجه از کلاس استاتیک تو در تو استHashMap.Entry
که یک ساختار داده در داخل استHashMap
. شایان ذکر است که مانند کلاس های داخلی، کلاس های تو در تو استاتیک در یک فایل .class جداگانه اعلان می شوند. بنابراین، اگر پنج کلاس تودرتو در کلاس اصلی خود اعلام کنید، 6 فایل با پسوند .class خواهید داشت. مثال دیگر اعلان خودمان استComparator
، مانند یک مقایسه کننده سنی (AgeComparator
) درEmployee
کلاس. -
اصلاح کننده استاتیک را می توان در یک بلوک استاتیک نیز مشخص کرد، که بیشتر به عنوان "بلوک اولیه سازی استاتیک" شناخته می شود، که هنگام بارگیری کلاس اجرا می شود. اگر چنین بلوکی را اعلان نکنید، جاوا تمام فیلدهای استاتیک را در یک لیست واحد جمع آوری می کند و هنگام بارگیری کلاس، آنها را مقداردهی اولیه می کند. یک بلوک ایستا نمی تواند استثناهای علامت زده شده را پرتاب کند، اما می تواند موارد بدون علامت را پرتاب کند. در این صورت یک
ExceptionInInitializerError
اتفاق رخ می دهد. در عمل، هر استثنایی که در زمان اولیه سازی فیلدهای استاتیک رخ دهد، توسط جاوا در این خطا قرار می گیرد. این نیز شایعترین علت این استNoClassDefFoundError
، زیرا کلاس در هنگام ارجاع در حافظه نخواهد بود. -
دانستن این نکته مفید است که متدهای استاتیک در زمان کامپایل پیوند داده میشوند، بر خلاف پیوند روشهای مجازی یا غیراستاتیک، که در زمان اجرا و هنگام فراخوانی یک شی واقعی، پیوند داده میشوند. بر این اساس، روشهای استاتیک را نمیتوان در جاوا نادیده گرفت، زیرا پلیمورفیسم در زمان اجرا برای آنها اعمال نمیشود. این یک محدودیت مهم است که باید در هنگام اعلام یک روش ثابت در نظر گرفت. انجام این کار تنها زمانی معنا پیدا می کند که توانایی یا نیازی به لغو روش در یک زیر کلاس وجود نداشته باشد. روش های کارخانه و روش های کاربردی نمونه های خوبی از استفاده صحیح از اصلاح کننده استاتیک هستند. Joshua Bloch در کتاب Effective Java که خواندن آن برای هر برنامه نویس جاوا اجباری است، به چندین مزیت روش کارخانه ایستا نسبت به سازنده ها اشاره می کند.
-
مقداردهی اولیه یک جنبه مهم از یک بلوک استاتیک است. فیلدها یا متغیرهای استاتیک پس از بارگیری کلاس در حافظه مقداردهی اولیه می شوند. ترتیب مقداردهی اولیه از بالا به پایین است، به همان ترتیبی که در فایل منبع کلاس جاوا اعلان می شوند. از آنجایی که فیلدهای استاتیک به روشی ایمن برای نخ مقداردهی می شوند، از این فرآیند برای پیاده سازی
Singleton
الگو نیز استفاده می شود.Enum
اگر به دلایلی از یک به عنوان یک استفاده نمی کنیدSingleton
، جایگزین خوبی دارید. اما در این مورد، باید در نظر داشته باشید که این یک مقداردهی اولیه "تنبل" نیست. این بدان معنی است که فیلد استاتیک حتی قبل از اینکه کسی آن را بخواهد مقداردهی اولیه می شود. اگر یک شی دارای منابع سنگین است یا به ندرت استفاده می شود، مقداردهی اولیه آن در یک بلوک استاتیک به نفع شما کار نخواهد کرد. -
در طول سریال سازی، فیلدهای استاتیک، مانند
transient
متغیرها، سریالی نمی شوند. در واقع، اگر هر داده ای را در یک فیلد ثابت ذخیره کنید، پس از جداسازی، مقدار اولیه (پیشفرض) آن را خواهد داشت. به عنوان مثال، اگر یک فیلد استاتیک یک باشدint
، مقدار آن پس از deserialization صفر خواهد بود. اگر نوع آن باشدfloat
، مقدار 0.0 خواهد بود. اگر فیلد یک باشدObject
، مقدار آن خواهد بودnull
. صادقانه بگویم، این یکی از متداول ترین سوالاتی است که در مورد سریال سازی در مصاحبه ها برای موقعیت های جاوا پرسیده می شود. داده های اشیاء ضروری را در یک فیلد ثابت ذخیره نکنید! -
در نهایت، اجازه دهید در مورد واردات استاتیک صحبت کنیم. این اصلاحکننده شباهتهای زیادی با
import
دستور استاندارد دارد، اما از این جهت متفاوت است که به شما امکان میدهد یک یا همه اعضای کلاس استاتیک را منتقل کنید. هنگامی که متدهای استاتیک وارد می شوند، می توان به آنها دسترسی پیدا کرد که گویی در همان کلاس تعریف شده اند. به همین ترتیب، با وارد کردن فیلدهای ثابت، می توانیم بدون تعیین نام کلاس به آنها دسترسی داشته باشیم. این ویژگی در جاوا 1.5 ظاهر شد و خوانایی کد را در صورت استفاده صحیح بهبود می بخشد. این ساختار اغلب در تستهای JUnit یافت میشود، زیرا تقریباً همه توسعهدهندگان تست از import static برای روشهای ادعا استفاده میکنند، به عنوان مثالassertEquals()
و انواع بارگذاریشده آنها. -
فعلاً همین است. هر برنامه نویس جاوا باید تمام جنبه های اصلاح کننده استاتیک که در بالا ذکر شد را بداند. این مقاله اطلاعات اولیه در مورد متغیرهای استاتیک، فیلدها، روش ها، بلوک های اولیه و واردات را بررسی می کند. همچنین برخی از ویژگیهای مهمی را که دانستن آنها برای نوشتن و درک برنامههای جاوا ضروری است، لمس کرد. من امیدوارم که هر توسعهدهندهای استفاده ماهرانه خود از اعضای ثابت را کامل کند، زیرا این برای توسعه نرمافزار جدی بسیار مهم است."
GO TO FULL VERSION