Java:什么场景需要使用反射?

发布于 2025-01-04 22:54:39 字数 153 浏览 0 评论 0原文

因此,通过阅读一些文章,我从中得到的信息是能够实时修改字段并向类设置值,而无需重新编译。

那么是否可以对第三方java库创建的没有可用源代码的类执行此操作/是否可以使用反射在运行时修改类实例?

反射还常用在哪些场景中?

我试图了解反射如何适用。

So from reading some of the articles, the message i got out of it was being able to modify fields and set values to classes in real time without recompiling.

so is it possible to do this to 3rd party java library created classes which no source code is available / is it possible to use reflection to modify class instances on run time?

in what other scenarios is reflection commonly used?

I am trying to understand how reflection can be applicable.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(6

一城柳絮吹成雪 2025-01-11 22:54:39

每当您在运行时处理字符串并希望将该字符串的一部分视为该语言中的标识符时。

  1. 远程过程调用——将通过网络接收到的消息的一部分视为方法名称。
  2. 序列化和反序列化——将字段名称转换为字符串,以便您可以将对象的字段写入流,然后将其转换回对象。
  3. 对象关系映射——维护对象中的字段与数据库中的列之间的关系。
  4. 与动态类型脚本语言的接口——将脚本语言生成的字符串值转换为对对象上的字段或方法的引用。

它还可用于允许在语言中模拟语言功能。
考虑命令行 java com.example.MyClass 将字符串转换为类名。这不需要反射,因为 java 可执行文件可以将 .class 文件转换为代码,但如果没有反射,它就无法编写 java com. example.Wrapper com.example.MyClass 其中 Wrapper 委托给其参数,如下所示:

class Wrapper {
  public static void main(String... argv) throws Exception {
    // Do some initialization or other work.
    Class<?> delegate = Class.forName(argv[0]);
    Method main = delegate.getMethod("main", String[].class);
    main.apply(null, Arrays.asList(argv).subList(1, argv.length).toArray(argv));
  }
}

Any time you're dealing with a string at runtime and want to treat part of that string as an identifier in the language.

  1. Remote procedure calling -- treat part of a message received over the network as a method name.
  2. Serialization and deserialization -- convert field names to string so you can write the object's fields to a stream and later convert it back into an object.
  3. Object-relational mappings -- maintain a relationship between fields in an object and columns in a database.
  4. Interfaces with dynamically typed scripting languages -- turn a string value produced by a scripting language into a reference to a field or method on an object.

It can also be used to allow language features to be emulated in the language.
Consider the command line java com.example.MyClass which turns a string into a class name. This doesn't require reflection, because the java executable can turn a .class file into code, but without reflection it would not be able to write java com.example.Wrapper com.example.MyClass where Wrapper delegates to its argument as in:

class Wrapper {
  public static void main(String... argv) throws Exception {
    // Do some initialization or other work.
    Class<?> delegate = Class.forName(argv[0]);
    Method main = delegate.getMethod("main", String[].class);
    main.apply(null, Arrays.asList(argv).subList(1, argv.length).toArray(argv));
  }
}
染柒℉ 2025-01-11 22:54:39

另一种情况是开发 IDE,如 eclipse/netbeans 等,以确定抽象类中的哪些方法需要由子类实现,并自动为您编写缺少的方法调用(一个示例)。

One other case developing IDEs like eclipse/netbeans etc., to determine which methods in an abstract class need to be implemented by a child class, and automatically write the missing method calls for you (one example).

绳情 2025-01-11 22:54:39

Guice 或 Spring 等注入框架使用反射来帮助您在运行时构建对象的实例。

Injection frameworks like Guice or Spring use reflection to help you build instances of objects at runtime.

献世佛 2025-01-11 22:54:39

在需要配置将事物串在一起的情况下,反射也很有用。例如,在我编写的应用程序中,我有一个 @Report("debits") 注释,它只是添加到生成报告的方法中。然后,在 XML 配置中,用户可以简单地添加:

<requiredReports="debits,blah,another"/>

这可以最大限度地减少将 XML 代码映射到实际方法的样板代码,因为反射可以发现报告方法并使其直接可用。

Reflection is also useful in cases where configuration is required to string things together. For example, in an application I wrote I have a @Report("debits") annotation that is simply added to methods that generate reports. Then, in the XML configuration a user can simply add:

<requiredReports="debits,blah,another"/>

This minimizes boiler plate code from mapping the XML code to the actual method, since reflection can discover the report methods and make it available directly.

岁月静好 2025-01-11 22:54:39

我被要求为以下语句创建一个解决方案。

“1)差异服务:
• 可以计算两个对象之间的差异并返回结果
“差异”
• 可以对原始对象应用先前创建的“差异”,以便
返回的对象与用于计算的修改后的对象相匹配
差异。 “

