Farzad Afi Logo

FarzadAfi

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

Generic Type Erasure

📖توضیحات درس

🎥 آموزش جاوا – قسمت هشتاد و یکم از بوت‌کمپ رایگان جاوا 📚 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 هر سؤالی داشتی، داخل گروه بپرس؛ من و مربی‌های گروه همیشه آماده کمک هستیم 💬 🎯 بوت‌کمپ رایگان جاوا – آموزش پروژه‌محور برای یادگیری اصولی و آماده‌سازی برای ورود به بازار کار
00:08:42🎯رایگان

📄جزوه

مفاهیم کلیدی

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

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

  • Upper Bound محدودیتی که با کلمه کلیدی extends روی تایپ پارامتر اعمال می‌شود (مثلاً <T extends Number>). این کار باعث می‌شود کامپایلر بداند که تایپ ورودی حتماً باید از یک کلاس خاص مشتق شده باشد.

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

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


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

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

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

  • تایپ پارامتر در حالت Bounded (مثلاً <T extends Number>) به چه چیزی تبدیل می‌شود؟ در این حالت، کامپایلر تمامی تکرارهای T را با اولین کران بالا که در اینجا Number است، جایگزین می‌کند.

  • در صورت وجود چندین محدودیت (Multiple Bonding) مانند <T extends A & B> چه اتفاقی می‌افتد؟ کامپایلر تایپ پارامتر را با اولین کلاس یا اینترفیس ذکر شده در لیست محدودیت‌ها (در اینجا کلاس A) جایگزین می‌کند.

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


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

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

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

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

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


بیشتر بدانید

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

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

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