Java Εκμάθηση Reflection API με παράδειγμα

⚡ Έξυπνη Σύνοψη

Java Το Reflection API αναλύει και τροποποιεί τις δυνατότητες μιας κλάσης κατά τον χρόνο εκτέλεσης, συμπεριλαμβανομένων των πεδίων, των μεθόδων και των κατασκευαστών της. Αυτός ο πόρος εξηγεί το πακέτο java.lang.reflect, τις βασικές μεθόδους του java.lang.Class και τέσσερα παραδείγματα που διαβάζουν τα μεταδεδομένα μιας κλάσης, μιας μεταβλητής, μιας μεθόδου και ενός κατασκευαστή.

  • 🔍 Ορισμός: Το Reflection επιθεωρεί και αλλάζει κλάσεις και τα μέλη τους κατά τον χρόνο εκτέλεσης, ακόμη και ιδιωτικές.
  • 📦 Πακέτο Reflect: Οι κλάσεις Field, Method, Constructor και Modifier συλλέγουν δηλωτικές πληροφορίες σχετικά με τα μέλη.
  • 🏷️ Μέθοδοι Κλάσης: Οι getName(), getSuperclass(), getInterfaces() και getModifiers() επιστρέφουν μεταδεδομένα βασικής κλάσης.
  • 🧪 Παραδείγματα εργασίας: Τέσσερα προγράμματα extracμεταδεδομένα μιας κλάσης, μεταβλητές, μέθοδοι και κατασκευαστές.
  • ⚠️ Προσοχή: Η αντανάκλαση μπορεί να έχει πρόσβαση σε ιδιωτικά μέλη και είναι πιο αργή, επομένως χρησιμοποιήστε την ως έσχατη λύση.

Java Εκμάθηση API Αντανάκλασης

Τι είναι το Reflection σε Java?

Java Η αναστοχασμός είναι η διαδικασία ανάλυσης και τροποποίησης όλων των δυνατοτήτων μιας κλάσης κατά τον χρόνο εκτέλεσης. Το API αναστοχασμού στο Java Χρησιμοποιείται για τον χειρισμό μιας κλάσης και των μελών της, τα οποία περιλαμβάνουν πεδία, μεθόδους, κατασκευαστές κ.λπ., κατά τον χρόνο εκτέλεσης.

Ένα πλεονέκτημα του Reflection API στο Java είναι ότι μπορεί να χειραγωγήσει και τα ιδιωτικά μέλη της κλάσης.

Το πακέτο java.lang.reflect παρέχει πολλές κλάσεις για την υλοποίηση της αντανάκλασης. Οι μέθοδοι της κλάσης java.lang.Class χρησιμοποιούνται για τη συλλογή των πλήρων μεταδεδομένων μιας συγκεκριμένης κλάσης.

Κατηγορία στο java.lang.reflect Package

Ακολουθεί μια λίστα με διάφορα Java τάξεις στο πακέτο java.lang.reflect για την υλοποίηση της αντανάκλασης:

  • Πεδίο: Αυτή η κλάση χρησιμοποιείται για τη συλλογή δηλωτικών πληροφοριών όπως ο τύπος δεδομένων, ο τροποποιητής πρόσβασης, το όνομα και η τιμή μιας μεταβλητής.
  • Μέθοδος: Αυτή η κλάση χρησιμοποιείται για τη συλλογή δηλωτικών πληροφοριών όπως ο τροποποιητής πρόσβασης, ο τύπος επιστροφής, το όνομα, οι τύποι παραμέτρων και ο τύπος εξαίρεσης μιας μεθόδου.
  • Κατασκευαστής: Αυτή η κλάση χρησιμοποιείται για τη συλλογή δηλωτικών πληροφοριών, όπως ο τροποποιητής πρόσβασης, το όνομα και οι τύποι παραμέτρων ενός κατασκευαστή.
  • Επεξεργασία: Αυτή η κλάση χρησιμοποιείται για τη συλλογή πληροφοριών σχετικά με έναν συγκεκριμένο τροποποιητή πρόσβασης.