如果不使用反射,这将非常困难。使用反射,我可以列出所有未知对象的类元素、属性和方法。我可以使用它们来获取对象中包含的值。我可以比较原始对象值和修改后的对象值,创建反映两个对象之间变化的“diff”对象,

然后我可以读取“diff”对象中的指令并将其应用到原始对象上,Java 反射为我提供了更改未知属性值所需的工具。我可以调用原始对象的 setter 方法和如果原始属性为 null,则在需要时实例化类型以在原始对象上设置修改后的值。

“diff”应用程序适用于同一类型的任何两个对象,但它们可以是任何类型,两个对象都必须是同一类型。反射

非常强大,允许我们创建真正的通用多态方法、函数、库和系统,其中传递的对象类型不需要在编译时知道。这适用于同时使用 Java 反射和泛型(这是一个非常强大的组合)。

最后,我还使用 Java Reflection 创建了一个通用排序函数,它可以使用该类的任何属性作为排序键对任何类类型的任何列表进行排序。只要调用方法传递列表和属性要使用的名称,该方法将返回一个排序列表。

I was asked to create a solution for the below statement.

"1) A diff service that:
• can calculate the differences between two objects and return the resulting
"diff"
• can apply a previously created "diff" against an original object, so that
the returned object matches the modified object that was used to calculate
the diff. "

This would have been very difficult without using reflection. Using reflection I could list all the unknown object's Class elements, properties and methods. I could use these to get the values contained in the object. I could compare the original and modified objects values, create "diff" object reflecting changes between the two objects.

Using Java reflection I could then read the instructions in the "diff" object and apply these to the original object. Java reflection gave me the tools needed to change the values on the unknown properties of the original object. I could invoke setter methods and instantiate types where needed if the original property was null to set the modified value on the original object.

The "diff" app works on any two objects of the same type, but they could be any type, both objects just have to be of the same type.

Reflection is very powerful and allow us to create true generic polymorphic methods, functions, libraries and system, where the passed object type does not need to be known at compile time. This applies when using Java Reflection and Generics together, a very powerful combination.

To end of, I have also used Java Reflection to create a generic sort function, that could sort any list of any Class Type, using any property of the Class as the sort key.As long as the calling method passed the list and the property name to use, the method would return a sorted list.

樱花细雨 2025-01-11 22:54:39

以下是使用反射的一些情况 在

public class Main {

    public static void main(String[] args) {

        displayProperties(Stage.class);
    }

    public static void displayProperties(Class class) {
        boolean hasParam = false;
        boolean hasReturn = false;
        ArrayList<Method> propMethods = new ArrayList<>();
        Method[] methods = clazz.getMethods();
        for (Method m: methods) {

            Parameter[] paraType = m.getParameters();
            if(m.getParameterCount()<2) {
                if ((m.getReturnType() == void.class && paraType.length == 1) || (m.getReturnType() != void.class && paraType.length == 0)) {
                    //Get the properties alone
                    propMethods.add(m);
                }
            }

        }
        for (int i = 0; i < propMethods.size(); i++) {

            if (propMethods.get(i).getName().startsWith("get") || propMethods.get(i).getName().startsWith("set")) {

                System.out.println(readWrite(propMethods.get(i), propMethods) + " " + propMethods.get(i).getName().substring(3)+"( "+propMethods.get(i).getReturnType().getTypeName()+" )");
            } else
                System.out.println(readWrite(propMethods.get(i), propMethods) + " " + propMethods.get(i).getName() + "( "+propMethods.get(i).getReturnType().getTypeName()+" )");
        }

    }

    public static String readWrite(Method method, ArrayList<Method> propMeths) {

        ArrayList<Method> temp;
        temp = propMeths;

        boolean readIn = false;
        boolean writeIn = false;
        String onlyName = method.getName().substring(3);

        for (int i = 0; i < temp.size(); i++) {
            //use the substring--

            if (temp.get(i).getName().startsWith("get") && temp.get(i).getName().endsWith(onlyName)) {
                readIn = true;
            }
            if (temp.get(i).getName().startsWith("set") && temp.get(i).getName().endsWith(onlyName)) {

                writeIn = true;
            }
        }

        if (readIn == true && writeIn == true)
            return "rw ";
        else if (readIn == true && writeIn == false)
            return "r ";
        else
            return "w ";
    }
}

String 类的另一种情况

