جلسه شماره 89رایگان

Generic Limitation

00:18:55

توضیحات جلسه

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

جزوه و مستندات

مفاهیم کلیدی

  • Type Erasure

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

  • 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ها در زمان اجرا نوع خود را از دست می‌دهند. به همین دلیل نمی‌توان مستقیماً یک آرایه جنریک مانند new T ایجاد کرد.

  • چگونه می‌توان محدودیت instanceof را برای Genericها برطرف کرد؟

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

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

در این ویدیو، برای مدیریت محدودیت‌های Generic، از یک سناریوی مبتنی بر Reflection استفاده شده است.

برای اینکه بتوانیم در زمان اجرا متوجه شویم T چه نوع داده‌ای است یا از آن نمونه‌سازی کنیم، در سازنده یا Constructor کلاس، یک شیء از نوع Class<T> دریافت می‌کنیم.

با ذخیره کردن این Class در یک فیلد، می‌توانیم از متد newInstance() برای ساختن اشیای جدید یا از متد isInstance() برای بررسی نوع داده در زمان اجرا استفاده کنیم.

این روش به برنامه اجازه می‌دهد با وجود حذف شدن Genericها توسط کامپایلر، همچنان به نوع واقعی داده دسترسی داشته باشد.

بیشتر بدانید

  • نکته برنامه نویسی

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

  • نکته IDE

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

البته توصیه می‌شود تا حد امکان کد را طوری بنویسید که کامپایلر بتواند صحت آن را تضمین کند.

  • راه حل آرایه‌های Generic

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