Execute method and create object with Reflection java
توضیحات جلسه
جزوه و مستندات
مفاهیم کلیدی
- Reflection
یک قابلیت قدرتمند در Java که به برنامه اجازه میدهد در زمان اجرا (Runtime) ساختار درونی خود، شامل کلاسها، فیلدها، متدها و کانستراکتورها را بررسی کرده و حتی به اعضای private دسترسی پیدا کند.
- Method.invoke
متدی در API رفلکشن که برای اجرای (Execute) یک method خاص بر روی یک object استفاده میشود. این متد پارامترهایی برای مشخص کردن شیء هدف و آرگومانهای ورودی متد دریافت میکند.
- setAccessible
متدی که برای تغییر وضعیت دسترسی اعضای کلاس (مانند private field یا private method) به کار میرود. با مقداردهی true به این متد، محدودیتهای دسترسی زبان جاوا دور زده شده و اجازه کار با اعضای مخفی کلاس داده میشود.
- Constructor.newInstance
روشی برای ساخت یک object جدید از کلاس با استفاده از یک constructor مشخص. این روش جایگزین مدرن و ایمنتر برای Class.newInstance است و اجازه میدهد حتی با کانستراکتورهای پارامتریک و private شیء بسازیم.
- getDeclaredMethods
متدی که لیست تمامی متدهای تعریفشده در یک کلاس، اعم از public، protected و private را برمیگرداند؛ این در حالی است که متد getMethods فقط متدهای عمومی را شامل میشود.
- VarArgs (Variable Arguments)
مکانیزمی در جاوا که اجازه میدهد یک متد تعداد نامشخصی آرگومان ورودی دریافت کند. در رفلکشن، متدهای invoke و newInstance از این قابلیت برای دریافت پارامترهای متد هدف استفاده میکنند.
موارد مصاحبه ای
- چگونه میتوان یک متد private را با استفاده از Reflection فراخوانی کرد؟
ابتدا باید با استفاده از getDeclaredMethod به متد دسترسی پیدا کرد. سپس با فراخوانی setAccessible(true) بر روی آن، سطح دسترسی را تغییر داد و در نهایت با استفاده از invoke آن را اجرا نمود.
- تفاوت بین getMethods و getDeclaredMethods در چیست؟
متد getMethods تمامی متدهای public کلاس و همچنین متدهای عمومی که از کلاسهای والد (مثل Object) به ارث رسیده را برمیگرداند. اما getDeclaredMethods فقط متدهایی را برمیگرداند که دقیقاً در همان کلاس تعریف شدهاند (شامل متدهای خصوصی)، اما متدهای ارثبری شده را شامل نمیشود.
- چرا استفاده از Class.newInstance() از جاوا ۹ به بعد منسوخ (Deprecated) شده است؟
زیرا این متد فقط میتواند کانستراکتورهای بدون آرگومان (no-arg) را فراخوانی کند و در مدیریت خطاهای زمان اجرا (Exceptions) دقت کافی ندارد. جایگزین بهتر، استفاده از getConstructor().newInstance() است که انعطافپذیری و امنیت بیشتری دارد.
- آیا رفلکشن میتواند کپسولهسازی (Encapsulation) را نقض کند؟
بله، رفلکشن با استفاده از ابزارهایی مانند setAccessible(true) میتواند به اعضای private کلاس دسترسی پیدا کرده و مقادیر آنها را تغییر دهد یا آنها را اجرا کند، که عملاً مرزهای کپسولهسازی را جابهجا میکند.
سناریو کاربردی
در این ویدیو، سناریوی تغییر یک فیلد خصوصی و اجرای یک متد مخفی پیادهسازی شده است. فرض کنید کلاسی دارید که نام کاربر را در یک فیلد private نگه میدارد و تنها یک متد private برای تغییر آن دارد. در حالت عادی هیچ راهی برای فراخوانی این متد از خارج کلاس وجود ندارد.
مدرس نشان میدهد که چگونه با استفاده از رفلکشن، ابتدا متد changeFirstName را شناسایی کرده، قفل دسترسی آن را با setAccessible باز میکند و سپس با invoke نام جدید را به آن تزریق میکند. همچنین نشان داده میشود که چگونه میتوان با استفاده از یک private constructor که دو رشته دریافت میکند، یک نمونه کاملاً جدید از کلاس ایجاد کرد، در حالی که در کدنویسی معمولی این کار غیرممکن است.
بیشتر بدانید
- نکته در مورد مدیریت خطا
هنگام کار با رفلکشن، همیشه باید Checked Exceptions مانند NoSuchMethodException یا IllegalAccessException را مدیریت کنید، زیرا رفلکشن در زمان اجرا عمل میکند و کامپایلر نمیتواند وجود یا عدم وجود متدها را پیشبینی کند.
- نکته در مورد شیء Class
برای شروع هر عملیات رفلکشن، ابتدا باید به شیء Class دسترسی داشته باشید که از دو راه obj.getClass() یا ClassName.class امکانپذیر است. نسخه جدیدتر و مستقلتر نیز استفاده از Class.forName("Full_Path_Address") است.
