java.lang.reflect.Field वर्ग

फ़ील्ड क्लास किसी वर्ग या इंटरफ़ेस के एकल फ़ील्ड के बारे में जानकारी और गतिशील पहुँच प्रदान करता है फ़ील्ड प्राप्त या सेट एक्सेस ऑपरेशन के दौरान एक विस्तृत प्रकार के रूपांतरण की भी अनुमति देता है, लेकिन यदि संकुचन होता है तो IllegalArgumentException फेंकता है।

फ़ील्ड ऑब्जेक्ट प्राप्त करने के लिए , हम पहले एक क्लास लिखेंगे:


public class Person {
    private String name;
    private int age;
    
    public boolean isMale;
    
    protected String address;
    
    public static final int MAX_AGE = 120;
    public static final int MIN_AGE = 0;
}

और यहाँ उस वर्ग के साथ काम करने के लिए हमारा कोड है:


public class Main {
    public static void main(String[] args) {
        Field[] fields = Person.class.getDeclaredFields();
        List<Field> actualFields = getFieldNames(fields);
        System.out.println(actualFields);
    }

    static List<Field> getFieldNames(Field[] fields) {
        return List.of(fields);
    }
}

इस प्रकार हमें अपनी कक्षा के क्षेत्रों की सूची मिलती है, जिसके साथ हम बाद में काम करेंगे। यहाँ परिणाम है:

[निजी java.lang.String com.company.Person.name, निजी int com.company.Person.age, सार्वजनिक बूलियन com.company.Person.isMale, संरक्षित java.lang.String com.company.Person.address, सार्वजनिक स्थिर अंतिम int com.company.Person.MAX_AGE, सार्वजनिक स्थैतिक अंतिम int com.company.Person.MIN_AGE]

अब आइए जानें कि हम इस डेटा के साथ क्या कर सकते हैं। आइए फील्ड क्लास के तरीकों के बारे में बात करते हैं:

तरीका विवरण
गेट टाइप () एक क्लास ऑब्जेक्ट लौटाता है जो इसके द्वारा दर्शाए गए फ़ील्ड के घोषित प्रकार की पहचान करता हैमैदानवस्तु।
getAnnotatedType () एक देता हैएनोटेट टाइपऑब्जेक्ट जो इस फ़ील्ड द्वारा दर्शाए गए फ़ील्ड के घोषित प्रकार को निर्दिष्ट करने के लिए एक प्रकार के उपयोग का प्रतिनिधित्व करता है।
getGenericType () रिटर्न एप्रकारऑब्जेक्ट जो इसके द्वारा दर्शाए गए क्षेत्र के घोषित प्रकार का प्रतिनिधित्व करता हैमैदानवस्तु।
गेटनाम () इसके द्वारा दर्शाए गए क्षेत्र का नाम लौटाता हैमैदानवस्तु।
getModifiers () इसके द्वारा दर्शाए गए क्षेत्र के लिए जावा भाषा संशोधक एक इंट एन्कोडिंग लौटाता हैमैदानवस्तु।
getAnnotations () इस क्षेत्र के लिए एनोटेशन लौटाता है। यदि कोई एनोटेशन नहीं है, तो यह एक खाली सरणी देता है।

getType (), getName (), और getModifiers () विधियाँ

हम अपने क्षेत्र का प्रकार प्राप्त करने के लिए getType() विधि का उपयोग कर सकते हैं। आइए एक विधि लिखें:


static void printTypes(List<Field> fields){
      fields.forEach(e -> System.out.println(e.getType()));
  }

और हमें यह परिणाम मिलता है:

वर्ग java.lang.String
int
बूलियन
वर्ग java.lang.String
int
int

अब एक क्षेत्र का नाम प्राप्त करने के लिए अपनी कक्षा में एक विधि जोड़ते हैं। इससे हमारी कक्षा के क्षेत्रों को नेविगेट करना आसान हो जाएगा।


static void printTypesAndNames(List<Field> fields){
   fields.forEach(e -> System.out.printf("Field type - %s\nField name - %s\n\n", e.getType(), e.getName()));
}

अब परिणाम अधिक समझ में आता है:

फ़ील्ड प्रकार - वर्ग java.lang.String
फ़ील्ड नाम - नाम

फ़ील्ड प्रकार - int
फ़ील्ड नाम - आयु

फ़ील्ड प्रकार - बूलियन
फ़ील्ड नाम - isMale

फ़ील्ड प्रकार - वर्ग java.lang.String
फ़ील्ड नाम - पता

