1. Sahələr haqqında məlumatın alınması
getFields() və getDeclaredFields() nə ilə fərqlənir
Java-da hər bir sinifin sahələri (fields) var — sinifin daxilində elan edilmiş dəyişənlər. Refleksiya vasitəsilə onların adlarını, tiplərini, giriş modifikatorlarını (public/private) öyrənə və həmçinin icra zamanı onlara çıxış əldə edə bilərik. Əsas giriş nöqtəsi — Class<?> obyekti.
Sahələrlə işləmək üçün Class sinifinin əsas metodları:
| Metod | Nə qaytarır |
|---|---|
|
Sinifin, onun üst siniflərinin və interfeyslərinin bütün public sahələrinin massivi |
|
Bütün bu sinifdə elan edilmiş sahələrin massivi |
Oxşarlıq: getFields() — sanki yalnız nümayiş zallarına (public) ekskursiyadır, getDeclaredFields() isə — əlavə olaraq texniki otaqlara da (private, protected, package-private).
Nümunə: sinifin bütün sahələrini çıxarırıq
Tutaq ki, bizdə belə bir sinif var:
public class Person {
public String name;
private int age;
protected String email;
}
Sahələr haqqında məlumat alaq:
import java.lang.reflect.Field;
Class<?> clazz = Person.class;
// Bütün public sahələr (miras alınanlar daxil olmaqla)
System.out.println("Public fields:");
for (Field field : clazz.getFields()) {
System.out.println(field.getName() + " : " + field.getType().getSimpleName());
}
// Bu sinifdə elan edilən bütün sahələr (private daxil olmaqla, yalnız bu sinfin sahələri)
System.out.println("\nDeclared fields:");
for (Field field : clazz.getDeclaredFields()) {
System.out.println(field.getName() + " : " + field.getType().getSimpleName());
}
Nəticə:
Public fields:
name : String
Declared fields:
name : String
age : int
email : String
Sahənin modifikatorlarını necə öyrənmək olar?
Hər bir sahənin (Field) modifikatorları var (public/private/protected, static, final və s.). Onları getModifiers() vasitəsilə almaq və Modifier ilə sətirə çevirmək olar:
import java.lang.reflect.Modifier;
for (Field field : clazz.getDeclaredFields()) {
int mods = field.getModifiers();
System.out.println(field.getName() + " : " + Modifier.toString(mods));
}
2. Metodlar haqqında məlumatın alınması
getMethods() və getDeclaredMethods() metodları
Metodlar — obyektin yerinə yetirə bildiyi əməliyyatlardır. Refleksiya vasitəsilə sinifdə hansı metodların olduğunu, onların parametrlərini, qaytardığı tipləri, modifikatorlarını və annotasiyalarını öyrənmək olar.
| Metod | Nə qaytarır |
|---|---|
|
Sinifin və onun üst siniflərinin bütün public metodları (Object daxil olmaqla) |
|
Bu sinifdə elan edilən bütün metodlar (private daxil olmaqla) |
Nümunə: sinifin bütün metodlarını çıxarırıq
import java.lang.reflect.Method;
System.out.println("Public methods:");
for (Method method : clazz.getMethods()) {
System.out.println(method.getName());
}
System.out.println("\nDeclared methods:");
for (Method method : clazz.getDeclaredMethods()) {
System.out.println(method.getName());
}
Nəticə (Person üçün):
Public methods:
getClass
hashCode
equals
toString
notify
notifyAll
wait
wait
wait
Declared methods:
(heç nə, əgər Person daxilində öz metodları elan edilməyibsə)
Person-a metod əlavə edək:
public class Person {
public String name;
private int age;
protected String email;
public void sayHello() {
System.out.println("Hi!");
}
}
İndi getDeclaredMethods() onu da göstərəcək.
Metodun parametrlərini və qaytarma tipini necə öyrənmək olar?
for (Method method : clazz.getDeclaredMethods()) {
System.out.print(Modifier.toString(method.getModifiers()) + " ");
System.out.print(method.getReturnType().getSimpleName() + " ");
System.out.print(method.getName() + "(");
Class<?>[] params = method.getParameterTypes();
for (int i = 0; i < params.length; i++) {
System.out.print(params[i].getSimpleName());
if (i < params.length - 1) System.out.print(", ");
}
System.out.println(");");
}
Çıxış:
public void sayHello();
3. Konstruktorlar haqqında məlumatın alınması
Konstruktorlar obyektlərin yaradılması üçün istifadə olunan xüsusi metodlardır.
| Metod | Nə qaytarır |
|---|---|
|
Bütün public konstruktorlar |
|
Sinifdə elan edilən bütün konstruktorlar |
Nümunə: sinifin bütün konstruktorlarını çıxarırıq
import java.lang.reflect.Constructor;
System.out.println("Constructors:");
for (Constructor<?> constructor : clazz.getDeclaredConstructors()) {
System.out.print(clazz.getSimpleName() + "(");
Class<?>[] params = constructor.getParameterTypes();
for (int i = 0; i < params.length; i++) {
System.out.print(params[i].getSimpleName());
if (i < params.length - 1) System.out.print(", ");
}
System.out.println(");");
}
Əgər sinifdə yalnız standart (default) konstruktor elan olunubsa, o da çıxarılacaq.
4. Annotasiyalar: sinifin, metodun və ya sahənin hansı annotasiyalarla işarələndiyini necə bilmək olar
Annotasiyalar siniflərə, metodlara, sahələrə və parametrlərə əlavə edilən xüsusi nişanlardır. Refleksiya vasitəsilə elementdə hansı annotasiyaların olduğunu öyrənmək olar.
Annotasiyaların əldə edilməsi
- Sinif üçün: clazz.getAnnotations()
- Metod üçün: method.getAnnotations()
- Sahə üçün: field.getAnnotations()
Nümunə: @Deprecated annotasiyasının olub-olmadığını yoxlayaq
for (Method method : clazz.getDeclaredMethods()) {
if (method.isAnnotationPresent(Deprecated.class)) {
System.out.println(method.getName() + " is @Deprecated");
}
}
Nümunə: sinifin bütün annotasiyalarını çıxarırıq
for (var annotation : clazz.getAnnotations()) {
System.out.println(annotation);
}
5. Praktika: sinifin strukturunu təhlil edən mini‑proqram
Gəlin hamısını birləşdirək və sinifin adı veriləndə onun strukturunu: sahələrini, metodlarını, konstruktorlarını və annotasiyalarını çıxaran kiçik bir utilit yazaq.
Kod nümunəsi: ClassInspector
import java.lang.reflect.*;
import java.util.Scanner;
public class ClassInspector {
public static void main(String[] args) throws Exception {
Scanner scanner = new Scanner(System.in);
System.out.print("Sinifin tam adını daxil edin (məsələn, java.util.ArrayList): ");
String className = scanner.nextLine();
Class<?> clazz = Class.forName(className);
System.out.println("\n== Sinif: " + clazz.getName() + " ==");
// Sinifin annotasiyaları
System.out.println("Annotasiyalar:");
for (Annotation annotation : clazz.getAnnotations()) {
System.out.println(" " + annotation);
}
// Sahələr
System.out.println("\nSahələr:");
for (Field field : clazz.getDeclaredFields()) {
System.out.println(" " + Modifier.toString(field.getModifiers())
+ " " + field.getType().getSimpleName()
+ " " + field.getName());
}
// Metodlar
System.out.println("\nMetodlar:");
for (Method method : clazz.getDeclaredMethods()) {
System.out.print(" " + Modifier.toString(method.getModifiers())
+ " " + method.getReturnType().getSimpleName()
+ " " + method.getName() + "(");
Class<?>[] params = method.getParameterTypes();
for (int i = 0; i < params.length; i++) {
System.out.print(params[i].getSimpleName());
if (i < params.length - 1) System.out.print(", ");
}
System.out.println(");");
}
// Konstruktorlar
System.out.println("\nKonstruktorlar:");
for (Constructor<?> constructor : clazz.getDeclaredConstructors()) {
System.out.print(" " + Modifier.toString(constructor.getModifiers())
+ " " + clazz.getSimpleName() + "(");
Class<?>[] params = constructor.getParameterTypes();
for (int i = 0; i < params.length; i++) {
System.out.print(params[i].getSimpleName());
if (i < params.length - 1) System.out.print(", ");
}
System.out.println(");");
}
}
}
Bu necə işləyir?
- İstifadəçi sinifin tam adını daxil edir (məsələn, "java.util.ArrayList" və ya öz sinfini).
- Proqram sinfi dinamik şəkildə yükləyir və onun annotasiyalarını, sahələrini, metodlarını və konstruktorlarını çıxarır.
- JDK-nın standart siniflərində sınayın — daxilində nə qədər maraqlı şeyin gizləndiyini görəcəksiniz!
6. Faydalı nüanslar və vizuallaşdırma
Vizual sxem: refleksiya vasitəsilə sinif haqqında nələri öyrənmək olar
graph TD
A[Class<?>] --> B["getFields/getDeclaredFields"]
A --> C[getMethods/getDeclaredMethods]
A --> D[getConstructors/getDeclaredConstructors]
A --> E[getAnnotations]
B --> F[Field: tip, ad, modifikatorlar]
C --> G[Method: qaytarılan tip, parametrlər]
D --> H[Constructor: parametrlər]
E --> I["Annotation[]"]
Cədvəl: məlumatı harada axtarmaq olar
| Nəyi öyrənmək istəyirik | Refleksiya ilə necə əldə etməli |
|---|---|
| Bütün public sahələr | |
| Bütün elan edilən sahələr | |
| Bütün public metodlar | |
| Bütün elan edilən metodlar | |
| Bütün public konstruktorlar | |
| Bütün elan edilən konstruktorlar | |
| Sinifin annotasiyaları | |
| Metodun/sahənin annotasiyaları | |
| Modifikatorlar | |
7. Refleksiya ilə işləyərkən tipik səhvlər
Səhv №1: getFields() və getDeclaredFields() qarışdırılır.
Əgər siz private sahələri axtarırsınızsa, getDeclaredFields()-dən istifadə edin, yoxsa getFields()-dən. Birincisi sinifdə elan edilən bütün sahələri qaytarır, ikincisi isə yalnız public sahələri (və miras alınanları!).
Səhv №2: Yoxlanılan (checked) istisnalar işlənmir.
Refleksiya metodlarının bir çoxu istisna atır (məsələn, ClassNotFoundException və ya SecurityException). Onları ya emal etməyi, ya da metodun siqnatürasında elan etməyi unutmayın.
Səhv №3: Giriş modifikatorları nəzərə alınmır.
private sahə və metodlara çıxış yalnız setAccessible(true) çağırıldıqdan sonra mümkündür, əks halda IllegalAccessException olacaq. Nümunə:
Field field = clazz.getDeclaredField("age");
field.setAccessible(true); // private sahəyə çıxışı açırıq
int value = (int) field.get(person);
Səhv №4: Yalnız öz metodlarını/sahələrini görməyi gözləyirlər.
getMethods() və getFields() yalnız cari sinifin deyil, bütün üst siniflərin də public üzvlərini qaytarır, Object daxil olmaqla. Əgər yalnız öz yazdıqlarınızı görməyi gözləyirsinizsə, bu sizi təəccübləndirə bilər.
Səhv №5: Annotasiyaların mövcudluğu düzgün yoxlanmır.
Konkret annotasiyanı yoxlamaq üçün isAnnotationPresent()-dən istifadə edin; ehtiyac olmadan annotasiya massivi üzərindən əl ilə keçməyin.
GO TO FULL VERSION