Μέθοδοι που χρησιμοποιούνται στο java.lang.Class

  • δημόσια συμβολοσειρά getName(): Επιστρέφει το όνομα της κλάσης.
  • δημόσια κλάση getSuperclass(): Επιστρέφει την αναφορά υπερκλάσης.
  • δημόσια κλάση[] getInterfaces(): Επιστρέφει έναν πίνακα διεπαφών που υλοποιούνται από την καθορισμένη κλάση.
  • public int getModifiers(): Επιστρέφει μια ακέραια τιμή που αντιπροσωπεύει τους τροποποιητές της καθορισμένης κλάσης, η οποία πρέπει να διαβιβαστεί ως παράμετρος στη μέθοδο "public static String toString(int i)" που επιστρέφει τον προσδιοριστή πρόσβασης για τη δεδομένη κλάση.

Πώς να λάβετε πλήρεις πληροφορίες για μια τάξη

Για να λάβετε πληροφορίες για μεταβλητές, μεθόδους και κατασκευαστές μιας κλάσης, πρέπει να δημιουργήσουμε ένα αντικείμενο της κλάσης. Το ακόλουθο παράδειγμα δείχνει διαφορετικούς τρόπους για να δημιουργήσετε ένα αντικείμενο της κλάσης "Κλάση":

Μέθοδοι που χρησιμοποιούνται στο java.lang.Class

public class Guru99ClassObjectCreation {
    public static void main(String[] args) throws ClassNotFoundException {
        // 1 - By using Class.forName() method
        Class c1 = Class.forName("Guru99ClassObjectCreation");
        // 2 - By using getClass() method
        Guru99ClassObjectCreation guru99Obj = new Guru99ClassObjectCreation();
        Class c2 = guru99Obj.getClass();
        // 3 - By using .class
        Class c3 = Guru99ClassObjectCreation.class;
    }
}

Παράδειγμα 1: Πώς να λάβετε μεταδεδομένα κλάσης

Το ακόλουθο παράδειγμα δείχνει πώς να λάβετε μεταδεδομένα όπως το όνομα της κλάσης, το όνομα της υπερκλάσης, τις υλοποιημένες διεπαφές και τους τροποποιητές πρόσβασης μιας κλάσης.

Θα λάβουμε τα μεταδεδομένα της παρακάτω κλάσης με το όνομα Guru99Base.class:

Λάβετε μεταδεδομένα της τάξης

import java.io.Serializable;
public abstract class Guru99Base implements Serializable, Cloneable {
}
  1. Το όνομα της κλάσης είναι: Guru99 Βάση
  2. Οι τροποποιητές πρόσβασης είναι: public και abstract
  3. Έχει υλοποιήσει διεπαφές: Serializable και Cloneable
  4. Δεδομένου ότι δεν έχει επεκτείνει καμία κλάση ρητά, η υπερκλάση του είναι: java.lang.Object

Η παρακάτω κλάση θα λάβει τα μεταδεδομένα του Guru99Base.class και εκτυπώστε το:

Λάβετε μεταδεδομένα της τάξης

import java.lang.reflect.Modifier;
public class Guru99GetclassMetaData {
    public static void main(String[] args) throws ClassNotFoundException {
        // Create Class object for Guru99Base.class
        Class<Guru99Base> guru99ClassObj = Guru99Base.class;

        // Print name of the class
        System.out.println("Name of the class is : " + guru99ClassObj.getName());

        // Print super class name
        System.out.println("Name of the super class is : " + guru99ClassObj.getSuperclass().getName());

        // Get the list of implemented interfaces using getInterfaces() method
        Class[] guru99InterfaceList = guru99ClassObj.getInterfaces();

        // Print the implemented interfaces using a for-each loop
        System.out.print("Implemented interfaces are : ");
        for (Class guru99class1 : guru99InterfaceList) {
            System.out.print(guru99class1.getName() + " ");
        }
        System.out.println();

        // Get access modifiers using getModifiers() and Modifier.toString()
        int guru99AccessModifier = guru99ClassObj.getModifiers();
        System.out.println("Access modifiers of the class are : " + Modifier.toString(guru99AccessModifier));
    }
}
  1. Εκτυπώστε το όνομα της κλάσης χρησιμοποιώντας τη μέθοδο getName().
  2. Εκτυπώστε το όνομα της υπερκλάσης χρησιμοποιώντας τη μέθοδο getSuperclass().getName().
  3. Εκτυπώστε τα ονόματα των υλοποιημένων διεπαφών.
  4. Εκτυπώστε τους τροποποιητές πρόσβασης που χρησιμοποιούνται από την κλάση.

