Farzad Afi Logo

FarzadAfi

آموزش تخصصی برنامه نویسی

Generic Limitation

📖توضیحات درس

📚 آموزش جاوا – قسمت هشتاد و دوم بوت‌کمپ رایگان جاوا 🎥 هفتمین ویدیو از پلی‌لیست جنریک‌ها در جاوا توی این جلسه می‌ریم سراغ یکی از مهم‌ترین موضوعات مربوط به Generics در جاوا: ✨ محدودیت‌های جنریک‌ها و کارهایی که نمی‌تونی باهاشون انجام بدی! در این ویدیو با مثال‌های عملی و ساده، دقیق بررسی می‌کنیم که چرا محدودیت‌های خاصی وجود داره و این موضوع چطور روی طراحی کد حرفه‌ای تأثیر می‌گذاره. 🎯 توی این قسمت یاد می‌گیریم: چرا نمی‌تونیم نوع جنریک جدید بسازیم و نوع T رو مستقیماً Instantiate کنیم مشکل ساخت آرایه‌های جنریک و راه‌حل‌های رایج دلیل اینکه نمی‌تونیم مقادیر static جنریک تعریف کنیم چرا نوع‌های Primitive در جنریک استفاده نمی‌شن محدودیت استفاده از instanceof T اینکه چرا نوع جنریک در زمان اجرا پاک می‌شود (Type Erasure) و پیامدهای آن آشنایی با محدودیت‌های Reflection در کار با Genericها و در پایان یک مرور کامل برای تثبیت مفاهیم ✨ لینک داکیومنت تدریس: https://github.com/farzadafi/ProgrammingByFarzadAfi/tree/master/document/generic 💬 گروه پرسش و پاسخ تلگرام: @programmingByFarzadAfi 💬 گروه پرسش و پاسخ بله: @programming_by_farzadafi هر سوالی داشتی داخل گروه بپرس؛ خودم یا مربی‌های گروه راهنماییت می‌کنیم 💬 🎯 بوت‌کمپ رایگان جاوا – آموزش پروژه‌محور برای ورود حرفه‌ای به بازار کار
00:18:55🎯رایگان

📄جزوه

مفاهیم کلیدی

  • Type Erasure فرآیندی در کامپایلر جاوا که طی آن تمام اطلاعات مربوط به Genericها حذف شده و با نوع Object (یا باند مربوطه) جایگزین می‌شوند تا کد با نسخه‌های قدیمی سازگار باشد.

  • Reflection قابلیتی در جاوا که اجازه می‌دهد در زمان اجرا (Run-time) به ساختار کلاس‌ها، متدها و فیلدها دسترسی داشته باشیم و محدودیت‌های معمول Generic را دور بزنیم.

  • Primitive Type انواع داده‌ای پایه مانند int و boolean که به دلیل اینکه از نوع Object نیستند، نمی‌توانند به عنوان آرگومان در Genericها استفاده شوند.

  • Wrapper Class کلاس‌های معادلی برای انواع داده‌ای پایه (مانند Integer برای int) که اجازه می‌دهند از Primitiveها در محیط‌های شیءگرا و Generic استفاده کنیم.

  • Static Member اعضایی از کلاس (متد یا فیلد) که متعلق به خودِ کلاس هستند و نه به یک Instance خاص؛ به همین دلیل نمی‌توانند از Generic Type کلاس استفاده کنند.

موارد مصاحبه ای

  • چرا نمی‌توان یک نمونه از Generic Type را مستقیماً با دستور new T() ایجاد کرد؟ به دلیل عملیات Type Erasure، در زمان اجرا (Run-time) نوع واقعی T حذف شده و تبدیل به Object می‌شود. بنابراین JVM نمی‌داند دقیقاً از چه کلاسی باید نمونه‌سازی کند.

  • دلیل محدودیت استفاده از Primitive Typeها در Genericها چیست؟ در جاوا Genericها بر پایه Object کار می‌کنند و Type Erasure آن‌ها را به Object تبدیل می‌کند. چون Primitiveها از Object ارث‌بری نمی‌کنند، نمی‌توانند جایگزین Generic Typeها شوند.

  • چرا تعریف فیلدهای استاتیک از نوع Generic (مثلاً static T myField) مجاز نیست؟ فیلدهای استاتیک بین تمام نمونه‌های یک کلاس مشترک هستند، در حالی که Generic Type در هر Instance می‌تواند متفاوت باشد (مثلاً یک شیء با Integer و دیگری با String). این تضاد مانع از تعریف استاتیک برای Genericها می‌شود.

  • تفاوت آرایه‌ها و Genericها در برخورد با نوع داده (Type) چیست؟ آرایه‌ها نوع داده خود را در زمان اجرا حفظ می‌کنند (Reified)، اما Genericها در زمان اجرا نوع خود را از دست می‌دهند. به همین دلیل نمی‌توان مستقیماً یک آرایه Generic مانند new T ایجاد کرد.

  • چگونه می‌توان محدودیت instanceof را برای Genericها برطرف کرد؟ از آنجا که در زمان اجرا T وجود ندارد، نمی‌توان از instanceof T استفاده کرد. راه حل جایگزین، استفاده از Reflection و متد isInstance() روی کلاسِ مربوط به آن نوع داده است.

سناریو کاربردی

در این ویدیو، برای غلبه بر محدودیت‌های Generic، از یک سناریوی مبتنی بر Reflection استفاده شده است. برای اینکه بتوانیم در زمان اجرا متوجه شویم T چه نوع داده‌ای است یا از آن نمونه‌سازی کنیم، در سازنده (Constructor) کلاس، یک شیء از جنس Class<T> دریافت می‌کنیم. با ذخیره کردن این Class در یک فیلد، می‌توانیم از متد newInstance() برای ساختن اشیاء جدید یا از isInstance() برای چک کردن نوع داده در زمان اجرا استفاده کنیم. این روش به برنامه اجازه می‌دهد با وجود حذف شدن Genericها توسط کامپایلر، همچنان به نوع واقعی داده دسترسی داشته باشد.

بیشتر بدانید

  • نکته برنامه نویسی برای استفاده از اعداد یا مقادیر منطقی در Genericها، حتماً باید از رپر کلاس‌ها استفاده کنید؛ برای مثال به جای int از Integer و به جای char از Character استفاده نمایید.

  • نکته IDE در محیط IntelliJ IDEA، اگر هنگام کار با Reflection و تبدیل انواع (Casting) با Warningهای زرد رنگ مواجه شدید، می‌توانید با اطمینان از صحت کد، از انوتیشن @SuppressWarnings("unchecked") استفاده کنید، هرچند توصیه می‌شود تا حد امکان کد را طوری بنویسید که کامپایلر بتواند صحت آن را تضمین کند.

  • راه حل آرایه‌های Generic برای ساخت آرایه از نوع Generic، به جای دستور مستقیم new باید از متد استاتیک Array.newInstance در پکیج java.lang.reflect استفاده کرد که نوع کلاس و طول آرایه را ورودی می‌گیرد.