फ़ील्ड प्रकार - int
फ़ील्ड नाम - MAX_AGE

फ़ील्ड प्रकार - int
फ़ील्ड का नाम - MIN_AGE

महान! आइए अपनी पद्धति को कुछ और संशोधित करें! हम यहां एक्सेस संशोधक जोड़ेंगे


static void printFieldInfo(List<Field> fields){
   fields.forEach(e -> System.out.printf("Field type - %s\nField name - %s\nModifiers - %s\n\n", e.getType(), e.getName(), Modifier.toString(e.getModifiers())));
}

और देखते हैं कि e.getModifiers() रिटर्न क्या देता है। यह विधि एक इंट लौटाती है जो हमें हमारे क्षेत्र के एक्सेस संशोधक की स्थिति निर्धारित करने देती है। संशोधक वर्ग में क्षेत्र के प्रत्येक विशिष्ट संशोधक के लिए जिम्मेदार स्थिर चर होते हैं।

चलिए हमारे रिटर्न वैल्यू को Modifier.toString() में रैप करते हैं और तुरंत टेक्स्ट के रूप में इसकी वैल्यू प्राप्त करते हैं:

फ़ील्ड प्रकार - वर्ग java.lang.String
फ़ील्ड नाम - नाम
संशोधक - निजी

फ़ील्ड प्रकार - int
फ़ील्ड नाम - आयु
संशोधक - निजी

फ़ील्ड प्रकार - बूलियन
फ़ील्ड नाम - isMale
संशोधक - सार्वजनिक

फ़ील्ड प्रकार - वर्ग java.lang.String
फ़ील्ड नाम - पता
संशोधक - संरक्षित

फ़ील्ड प्रकार - int
फ़ील्ड नाम - MAX_AGE
संशोधक - सार्वजनिक स्थैतिक अंतिम

फ़ील्ड प्रकार - int
फ़ील्ड नाम - MIN_AGE
संशोधक - सार्वजनिक स्थैतिक अंतिम

यह बिना Modifier.toString() के कैसा दिखता है :

फ़ील्ड प्रकार - वर्ग java.lang.String
फ़ील्ड नाम - नाम
संशोधक - 2

फ़ील्ड प्रकार - int
फ़ील्ड नाम - आयु
संशोधक - 2

फ़ील्ड प्रकार - बूलियन
फ़ील्ड नाम - isMale
संशोधक - 1

फ़ील्ड प्रकार - वर्ग java.lang.String
फ़ील्ड नाम - पता
संशोधक - 4

फ़ील्ड प्रकार - int
फ़ील्ड नाम - MAX_AGE
संशोधक - 25

फ़ील्ड प्रकार - int
फ़ील्ड नाम - MIN_AGE
संशोधक - 25

getAnnotations (), getAnnotatedType (), और getGenericType () विधियाँ

आइए इन विधियों के साथ काम करने के लिए व्यक्ति वर्ग को संशोधित करें। हम अपना एनोटेशन लिखेंगे और इसे अपने क्षेत्रों में लागू करेंगे। और हम कुछ और क्षेत्र जोड़ेंगे।

चलिए दो एनोटेशन बनाते हैं। हम पिग लैटिन में चर नाम को एक में पास करेंगे, और हम तत्वों के लिए दूसरे का उपयोग करेंगे:


@Target(value=ElementType.FIELD)
@Retention(value= RetentionPolicy.RUNTIME)
public @interface Name {
    String name();
}

@Target({ ElementType.TYPE_USE })
@Retention(RetentionPolicy.RUNTIME)
public @interface Number {
}

और हम अपना मुख्य वर्ग और व्यक्ति वर्ग बदल देंगे:


public class Person {
    @Name(name = "Ame-nay")
    private String name;

    @Name(name = "User nicknames")
    List<String> nicknames;

    private final Class<Object> type;

    private int @Number[] number;

    public Person(Class<Object> type) {
        this.type = type;
    }
}

public static void main(String[] args) {
    Field[] fields = Person.class.getDeclaredFields();
    List<Field> actualFields = getFieldNames(fields);
    
    printAdditionalInfo(actualFields);
}

static void printAdditionalInfo(List<Field> fields) {
   System.out.println("\ngetAnnotatedType:");
   fields.forEach(e -> System.out.println(e.getAnnotatedType()));

   System.out.println("\ngetGenericType:");
   fields.forEach(e -> System.out.println(e.getGenericType()));

   System.out.println("\ngetAnnotations:");
   fields.forEach(e -> System.out.println(Arrays.toString(e.getAnnotations())));
}