Λάβετε μεταδεδομένα της τάξης

Λάβετε μεταδεδομένα της τάξης

Παράδειγμα 2: Πώς να λάβετε μεταδεδομένα μεταβλητής

Το ακόλουθο παράδειγμα δείχνει πώς να λάβετε τα μεταδεδομένα μιας μεταβλητής.

Εδώ, δημιουργούμε μια κλάση με το όνομα Guru99VariableMetaData.class με ορισμένες μεταβλητές:

package guru;
public class Guru99VariableMetaData {
    public static int guru99IntVar1 = 1111;
    static int guru99IntVar2 = 2222;
    static String guru99StringVar1 = "guru99.com";
    static String guru99StringVar2 = "Learning Reflection API";
}

Βήματα για να λάβετε τα μεταδεδομένα σχετικά με τις μεταβλητές στην παραπάνω κλάση:

  1. Δημιουργήστε το αντικείμενο κλάσης της παραπάνω κλάσης, δηλαδή, Guru99VariableMetaData.class, όπως παρακάτω:
    Guru99VariableMetaData guru99ClassVar = new Guru99VariableMetaData();
    Class guru99ClassObjVar = guru99ClassVar.getClass();
  2. Λάβετε τα μεταδεδομένα με τη μορφή ενός πίνακα Field χρησιμοποιώντας το getFields() or getDeclaredFields() μεθόδους όπως παρακάτω:
    Field[] guru99Field1 = guru99ClassObjVar.getFields();
    Field[] guru99Field2 = guru99ClassObjVar.getDeclaredFields();

The getFields() Η μέθοδος επιστρέφει τα μεταδεδομένα των δημοσίων μεταβλητών από την καθορισμένη κλάση καθώς και από την υπερκλάση της.

The getDeclaredFields() Η μέθοδος επιστρέφει τα μεταδεδομένα όλων των μεταβλητών μόνο από την καθορισμένη κλάση.

  1. Λάβετε το όνομα των μεταβλητών χρησιμοποιώντας τη μέθοδο "public String getName()".
  2. Λάβετε τον τύπο δεδομένων των μεταβλητών χρησιμοποιώντας τη μέθοδο "public Class getType()".
  3. Λάβετε την τιμή της μεταβλητής χρησιμοποιώντας τη μέθοδο "public xxx get(Field)". Εδώ, το xxx θα μπορούσε να είναι ένα byte, ένα short ή οποιοσδήποτε τύπος τιμής που θέλουμε να ανακτήσουμε.
  4. Λάβετε τους τροποποιητές πρόσβασης των μεταβλητών χρησιμοποιώντας τις μεθόδους getModifiers() και Modifier.toString(int i).

Εδώ, γράφουμε μια κλάση για να λάβουμε τα μεταδεδομένα των μεταβλητών που υπάρχουν στην κλάση Guru99VariableMetaData.class:

Λήψη μεταδεδομένων της μεταβλητής

package guru;
import java.lang.reflect.Field;
import java.lang.reflect.Modifier;