public static void main(String[] args) 
    {
        displayProperties(String.class);
    }

    public static void displayProperties(Class class){
        clazz.getDeclaredFields();

        Method[] methods = clazz.getDeclaredMethods();

        for(int ii = 0; ii<methods.length; ii++){
            System.out.println("Method Name: "+methods[ii].getName());
            System.out.println("Method Type: "+methods[ii].getReturnType());
            System.out.println("Method Pa: "+methods[ii].getParameterCount());
            System.out.println("Method Type: "+methods[ii].getReturnType());

        }
    }

下 使用反射从 XML 加载

public static Object loadFromXml(String filePath) throws Exception {

        DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
        DocumentBuilder builder = factory.newDocumentBuilder();
        File newFile = new File(filePath);
        Document doc = builder.parse(newFile);
        Node root = doc.getFirstChild();

        return loadObjectElement(root);


    }
    /**
     * This method loads from an xml file and returns all the contents of the file as an object
     * @param root The node passed in to the method from which the "tree" gets a new level
     * @return all the contents of the xml file as an object
     * @throws Exception
     */
    public static Object loadObjectElement(Node root) throws Exception {
        //loads the root
        String studentClass = root.getAttributes().getNamedItem("class").getTextContent();
        Object newStudentObject = Class.forName(studentClass).newInstance();
        //gets the children nodes (may have text elements like \n)
        NodeList studentFieldList = root.getChildNodes();

        //iterates through the children nodes
        for (int i = 0; i < studentFieldList.getLength(); i++) {
            //checks to make sure the child node is not a text node
            if (studentFieldList.item(i).getNodeType() != Node.TEXT_NODE) {
                //checks if the current node does not have children
                if (studentFieldList.item(i).getChildNodes().getLength() == 0) {
                    //receives data of the current node
                    String nameField = studentFieldList.item(i).getAttributes().getNamedItem("name").getTextContent();
                    String valueField = studentFieldList.item(i).getAttributes().getNamedItem("value").getTextContent();
                    Field declaredFieldInClass = newStudentObject.getClass().getDeclaredField(nameField);

                    //makes the field accessible
                    declaredFieldInClass.setAccessible(true);
                    //checks the field type
                    switch (declaredFieldInClass.getType().getSimpleName().toLowerCase()) {
                        case "integer":
                        case "int":
                            declaredFieldInClass.set(newStudentObject, Integer.valueOf(valueField));
                            break;
                        case "float":
                            declaredFieldInClass.set(newStudentObject, Float.valueOf(valueField));
                            break;
                        case "boolean":
                            declaredFieldInClass.set(newStudentObject, Boolean.valueOf(valueField));
                            break;
                        default:
                            declaredFieldInClass.set(newStudentObject, valueField);
                    }
                    declaredFieldInClass.setAccessible(false);
                } else {
                    //there are children in the current node
                    NodeList modulesObjectList = studentFieldList.item(i).getChildNodes();
                    String nameField = studentFieldList.item(i).getAttributes().getNamedItem("name").getTextContent();
                    Field declaredFieldInClass = newStudentObject.getClass().getDeclaredField(nameField);
                    List<Object> modules = new ArrayList<>();
                    //adds the modules into the array
                    for (int j = 0; j < modulesObjectList.getLength(); j++) {
                        if (modulesObjectList.item(j).getNodeType() != Node.TEXT_NODE) {
                            //recursively calls the the loadObjectElement method for any sub lists
                            modules.add(loadObjectElement(modulesObjectList.item(j)));
                        }
                    }
                    //sets the modules of the specific student that the method is working with
                    declaredFieldInClass.set(newStudentObject, modules);
                }
            }
        }
        return newStudentObject;
    }

Here are some cases to use reflection in

public class Main {

    public static void main(String[] args) {

        displayProperties(Stage.class);
    }

    public static void displayProperties(Class class) {
        boolean hasParam = false;
        boolean hasReturn = false;
        ArrayList<Method> propMethods = new ArrayList<>();
        Method[] methods = clazz.getMethods();
        for (Method m: methods) {

            Parameter[] paraType = m.getParameters();
            if(m.getParameterCount()<2) {
                if ((m.getReturnType() == void.class && paraType.length == 1) || (m.getReturnType() != void.class && paraType.length == 0)) {
                    //Get the properties alone
                    propMethods.add(m);
                }
            }

        }
        for (int i = 0; i < propMethods.size(); i++) {

            if (propMethods.get(i).getName().startsWith("get") || propMethods.get(i).getName().startsWith("set")) {

                System.out.println(readWrite(propMethods.get(i), propMethods) + " " + propMethods.get(i).getName().substring(3)+"( "+propMethods.get(i).getReturnType().getTypeName()+" )");
            } else
                System.out.println(readWrite(propMethods.get(i), propMethods) + " " + propMethods.get(i).getName() + "( "+propMethods.get(i).getReturnType().getTypeName()+" )");
        }

    }

