متغیرهای final و static در جاوا
منبع:gameover.blog.ir
داده های نوع static همیشه آخرین مقداری رو که بهشون می دیم تو کل برنامه یا تو کل بازی حفظ می کنن و دیگه صفر نمیشه مگه اینکه خودمون مقدارشو صفر یا تغییر بدیم.
اگر یک متغیر final (نهایی) یک مرجع به یک ابجکت را نگه دارد،آنگاه وضعیت
آبجکت ممکن است بوسیله ی عملیاتی روی ابجکت تغییر کند،اما متغیر همیشه به
همان ابجکت رجوع می کند.این همچنین با آرایه ها بکار می رود.زیرا آرایه ها
اشیا هستند.
اگر یک متغیر final یک رجوع به یک آرایه داشته باشد،آنگاه اجزای آرایه
ممکن است است به وسیله ی عملیات روی آرایه تغییر کنند.،اما متغیر همیشه به
همان آرایه مراجعه خواهد کرد.
کلاس های final :
یک کلاس نهایی، نمی تواند subclass شود.این حالت باعث ایجاد امنیت و مزایای
موثری می شود.بنابراین تعدادی از کلاس های استانارد Java نهایی(final)
هستند.مثل java.lang.System و java.lang.String . همه ی متدها در کلاس
فاینال، final ضمنی هستند.
مثال :
public final class MyFinalClass {...} public class ThisIsWrong extends MyFinalClass {...} // forbidden
sub class های محود اغلب به کلاس های "soft final" نامیده می شوند.
متدهای final:
یک method فاینال نمی تواند به وسیله ی sub class ها ovveride یا hidden
شود.این به دلیل جلوگیری از رفتار غیر منتظره ی یک subclass (یا کلاس
فرزند) برای تغییر متدی بکار می رود که ممکن است برای function یا استکام
کلاس حیاتی باشد.
مثال:
public class Base { public void m1() {...} public final void m2() {...} public static void m3() {...} public static final void m4() {...} } public class Derived extends Base { public void m1() {...} // Ok, overriding Base#m1() public void m2() {...} // forbidden public static void m3() {...} // OK, hiding Base#m3() public static void m4() {...} // forbidden }یک تصور غلط عمومی این است که تعریف یک کلاس یا متد به عنوان کلاس final با اجازه به کامپایلر بهره وری را افزایش می دهد تا به طور مستقیم متد را در جاییکه فراخوانی یا call می شود درج کند.(اینجا رو بخونید: https://en.wikipedia.org/wiki/Inline_expansion) اما از آنجا که متد در لحظه ی اجرا لود می شود، کامپایلر ها قادر به اجرای این نیستند. فقط محیط اجرایی و کامپایلر JIT جی آی تی (https://en.wikipedia.org/wiki/Just-in-time_compilation) دقیقا می داند کدام کلاس لود شده است و فقط آنها می توانند در مورد زمان inline بودن تصمیم بگیرند خواه متد ،نهایی(final) باشد یا نباشد.
کامپایلرهای کد ماشین،که مستقیما کد اجرایی را تولید می کنند(platform-specific machine code) یک استثنا هستند. موقع استفاده از static linking (توضیحات بیشتر https://en.wikipedia.org/wiki/Static_linking ) کامپایلر می تواند به طور امن فرض کند که متدها و متغیرها در زمان کامپایل می توانند inline شوند.
Final variables:
یک متغیر فاینال از طریق یک initializer یا یک عبارت اختصاصی می تواند یکبار فراخوانی شود .نیاز نیست که در لحظه ی تعریف ، initialize شود: این یک متغیر "blank final" نامیده میشود. یک متغیر blank final instance از کلاس باید قطعا در هر constructor (سازنده)(یک کلاس همنام کلاس در خود کلاس) در جاییکه تعریف می شود اختصاص بیابد . در غیر اینصورت یک خطای زمان کامپایل در هر دو حالت رخ می دهد.(نکته: اگر متغیر یک رفرنس باشد این به این معنی است که متغیر نمی تواند بار دیگر به رفرنس ابجکت دیگری محدود شود.اما شی ای که آن رجوع می کند هنوز تغییر پذیر یا mutable است اگر هنوز به طور اصلی قابل تغییر باشد: https://en.wikipedia.org/wiki/Mutable_object)
بر خلاف مقدار یک constant(ثابت) ،مقدار متغیر نهایی (final) نیاز نیست در زمان کامپایل شناخته شود . این شیوه ی خوبی برای نمایش ثابت های final با حروف تمام بزرگ(uppercase) می باشد(به همراه خط زیر یا underline برای جداسازی کلمات)
مثال:
public class Sphere { // pi is a universal constant, about as constant as anything can be. public static final double PI = 3.141592653589793; public final double radius; public final double xPos; public final double yPos; public final double zPos; Sphere(double x, double y, double z, double r) { radius = r; xPos = x; yPos = y; zPos = z; } [...] }هر تلاشی برای اختصاص مجدد شعاع، xPos،yPos، یا zPos منجر به یک خطای کامپایلری خواهد شد.در واقع حتی اگر constructor(سازنده ی کلاس) یک متغیر نهایی را تنظیم نکند تلاش برای تنظیم آن در خارج از سازنده ی کلاس منجر به خطای کامپایلری می شود.
برای آنکه نشان دهیم finality تغییر ناپذیری را تضمین نمی کند:فرض کنید که ما سه متغیر موقعیت را با یکی نشان دهیم:
public final Position pos;که pos شامل pos.x و pos.y و pos.z هست. pos نمی تونه اخصاص داده بشه اما سه خصوصیت اون می تونن مقداردهی بشن مگر اینکه اونا خودشون نهایی باشن.مثل تغییرناپذیری کامل( https://en.wikipedia.org/wiki/Immutability) استفاده از مزایای زیادی داره مخصوصا در بهینه سازی(optimization) . برای نمونه، Sphere احتمالا یک حجم بازگشتی (function returning its volume) خواهد داشت. اگه بدونیم شعاع ثابت هست به ما اجازه می ده تا حجم محاسبه شده رو در حافظه ذخیره کنیم. اگر ما Spheres های نسبتا کمی داشته باشیم و ما اغلب حجم آنها را نیاز داریم افزایش عملکرد ممکن است قابل توجه باشد. ساخت یک Sphere final به توسعه دهندگان و کامپایلرها اطلاع می دهد که انواع بهینه سازی در تمام کدی که از Sphere ها استفاده می کنند ممکن است. هر چند به نظر میرسد که اصل final نقض شده است عبارت زیر قانونی است :
for (final SomeObject obj : someList) { // do something with obj }از آنجا که متغیر obj با هر بار تکرار در حلقه از حوزه خارج می شود واقعا با هر تکرار مجددا تعریف می شود.
ترجمه:sajjad3011
مطالعه ی بیشتر:
https://en.wikipedia.org/wiki/Final_%28Java%29#cite_note-2
اینم یه منبع فارسی دیگه:
http://www.tahlildadeh.com/ArticleDetails/%D8%A2%D9%85%D9%88%D8%B2%D8%B4-java-%D8%A7%D9%86%D9%88%D8%A7%D8%B9-%D9%85%D8%AA%D8%BA%DB%8C%D8%B1%D9%87%D8%A7%DB%8C-%D8%AC%D8%A7%D9%88%D8%A7
نکته بعدی: متغیرهای static متغیرهایی هستن که آخرین مقداری رو که بهشون می دیم همیشه حفظ می کنن.
خیلی عالی توضیح دادین
ممنون