دانستنی‌ها

جاوا ۱۰ و استنتاج نوع متغیر‌های محلی

جاوا ۱۰ نیز پس از مدت کوتاهی از انتشار جاوا ۹ در ۲۰ مارس ۲۰۱۸ به صورت عمومی منتشر شده و کم‌کم باید خودمان را برای انتشار نسخه مهم‌تر یعنی جاوا ۱۱ آماده کنیم که قرار است سپتامبر سال آینده معرفی شود.
در نسخه ۱۰ تغییرات مشهود زیادی اضافه نشده و اکثر تغییرات و قابلیت‌ها مربوط به بهینه‌سازی JDK و موارد اینچنینی بوده. لیستی از این قابلیت‌ها را می‌توانید از طریق این لینک مشاهده کنید. اما یکی از این قابلیت‌ها یعنی قابلیت اسنتاج خودکار نوع متغیر‌های محلی یا Local-Variable Type Inference است که در JEP 286 مشخصات آن ذکر شده است.
اگر با زبان‌هایی مثل اسکالا یا پایتون کار کرده باشید این قابلیت برای شما آشنا خواهد بود. همانطور که از اسم آن مشخص است دیگر نیازی به مشخص کردن نوع متغیر‌های محلی خود ندارید و کامپایلر می‌تواند در زمان کامپایل نوع متغیر شما را به صورت خودکار تشخیص دهد.
بگذارید یک مثال ساده را ببینیم:

تا‌کنون مجبور بودیم به این شکل متغیر‌های خود را تعریف کنیم. از آنجایی که برنامه‌نویس‌ها معمولا انسان‌های تنبلی هستند(!) خیلی‌ها این ایده به ذهنشان رسید که شاید برای یک متد که بدنه آن کاملا معمولی است و با یک نگاه به اسم تابع آن می‌شود کارکرد آن را متوجه شد نیازی به این همه تایپ کردن نداریم و خود کامپایلر آنقدر باهوش هست که بفهمد ما از چه نوع تایپی استفاده کرده‌ایم.
پس کد بالا را به شکل زیر می‌نویسیم:

کار نگارنده این کد خیلی آسان شده! کافی است از کلمه کلیدی۱ var  استفاده کنید و به سادگی مثل قبل کد بزنید.

اما شاید از خودتان بپرسید می‌توانستیم از نوع Object یا List استفاده کنیم و اصلا نیازی به var نبود. یعنی:

همانطور که میبینید استفاده از نوع List رفتار مدنظر ما را عوض می‌کند و عملا کارکردی مشابه با var را ندارد.

قابلیت‌های تکمیل خودکار کد و کمک‌های IDE در صورت به روز بودن وجود خواهد داشت و بدون مشکل می‌توانید مثل سابق از این کمک‌ها استفاده کنید: (در اینجا از نسخه ۲۰۱۸٫۱ IntjelliJIDEA استفاده شده)

ممکن است فکر کنید وجود چنین مکانیزمی باعث کند شدن اجرا برنامه شما می‌شود چون به نظر شبیه کد‌های زبان‌های داینامیک مثل پایتون یا جاوا‌اسکریپت شده. اما درست مشابه زبان اسکالا (var/val)، سی‌شارپ (var) یا سی‌++ (auto) یا بقیه زبان‌های با تایپ استاتیک که مکانیزم استنتاج نوع داده‌ها در زمان کامپایل را دارند، استفاده از این قابلیت بر سرعت اجرای برنامه شما تاثیری ندارد و در نهایت بایت‌کد تولیدشده تفاوتی با نسخه معمولی آن ندارد.

وجود چنین قابلیتی بحث‌های فراوانی پیرامون خوانایی کد ایجاد می‌کند. آیا استفاده از این قابلیت خوانایی کد‌ها را افزایش می‌دهد؟ یا منجر به افزایش پیچیدگی کد‌ها و سخت‌تر کردن نگهداری کد‌ها می‌شود؟
طبیعتا هیچ قانونی وجود ندارد که چه زمانی به صورت صریح نوع داده‌ها را بیان کنیم و چه زمانی به شکل ضمنی آن‌ها را مشخص کنیم.
خبر خوب یا بد این است که شما نمی‌توانید در هرجایی از این قابلیت استفاده کنید و محدودیت‌هایی وجود دارد. فیلد‌های کلاسی، پارامتر‌های پاس داده‌شده به متد یا سازنده، نوع خروجی متد و نوع اکسپشن‌ها در بلوک catch نمی‌توانند از این قابلیت استفاده کنند. در واقع بهترین موارد استفاده مثلا در حلقه‌ها و متغیر‌های میانی و موارد اینچنینی هستند که آنقدر بدیهی هستند که اصلا نیازی به وجود خوانایی و نگه‌داری از آن‌ها نیست و فقط میخواهیم زودتر خودمان را از شر نوشتنشان خلاص کنیم و به قسمت‌های مهم‌تر برنامه برسیم. از آنجایی که دامنه استفاده از چنین امکانی محدود هست، خیلی تصمیم‌گیری سختی نداریم که چه وقت از آن استفاده کنیم و یا چه وقت از آن استفاده نکنیم و صراحت را ترجیح دهیم.
لازم به ذکر است که بدون مقداردهی نمی‌توانید از این قابلیت استفاده کنید. یعنی چنین کدی کامپایل نخواهد شد:

اما به این شکل هیچ موردی وجود ندارد:

در این مثال در قسمت catch نمی‌توانیم از var e استفاده کنیم:

یک نمونه از کاربرد خوب در استفاده از حلقه‌ها:

اما این فقط بخشی از این محدودیت‌ها است. یکی دیگر از محدودیت‌ها هنگامی است که سمت راست عبارت شما عبارت لامبدا‌یی نوشته شده باشد که خود نیاز به استنتاج دارد و نمی توانید در سمت چپ این عبارت از var استفاده کنید. تعدادی از این نوع مثال‌ها:

برای مطالعه بیشتر جزئیات حتما این لینک را مطالعه کنید.

۱- جالب است بدانید بسیاری از کلماتی که به عنوان کلمات کلیدی در جاوا ۹ و ۱۰ معرفی شده‌اند مثل module یا var واقعا کلمه کلیدی نیستند و در واقع “نام نوع رزروشده” (reserved type name) می‌باشند. دلیل اینکار حفظ قابلیت backward-compatibility است.

نوشته های مشابه

دیدگاهتان را بنویسید

نشانی ایمیل شما منتشر نخواهد شد. بخش‌های موردنیاز علامت‌گذاری شده‌اند *

دکمه بازگشت به بالا