    public static String readWrite(Method method, ArrayList<Method> propMeths) {

        ArrayList<Method> temp;
        temp = propMeths;

        boolean readIn = false;
        boolean writeIn = false;
        String onlyName = method.getName().substring(3);

        for (int i = 0; i < temp.size(); i++) {
            //use the substring--

            if (temp.get(i).getName().startsWith("get") && temp.get(i).getName().endsWith(onlyName)) {
                readIn = true;
            }
            if (temp.get(i).getName().startsWith("set") && temp.get(i).getName().endsWith(onlyName)) {

                writeIn = true;
            }
        }

        if (readIn == true && writeIn == true)
            return "rw ";
        else if (readIn == true && writeIn == false)
            return "r ";
        else
            return "w ";
    }
}

Another case with the String class

public static void main(String[] args) 
    {
        displayProperties(String.class);
    }

    public static void displayProperties(Class class){
        clazz.getDeclaredFields();

        Method[] methods = clazz.getDeclaredMethods();

        for(int ii = 0; ii<methods.length; ii++){
            System.out.println("Method Name: "+methods[ii].getName());
            System.out.println("Method Type: "+methods[ii].getReturnType());
            System.out.println("Method Pa: "+methods[ii].getParameterCount());
            System.out.println("Method Type: "+methods[ii].getReturnType());

        }
    }

Loading from XML with reflection

public static Object loadFromXml(String filePath) throws Exception {

        DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
        DocumentBuilder builder = factory.newDocumentBuilder();
        File newFile = new File(filePath);
        Document doc = builder.parse(newFile);
        Node root = doc.getFirstChild();

        return loadObjectElement(root);


    }
    /**
     * This method loads from an xml file and returns all the contents of the file as an object
     * @param root The node passed in to the method from which the "tree" gets a new level
     * @return all the contents of the xml file as an object
     * @throws Exception
     */
    public static Object loadObjectElement(Node root) throws Exception {
        //loads the root
        String studentClass = root.getAttributes().getNamedItem("class").getTextContent();
        Object newStudentObject = Class.forName(studentClass).newInstance();
        //gets the children nodes (may have text elements like \n)
        NodeList studentFieldList = root.getChildNodes();

        //iterates through the children nodes
        for (int i = 0; i < studentFieldList.getLength(); i++) {
            //checks to make sure the child node is not a text node
            if (studentFieldList.item(i).getNodeType() != Node.TEXT_NODE) {
                //checks if the current node does not have children
                if (studentFieldList.item(i).getChildNodes().getLength() == 0) {
                    //receives data of the current node
                    String nameField = studentFieldList.item(i).getAttributes().getNamedItem("name").getTextContent();
                    String valueField = studentFieldList.item(i).getAttributes().getNamedItem("value").getTextContent();
                    Field declaredFieldInClass = newStudentObject.getClass().getDeclaredField(nameField);

                    //makes the field accessible
                    declaredFieldInClass.setAccessible(true);
                    //checks the field type
                    switch (declaredFieldInClass.getType().getSimpleName().toLowerCase()) {
                        case "integer":
                        case "int":
                            declaredFieldInClass.set(newStudentObject, Integer.valueOf(valueField));
                            break;
                        case "float":
                            declaredFieldInClass.set(newStudentObject, Float.valueOf(valueField));
                            break;
                        case "boolean":
                            declaredFieldInClass.set(newStudentObject, Boolean.valueOf(valueField));
                            break;
                        default:
                            declaredFieldInClass.set(newStudentObject, valueField);
                    }
                    declaredFieldInClass.setAccessible(false);
                } else {
                    //there are children in the current node
                    NodeList modulesObjectList = studentFieldList.item(i).getChildNodes();
                    String nameField = studentFieldList.item(i).getAttributes().getNamedItem("name").getTextContent();
                    Field declaredFieldInClass = newStudentObject.getClass().getDeclaredField(nameField);
                    List<Object> modules = new ArrayList<>();
                    //adds the modules into the array
                    for (int j = 0; j < modulesObjectList.getLength(); j++) {
                        if (modulesObjectList.item(j).getNodeType() != Node.TEXT_NODE) {
                            //recursively calls the the loadObjectElement method for any sub lists
                            modules.add(loadObjectElement(modulesObjectList.item(j)));
                        }
                    }
                    //sets the modules of the specific student that the method is working with
                    declaredFieldInClass.set(newStudentObject, modules);
                }
            }
        }
        return newStudentObject;
    }
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文