آشنایی با Reflection در جاوا
از سری مقالات آموزش جاوا, مبحث Reflection در جاوا را مورد بررسی قرار میدهیم.
بر اساس تعریف, Reflection به دستوراتی گفته میشود که رفتاری را در زمان اجرا, تعریف و یا بررسی میکند. بر اساس این خاصیت, با استفاده از Reflection میتوان رفتاری را به برنامه اضافه کرد که باعث بهینه شدن و بهبود کارایی برنامه شود. رفتاری که ممکن است در حالت کدنویسی عادی غیر ممکن باشد.
مزیت های استفاده از Reflection
با استفاده از Reflection میتوان به کلاس های موجود خواصی اضافه کرد به این ترتیب میتوانیم کلاس های موجود را متناسب با پروژه گسترش دهیم. Reflection میتوان یک ابزار بسیار کارامد برای Debugger ها برای ایجاد Test tools باشد. این افراد میتوانند به متد های درون کلاس ها دسترسی پیدا کنند و متناسب با نیاز خود, کارکرد برنامه و یا کلاس مد نظر را بررسی کنند. برای مثال در Junit از Reflection برای دسترسی به متد هایی که میخواهیم بررسی کنیم, استفاده میشود.
معایب استفاده از Reflection
بهبود کارایی و بهینگی یکی از مزیت های استفاده از Reflection است. اما باید این نکته را مد نظر داشته باشیم که گاهی استفاده از Reflection باعث میشود تا کارایی تمام برنامه کاهش یابد. بنابراین باید به صورت هوشمندانه از این ابزار استفاده کرد. علت این امر این است که یکسری تعاریف و بررسی ها در زمان اجرا صورت میگیرند. بنابراین Java Virtual Machine در بعضی از موارد نمیتواند بهینه سازی را انجام دهد و ممکن است این عمل بر روی کارایی تمام برنامه, تاثیر منفی بگذارد. همچنین reflection در زمان اجرا پردازش را بر روی کلاس ها انجام میدهد. بنابراین به Runtime Permission نیاز دارد. این دسترسی ممکن است از سوی security manager رد شود. در نهایت باید به این نکته اشاره کرد که در Reflection میتوانیم به متغیر ها و متد های private نیز دسترسی پیدا کنیم. بنابراین تغییر در رفتار این متد و متغیر ها, ممکن است رفتار غیر قابل پیش بینی برنامه را نیز به همراه داشته باشد.
مثال هایی از کاربرد Reflection
اکنون مثال هایی از کاربرد reflection را بررسی میکنیم. فرض کنید چنین کلاسی داریم و میخواهیم متد های موجود در آن را توسط کلاس دیگری بخوانیم:
public class ZeroToHero { private String username; private String password; private String subject; private String getUsername() { return username; } private void setUsername(String username) { this.username = username; } private String getPassword() { return password; } private void setPassword(String password) { this.password = password; } private String getSubject() { return subject; } private void setSubject(String subject) { this.subject = subject; }
سپس با استفاده از این دستور, متد های این کلاس را میخوانیم:
Method[] m = ZeroToHero.class.getDeclaredMethods(); Field[] vars = ZeroToHero.class.getDeclaredFields(); for (Method ms : m) { System.out.println(ms.getName()); } for (Field f : vars) { System.out.println(f.getName()); }
همانطور که مشاهده میکنید, این متد ها و متغیر ها به صورت private بودند. با این حال با استفاده از reflection به آن دسترسی پیدا کردهایم.
اکنون با استفاده از Reflection یک مقدار private را مقدار دهی میکنیم و خروجی آن را بررسی خواهیم کرد:
ZeroToHero zeroToHero=new ZeroToHero(); try { Field username = ZeroToHero.class.getDeclaredField("username"); username.setAccessible(true); username.set(zeroToHero, "vhdrjb"); } catch (NoSuchFieldException e) { e.printStackTrace(); } catch (IllegalAccessException e) { e.printStackTrace(); } System.out.println(zeroToHero.getUsername()); }
اگر کد فوق را اجرا کنید, مشاهده خواهید کرد که username مقدار مورد نظر را در خروجی چاپ میکند.
اگر بخواهیم یک متد را مقدار دهی کنیم نیز میتوانیم از این روش استفاده کنیم:
ZeroToHero zeroToHero=new ZeroToHero(); try { Method usernameMethod = ZeroToHero.class.getDeclaredMethod("setUsername", String.class); usernameMethod.setAccessible(true); usernameMethod.invoke(zeroToHero, "vhdrjb with method"); } catch (NoSuchMethodException e) { e.printStackTrace(); } catch (IllegalAccessException e) { e.printStackTrace(); } catch (InvocationTargetException e) { e.printStackTrace(); } System.out.println(zeroToHero.getUsername());
ابزار و Framework هایی که از Reflection استفاده میکنند
همانطور که در راستای مقاله اشاره شد, Reflection میتواند یک ابزار بسیار پر کاربرد باشد. Reflection در Junit از آن برای پیدا کردن متد هایی که باید بررسی شوند, استفاده میشود. Spring Framework برای Dependecy Injection و Tomcat برای هدایت درخواست به module مورد نظر, IDE ها برای auto complete و یک Framework هایی مانند Struct و Hibernate از Reflection استفاده میکنند.
نتیجه
Reflection یک ابزار بسیار پرقدرت در جاوا است که استفاده بجا از آن میتواند توانایی های بسیاری را به برنامه نویس دهد. همچنین باید توجه داشته باشیم که استفاده زیاد از Reflection باعث کاهش بهینگی و کارایی میشود و ممکن است باعث بروز اشکالاتی در منطق برنامه شود.
با ما همراه باشید
دیدگاهتان را بنویسید
برای نوشتن دیدگاه باید وارد بشوید.