public class Guru99VariableMetaDataTest {
    public static void main(String[] args) throws IllegalArgumentException, IllegalAccessException {
        // Create Class object for Guru99VariableMetaData.class
        Guru99VariableMetaData guru99ClassVar = new Guru99VariableMetaData();
        Class guru99ClassObjVar = guru99ClassVar.getClass();

        // Get the metadata of all the fields of the class
        Field[] guru99Field1 = guru99ClassObjVar.getDeclaredFields();

        // Print name, data types, access modifiers and values of the variables
        for (Field field : guru99Field1) {
            System.out.println("Variable name : " + field.getName());
            System.out.println("Datatype of the variable : " + field.getType());

            int guru99AccessModifiers = field.getModifiers();
            System.out.println("Access Modifiers of the variable : " + Modifier.toString(guru99AccessModifiers));
            System.out.println("Value of the variable : " + field.get(guru99ClassVar));
            System.out.println();
        }
    }
}
  1. Δημιουργήθηκε ένα αντικείμενο κλάσης για Guru99VariableMetaData.class.
  2. Λήφθηκαν όλα τα μεταδεδομένα των μεταβλητών σε έναν πίνακα Field.
  3. Εκτύπωσε όλα τα ονόματα μεταβλητών στην κλάση Guru99VariableMetaData.class.
  4. Εκτύπωσε όλους τους τύπους δεδομένων των μεταβλητών στην κλάση.
  5. Εκτύπωσε όλους τους τροποποιητές πρόσβασης των μεταβλητών στην κλάση.
  6. Εκτύπωσε τις τιμές όλων των μεταβλητών στην κλάση.

Λήψη μεταδεδομένων μεθόδου

Λήψη μεταδεδομένων μεθόδου

Παράδειγμα 3: Πώς να λάβετε μεταδεδομένα της μεθόδου

Το ακόλουθο παράδειγμα δείχνει πώς να λάβετε τα μεταδεδομένα μιας μεθόδου.

Εδώ, δημιουργούμε μια κλάση με το όνομα Guru99MethodMetaData.class με ορισμένες μεθόδους:

Λήψη μεταδεδομένων μεθόδου

package guru;
import java.sql.SQLException;
public class Guru99MethodMetaData {

    public void guru99Add(int firstElement, int secondElement, String result)
    throws ClassNotFoundException, ClassCastException {
        System.out.println("Demo method for Reflection API");
    }
    public String guru99Search(String searchString)
    throws ArithmeticException, InterruptedException {
        System.out.println("Demo method for Reflection API");
        return null;
    }
    public void guru99Delete(String deleteString)
    throws SQLException {
        System.out.println("Demo method for Reflection API");
    }
}

Βήματα για να λάβετε τα μεταδεδομένα σχετικά με τις μεθόδους στην παραπάνω κλάση:

  1. Δημιουργήστε το αντικείμενο κλάσης της παραπάνω κλάσης, δηλαδή, Guru99MethodMetaData.class, όπως παρακάτω:
    Guru99MethodMetaData guru99ClassVar = new Guru99MethodMetaData();
    Class guru99ClassObjVar = guru99ClassVar.getClass();
  2. Λάβετε πληροφορίες μεθόδου σε έναν πίνακα μεθόδων χρησιμοποιώντας τις μεθόδους getMethods() και getDeclaredMethods() όπως παρακάτω:
    Method[] guru99Method1 = guru99ClassObjVar.getMethods();
    Method[] guru99Method2 = guru99ClassObjVar.getDeclaredMethods();

    The getMethods() Η μέθοδος επιστρέφει τα μεταδεδομένα των δημόσιων μεθόδων από την καθορισμένη κλάση καθώς και από την υπερκλάση της. getDeclaredMethods() Η μέθοδος επιστρέφει τα μεταδεδομένα όλων των μεθόδων μόνο από την καθορισμένη κλάση.

  3. Λάβετε το όνομα της μεθόδου χρησιμοποιώντας το getName () μέθοδος.
  4. Λάβετε τον τύπο επιστροφής της μεθόδου χρησιμοποιώντας το getReturnType() μέθοδος.
  5. Αποκτήστε τροποποιητές πρόσβασης των μεθόδων χρησιμοποιώντας το getModifiers() και Τροποποιητής.toString(int i) μεθόδους.
  6. Λήψη τύπων παραμέτρων μεθόδου χρησιμοποιώντας το getParameterTypes() μέθοδος, η οποία επιστρέφει έναν πίνακα κλάσης.
  7. Λάβετε εξαιρέσεις χρησιμοποιώντας το getExceptionTypes() μέθοδος, η οποία επιστρέφει έναν πίνακα κλάσης.