यह हमारे तरीकों के परिणामों को देखने और यह पता लगाने का समय है कि वे किस लिए हैं:

getAnnotatedType:
java.lang.Class<java.lang.Object>
java.util.List<java.lang.String>
java.lang.String
int @Number()[]

getGenericType:
java.lang.Class<java.lang. ऑब्जेक्ट>
java.util.List<java.lang.String>
क्लास java.lang.String
क्लास [मुझे

एनोटेशन मिलते हैं:
[]
[@Name(name="\u0055\u0073\u0065\u0072\u0020\u006e\u0069\u0063 \u006b\u006e\u0061\u006d\u0065\u0073")]
[@Name(name="\u0041\u006d\u0065\u002d\u006e\u0061\u0079")] [
]
  • getAnnotatedType दिए गए फ़ील्ड के लिए एनोटेशन लौटाता है, यदि कोई हो। हमें क्षेत्र के लिए एनोटेशन मिलता है और हम इसे पूरी तरह से देख सकते हैं।

  • getGenericType आपको पैरामिट्रीकृत प्रकार को सही ढंग से प्रदर्शित करने देता है।

  • getAnnotations हमारी वस्तु पर लागू एनोटेशन लौटाता है।

इस तरह हम आसानी से अपनी कक्षा में प्रत्येक क्षेत्र के बारे में सभी डेटा प्राप्त कर सकते हैं, साथ ही इसके एक्सेस संशोधक, एनोटेशन और डेटा प्रकार भी प्राप्त कर सकते हैं।

java.lang.reflect.Method वर्ग

बहुत अच्छा! हमने अपनी कक्षा के क्षेत्रों के बारे में बात की है। अब तरीकों के बारे में बात करने का समय आ गया है।

मेथड ऑब्जेक्ट प्राप्त करने के लिए , हम getMethod मेथड को कॉल करते हैं, इसे हमारे मेथड का नाम देते हैं। मेथड ऑब्जेक्ट प्राप्त करने का यह मूल तरीका है :


Method getNameMethod =  Person.class.getMethod("getName");

हम अपनी कक्षा के साथ काम करना जारी रखेंगे। आइए गेटर्स और सेटर्स, और हैशकोड, बराबर और टूस्ट्रिंग विधियों को जोड़ें:


public class Person {
    private String name;
    private int age;

    public boolean isMale;

    protected String address;

    public static final int MAX_AGE = 120;
    public static final int MIN_AGE = 0;

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public int getAge() {
        return age;
    }

    public void setAge(int age) {
        this.age = age;
    }

    public boolean isMale() {
        return isMale;
    }

    public void setMale(boolean male) {
        isMale = male;
    }

    public String getAddress() {
        return address;
    }

    public void setAddress(String address) {
        this.address = address;
    }

    @Override
    public String toString() {
        return "Person{" +
                "name='" + name + '\'' +
                ", age=" + age +
                ", isMale=" + isMale +
                ", address='" + address + '\'' +
                '}';
    }

    @Override
    public boolean equals(Object o) {
        if (this == o) return true;
        if (o == null || getClass() != o.getClass()) return false;
        Person person = (Person) o;
        return age == person.age && isMale == person.isMale && Objects.equals(name, person.name) && Objects.equals(address, person.address);
    }

    @Override
    public int hashCode() {
        return Objects.hash(name, age, isMale, address);
    }
}

अब मेथड्स का एक सेट तैयार करते हैं जिसे हम मेथड क्लास का उपयोग करके जांचेंगे । यहाँ सबसे महत्वपूर्ण तरीकों की एक सूची है:

तरीका विवरण
गेटनाम () विधि का नाम लौटाता है।
getModifiers () इस विधि का एक्सेस संशोधक लौटाता है।
गेटरिटर्न टाइप () विधि का रिटर्न प्रकार लौटाता है।
getGenericReturnType () विधि का रिटर्न प्रकार लौटाता है, सामान्य विधियों के लिए लेखांकन।
getParameterTypes () विधि पैरामीटर की एक सरणी देता है।
getGenericParameterTypes () सामान्य तरीकों के लिए लेखांकन, विधि पैरामीटर की एक सरणी देता है।
getExceptionTypes () उन अपवादों को लौटाता है जिन्हें विधि फेंक सकती है।
getGenericExceptionTypes () उन अपवादों को लौटाता है जिन्हें विधि फेंक सकती है, पैरामीटरयुक्त प्रकारों के लिए लेखांकन।
getAnnotations () पैरेंट एनोटेशन सहित विधि के लिए एनोटेशन लौटाता है।
getDeclaredAnnotations () पैरेंट एनोटेशन को छोड़कर विधि के लिए एनोटेशन लौटाता है।

हमारी कक्षा की विधियों की एक सरणी प्राप्त करने के लिए, हम इस विधि को कॉल कर सकते हैं:


Method[] methods = Person.class.getDeclaredMethods();

यह हमें हमारी कक्षा में सभी तरीके देगा।

getName () और getModifiers () विधियाँ

हम प्रत्येक विधि का नाम प्राप्त करने के लिए getName का उपयोग कर सकते हैं:


static List<String> getMethodsName(Method[] methods) {
    return Arrays.asList(methods)
            .stream()
            .map(Method::getName)
            .collect(ArrayList::new, ArrayList::add, ArrayList::addAll);
}

अब संशोधक प्राप्त करने के लिए, चलिए एक विधि लिखते हैं जो getModifiers का उपयोग करती है :


static List<String> getModifiers(Method[] methods) {
    return Arrays
            .stream(methods)
            .map(Method::getModifiers)
            .map(String::valueOf)
            .collect(ArrayList::new, ArrayList::add, ArrayList::addAll);
}

यहाँ हमारी मुख्य विधि है:


public static void main(String[] args) {
    Method[] methods = Person.class.getDeclaredMethods();

    System.out.println(getMethodsName(methods));
    System.out.println(getModifiers(methods));
}

हमारा परिणाम:

[getName, equals, toString, hashCode, setName, getAddress, isMale, getAge, setAge, setMale, setAddress]
[1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1]

हमारे सभी तरीकों में सार्वजनिक संशोधक है, इसलिए अंतिम विधि लोगों की एक सरणी लौटाती है। यदि हम अपना कोड संशोधित करते हैं, तो हम अपने संशोधक स्वयं देखेंगे:


public static void main(String[] args) {
    Method[] methods = Person.class.getDeclaredMethods();

    System.out.println(getMethodsName(methods));
    System.out.println(modifyModifiers(getModifiers(methods)));
}
[getName, equals, toString, hashCode, setName, getAddress, isMale, getAge, setAge, setMale, setAddress] [
सार्वजनिक, सार्वजनिक, सार्वजनिक, सार्वजनिक, सार्वजनिक, सार्वजनिक, सार्वजनिक, सार्वजनिक, सार्वजनिक, सार्वजनिक, सार्वजनिक]

getReturnedType ()

यह विधि हमें विधि का रिटर्न प्रकार प्राप्त करने देती है:


static void getReturnedType(Method[] methods) {
    Arrays.stream(methods)
            .map(Method::getReturnType)
            .forEach(System.out::println);
}
वर्ग java.lang.String
बूलियन
वर्ग java.lang.String
int
शून्य
वर्ग java.lang.String
बूलियन
int
शून्य
शून्य
शून्य

getGenericReturnType ()

आइए अपने व्यक्ति वर्ग को एक ऐसा तरीका दें जो एक पैरामीटरयुक्त प्रकार में लिपटे हुए प्रकार को लौटाता है, और इसका रिटर्न मान प्राप्त करने का प्रयास करता है:


public List<String> someMethod() {
    // Very useful and important method
    return null;
}

और हम अपनी मुख्य विधि को अपडेट करेंगे:


static void getGenericReturnType(Method[] methods) {
    Arrays.stream(methods)
            .map(Method::getGenericReturnType)
            .forEach(System.out::println);
}

हमारी विधि का परिणाम:

वर्ग java.lang.String
बूलियन
वर्ग java.lang.String int
शून्य
वर्ग
java.lang.String
बूलियन
int
शून्य
शून्य java.util.List<java.lang.String>

getParameterTypes() और getGenericParameterTypes() विधियाँ

हम दो और तरीकों को जोड़ते हुए अपने व्यक्ति वर्ग को संशोधित करना जारी रखते हैं:


public List<String> someMethod(List<String> list, String s) {
    // Very useful and important method
    return null;
}

पहला वाला हमें अपने तरीकों के पैरामीटर प्राप्त करने देगा, और दूसरा हमें पैरामीटरयुक्त प्रकार भी देगा।


static void getParameterTypes(Method[] methods) {
    Class<?>[] types = method.getParameterTypes();
        for (Class<?> type : types) {
            System.out.println(type);
        }
}

static void getGenericParameterTypes(Method[] methods) {
   Type[] types = method.getGenericParameterTypes();
        for (Type type : types) {
            System.out.println(type);
        }
}

हम अपने तरीकों में से केवल एक का उपयोग करेंगे। किसी विशिष्ट नाम से किसी विधि तक पहुँचने के लिए, हम getMethod को कॉल करते हैं और उस विधि के नाम और मापदंडों को पास करते हैं जो हम चाहते हैं:


public static void main(String[] args) throws NoSuchMethodException {
    Method currentMethod = Person.class.getMethod("someMethod", List.class, String.class);

    getParameterTypes(currentMethod);
    System.out.println();
    getGenericParameterTypes(currentMethod);
}

हमारे कोड को चलाना, हम देखेंगे कि तरीके कैसे भिन्न होते हैं और वे क्या लौटाते हैं:

इंटरफ़ेस java.util.List
वर्ग java.lang.String

java.util.List<java.lang.String>
वर्ग java.lang.String

getExceptionTypes() और getGenericExceptionTypes() विधियाँ

हम इन विधियों का उपयोग उन अपवादों की एक सरणी प्राप्त करने के लिए कर सकते हैं जिन्हें हमारी विधि फेंक सकती है, साथ ही पैरामीटर प्रकार के अपवाद (यदि कोई हो)। आइए एक नए उदाहरण का उपयोग करें जिसमें एक छिपी हुई स्थिर कक्षा है:


private static class Processor {
    private void init() {}

    private void process() throws IOException {}
}

और हम अपने प्रोसेसर वर्ग पर विधियों को कॉल करेंगे:


public static void main(String... args) throws NoSuchMethodException {
    Method method = Processor.class.getDeclaredMethod("process");
    Type[] type = method.getExceptionTypes();
    System.out.println(Arrays.toString(type));
}

अब हम अपना अपवाद देख सकते हैं:

[वर्ग java.io.IOException]

अब चलिए प्रकार को पैरामीटर करते हैं। हम अपनी मुख्य कक्षा को संशोधित करेंगे:


private static class Processor<E extends IOException> {

    private void process() throws E {
    }
}

और मुख्य विधि का कोड :


public static void main(String... args) throws NoSuchMethodException {
    Method m = Processor.class.getDeclaredMethod("process");
    Type[] t = m.getGenericExceptionTypes();
    System.out.println(Arrays.toString(t));

    for (Type type : t) {
        if (type instanceof TypeVariable) {
            for (Type type1 : ((TypeVariable) type).getBounds()) {
                System.out.println(type1);
            }
        }
    }
}

इस पद्धति के अंदर, हमें एक TypeVariables ऑब्जेक्ट मिला , जो कि टाइप वेरिएबल्स के लिए एक सामान्य पैरेंट इंटरफ़ेस है। और उसके अंदर, अब हम आंतरिक पैरामीटर प्राप्त कर सकते हैं, अर्थात् हमारा नेस्टेड अपवाद:

[ई]
वर्ग java.io.IOException

getAnnotations() और getDeclaredAnnotations() तरीके

आइए इस नए वर्ग का उपयोग जारी रखें और इसमें कुछ एनोटेशन जोड़ें। हम अपना खुद का एनोटेशन एनोटेशन बनाएंगे :


@Retention(RetentionPolicy.RUNTIME)
@interface Annotation {

    public String key();
    public String value();
}

और इसे हमारे तरीके पर लागू करें:


@Annotation(key = "key", value = "value")
private void process() throws E{

}

और निश्चित रूप से हम अपने सभी एनोटेशन प्रदर्शित करने के लिए एक विधि जोड़ेंगे:


static void getMethodAnnotations(Class<?> clazz) {
    Method[] methods = clazz.getDeclaredMethods();
    for (Method method : methods) {
        System.out.println(method.getName());
        System.out.println(Arrays.toString(method.getAnnotations()));
        System.out.println();
    }
}

हमारी मुख्य विधि का कार्यान्वयन:


public static void main(String... args) {
    Class clazz = Processor.class;
    getMethodAnnotations(clazz);
}

परिणामी स्क्रीन आउटपुट है:

प्रक्रिया
[@com.company.Main&Annotation(key="key", value="value")]

इस तरह से हम उन एनोटेशन को प्राप्त कर सकते हैं जो हमारे तरीकों पर लागू किए गए हैं, और getAnnotations मेथड हमें क्लास के पैरेंट एनोटेशन तक भी पहुंचने देता है।

आज हम इस बात से परिचित हुए कि कैसे प्रतिबिंब तरीकों और क्षेत्रों के साथ काम कर सकता है, और हम इसके साथ क्या डेटा प्राप्त कर सकते हैं!