Generic Limitation
📖توضیحات درس
📄جزوه
مفاهیم کلیدی
-
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استفاده کرد که نوع کلاس و طول آرایه را ورودی میگیرد.