Εδώ, γράφουμε μια κλάση για να λάβουμε τα μεταδεδομένα των μεθόδων που υπάρχουν στην κλάση Guru99MethodMetaData.class:

Λήψη μεταδεδομένων μεθόδου

package guru;
import java.lang.reflect.Method;
import java.lang.reflect.Modifier;

public class Guru99MethodMetaDataTest {

    public static void main(String[] args) {
        // Create Class object for Guru99MethodMetaData.class
        Class guru99ClassObj = Guru99MethodMetaData.class;

        // Get the metadata of all the methods using getDeclaredMethods()
        Method[] guru99Methods = guru99ClassObj.getDeclaredMethods();

        for (Method method : guru99Methods) {
            System.out.println("Name of the method : " + method.getName());
            System.out.println("Return type of the method : " + method.getReturnType());

            int guru99ModifierList = method.getModifiers();
            System.out.println("Method access modifiers : " + Modifier.toString(guru99ModifierList));

            Class[] guru99ParamList = method.getParameterTypes();
            System.out.print("Method parameter types : ");
            for (Class class1 : guru99ParamList) {
                System.out.print(class1.getName() + " ");
            }
            System.out.println();

            Class[] guru99ExceptionList = method.getExceptionTypes();
            System.out.print("Exception thrown by method : ");
            for (Class class1 : guru99ExceptionList) {
                System.out.print(class1.getName() + " ");
            }
            System.out.println();
        }
    }
}
  1. Δημιουργήθηκε ένα αντικείμενο κλάσης για Guru99MethodMetaData.class.
  2. Λήφθηκαν όλα τα μεταδεδομένα όλων των μεθόδων σε έναν πίνακα μεθόδων.
  3. Εκτύπωσε όλα τα ονόματα μεθόδων που υπάρχουν στην κλάση.
  4. Εκτύπωσε τους τύπους επιστροφής των μεθόδων στην κλάση.
  5. Εκτύπωσε όλους τους τροποποιητές πρόσβασης των μεθόδων στην κλάση.
  6. Εκτύπωσε τους τύπους παραμέτρων των μεθόδων.
  7. Εκτύπωσε τις εξαιρέσεις που δημιουργούνται από τις μεθόδους.

Λήψη μεταδεδομένων μεθόδου

Λήψη μεταδεδομένων μεθόδου

Παράδειγμα 4: Πώς να λάβετε μεταδεδομένα από κατασκευαστές

Το ακόλουθο παράδειγμα δείχνει πώς να λάβετε τα μεταδεδομένα των κατασκευαστών.

Εδώ, δημιουργούμε μια κλάση με το όνομα Guru99Constructor.class με διαφορετικούς κατασκευαστές:

Λάβετε Μεταδεδομένα Κατασκευαστών

package guru;

import java.rmi.RemoteException;
import java.sql.SQLException;

public class Guru99Constructor {

    public Guru99Constructor(int no) throws ClassCastException, ArithmeticException { }
    public Guru99Constructor(int no, String name) throws RemoteException, SQLException { }
    public Guru99Constructor(int no, String name, String address) throws InterruptedException { }
}

Εδώ, γράφουμε μια κλάση για να λάβουμε τα μεταδεδομένα των κατασκευαστών που υπάρχουν στην κλάση Guru99Κατασκευαστής.κλάση:

Λάβετε Μεταδεδομένα Κατασκευαστών

