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

Generic Type Erasure

00:08:42

توضیحات جلسه

🎥 آموزش جاوا – قسمت هشتاد و یکم از بوت‌کمپ رایگان جاوا 📚 Generics in Java – Type Erasure Explained در ششمین ویدیو از پلی‌لیست تخصصی جنریک در جاوا می‌ریم سراغ یکی از مهم‌ترین مفاهیم پشت‌صحنه‌ی Generics؛ مفهومی که اگر دقیق درکش کنی، رفتار عجیب برخی از جنریک‌ها برات کاملاً قابل‌فهم می‌شه: 🎯 Type Erasure در این جلسه یاد می‌گیریم که جنریک‌ها در جاوا واقعاً چطور کار می‌کنن و بعد از کامپایل چه بلایی سرشون میاد! این همون جاییه که می‌فهمیم چرا جاوا در زمان اجرا type-safe نیست و چرا خیلی از محدودیت‌های جنریک‌ها وجود داره. در این ویدیو بررسی می‌کنیم: 📘 تعریف Type Erasure (Definition) در ابتدا توضیح می‌دیم Type Erasure دقیقاً چیه و چرا جاوا از این روش برای اجرای جنریک‌ها استفاده می‌کنه. ⚙️ قانون Erasure Rule در این بخش باز می‌کنیم که: چطور پارامترهای جنریک به نوع خام (Raw Type) تبدیل می‌شن چگونه boundsها روی type parameterها تأثیر می‌گذارن و چرا استفاده از برخی قابلیت‌ها در جنریک‌ها محدود شده 🔁 مرور نهایی (Review) در پایان جلسه یک جمع‌بندی داریم تا مطمئن بشیم Type Erasure و قوانینش به‌طور کامل در ذهن تثبیت شده. لینک داکیومنت تدریس: https://github.com/farzadafi/ProgrammingByFarzadAfi/tree/master/document/generic 💬 گروه پرسش و پاسخ تلگرام: @programmingByFarzadAfi 💬 گروه پرسش و پاسخ بله: @programming_by_farzadafi هر سؤالی داشتی، داخل گروه بپرس؛ من و مربی‌های گروه همیشه آماده کمک هستیم 💬 🎯 بوت‌کمپ رایگان جاوا – آموزش پروژه‌محور برای یادگیری اصولی و آماده‌سازی برای ورود به بازار کار

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

مفاهیم کلیدی

  • Type Erasure

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

  • Raw Type

به حالتی گفته می‌شود که یک کلاس یا اینترفیس جنریک بدون مشخص کردن Type Parameter استفاده شود؛ برای مثال، استفاده از List به‌جای List<String>. کامپایلر در فرآیند پاکسازی نوع، پارامترها را با این حالت جایگزین می‌کند.

  • Upper Bound

محدودیتی است که با کلمه کلیدی extends روی Type Parameter اعمال می‌شود؛ مانند <T extends Number>. این کار باعث می‌شود کامپایلر بداند که تایپ ورودی حتماً باید از یک کلاس خاص مشتق شده باشد.

  • Diamond Operator

علامت <> است که در جاوا برای جلوگیری از تکرار تایپ هنگام نمونه‌سازی استفاده می‌شود. کامپایلر در زمان Compile Time محتوای داخل این عملگر را حذف می‌کند.

  • Casting

عملیاتی است که کامپایلر پس از حذف اطلاعات جنریک انجام می‌دهد تا مطمئن شود مقادیر بازگشتی با نوع مورد انتظار برنامه هماهنگ هستند و امنیت کد یا Type Safety حفظ می‌شود.


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

  • مفهوم Type Erasure چیست؟

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

  • اگر یک تایپ پارامتر بدون محدودیت Unbounded باشد، با چه چیزی جایگزین می‌شود؟

اگر پارامتر به‌صورت <T> تعریف شده باشد، کامپایلر آن را با کلاس Object جایگزین می‌کند.

  • تایپ پارامتر در حالت Bounded، مانند <T extends Number>، به چه چیزی تبدیل می‌شود؟

در این حالت، کامپایلر تمام استفاده‌های T را با اولین کران بالا جایگزین می‌کند. در مثال <T extends Number>، تایپ T با Number جایگزین می‌شود.

  • در صورت وجود چندین محدودیت Multiple Bounding، مانند <T extends A & B>، چه اتفاقی می‌افتد؟

کامپایلر Type Parameter را با اولین کلاس یا اینترفیس ذکرشده در لیست محدودیت‌ها جایگزین می‌کند. در این مثال، T با A جایگزین می‌شود.

  • چرا در خروجی نهایی بایت‌کد، اثری از جنریک نیست؟

چون جنریک‌ها در جاوا در سطح کامپایلر مدیریت می‌شوند. برای حفظ سازگاری عقب‌رو یا Backward Compatibility با نسخه‌های قدیمی JVM، اطلاعات جنریک در لایه Bytecode حذف می‌شوند.


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

فرض کنید یک کلاس جنریک به نام Stack<E> دارید که درون آن آرایه‌ای از جنس E تعریف شده است.

۱. قبل از کامپایل

شما کدی می‌نویسید که در آن Stack<String> ایجاد شده و فقط مقدارهای رشته‌ای دریافت می‌کند. این کار امنیت کد شما را در مرحله توسعه تضمین می‌کند.

۲. در مرحله Type Erasure

کامپایلر تمام Eها را بررسی می‌کند. اگر E محدود نشده باشد، آن را به Object تبدیل می‌کند. بنابراین کلاس شما در Bytecode به‌صورت یک Stack معمولی دیده می‌شود که با Object کار می‌کند.

۳. نتیجه نهایی

اگر متدی در این کلاس مقدار بازگشتی از جنس E داشته باشد، کامپایلر به‌صورت خودکار یک Casting به String در محل فراخوانی متد اضافه می‌کند تا برنامه بدون خطا اجرا شود.


بیشتر بدانید

  • نکته کامپایلر

پاکسازی نوع فقط در سطح کلاس‌ها اتفاق نمی‌افتد، بلکه در سطح Methodها نیز انجام می‌شود. اگر متدی ورودی جنریک بگیرد، امضای آن در Bytecode تغییر می‌کند و به تایپ پایه، مانند Object، تبدیل می‌شود.

  • قانون جایگزینی

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

  • امنیت در بایت‌کد

با وجود حذف اطلاعات جنریک، امنیت کد از بین نمی‌رود؛ زیرا کامپایلر قبلاً در مرحله Compile Time تمام بررسی‌های لازم را انجام داده و کدهای Casting لازم، یعنی Checkcast، را در Bytecode تزریق کرده است.