package guru;
import java.lang.reflect.Constructor;
import java.lang.reflect.Modifier;
public class Guru99ConstructorMetaDataTest {

    public static void main(String[] args) {
        // Create Class object for Guru99Constructor.class
        Class guru99Class = Guru99Constructor.class;

        // Get all the constructor information in the Constructor array
        Constructor[] guru99ConstructorList = guru99Class.getConstructors();

        for (Constructor constructor : guru99ConstructorList) {
            System.out.println("Constructor name : " + constructor.getName());

            int guru99Modifiers = constructor.getModifiers();
            System.out.println("Constructor modifier : " + Modifier.toString(guru99Modifiers));

            Class[] guru99ParamList = constructor.getParameterTypes();
            System.out.print("Constructor parameter types : ");
            for (Class class1 : guru99ParamList) {
                System.out.print(class1.getName() + " ");
            }
            System.out.println();

            Class[] guru99ExceptionList = constructor.getExceptionTypes();
            System.out.print("Exception thrown by constructors : ");
            for (Class class1 : guru99ExceptionList) {
                System.out.print(class1.getName() + " ");
            }
            System.out.println();
        }
    }
}
  1. Δημιουργήθηκε ένα αντικείμενο κλάσης για Guru99Κατασκευαστής.κλάση.
  2. Λήφθηκαν όλα τα μεταδεδομένα όλων των κατασκευαστών σε έναν πίνακα Constructor.
  3. Εκτύπωσα όλα τα ονόματα των κατασκευαστών που υπάρχουν στην κλάση.
  4. Εκτύπωσε όλους τους τροποποιητές πρόσβασης των κατασκευαστών στην κλάση.
  5. Εκτύπωσε τους τύπους παραμέτρων των κατασκευαστών.
  6. Εκτύπωσε τις εξαιρέσεις που δημιουργήθηκαν από τους κατασκευαστές.

Λάβετε Μεταδεδομένα Κατασκευαστών

Λάβετε Μεταδεδομένα Κατασκευαστών

Συχνές Ερωτήσεις

Η αναστοχασμός επιτρέπει στα πλαίσια και τα εργαλεία τεχνητής νοημοσύνης να επιθεωρούν και να δημιουργούν κλάσεις κατά τον χρόνο εκτέλεσης. Υποστηρίζει την έγχυση εξαρτήσεων, τη σειριοποίηση και τον χάρτη ORM.pingκαι δυναμική φόρτωση πρόσθετων (plugins) χωρίς να γνωρίζουμε τις ακριβείς κλάσεις κατά τον χρόνο μεταγλώττισης.

Η τεχνητή νοημοσύνη μπορεί να δημιουργήσει γρήγορα έναν κώδικα αντανάκλασης, αλλά θα πρέπει να τον εξετάσετε προσεκτικά. Η αντανάκλαση μπορεί να παρακάμψει τους ελέγχους πρόσβασης και να εισαγάγει κινδύνους ασφάλειας και απόδοσης, επομένως ο παραγόμενος κώδικας χρειάζεται δοκιμή και επικύρωση.

Η ανακλαστικότητα είναι πιο αργή από τις άμεσες κλήσεις μεθόδων, μπορεί να διακόψει την ενθυλάκωση αποκτώντας πρόσβαση σε ιδιωτικά μέλη και μπορεί να προκαλέσει προβλήματα ασφάλειας και συντήρησης. Θα πρέπει να χρησιμοποιείται μόνο όταν δεν υπάρχει διαθέσιμη απλούστερη προσέγγιση.

Ναι. Χρησιμοποιώντας την setAccessible(true), η αντανάκλαση μπορεί να διαβάσει και να τροποποιήσει ιδιωτικά πεδία και να καλέσει ιδιωτικές μεθόδους. Αυτό είναι ισχυρό για δοκιμές και πλαίσια, αλλά μπορεί να διακόψει την ενθυλάκωση και να δημιουργήσει προβλήματα ασφαλείας.

Συνοψίστε αυτήν την ανάρτηση με: