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

时间:2012-02-10 04:18:17

标签: java reflection

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

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

在其他场景中常用的反射是什么?

我试图理解反射是如何适用的。

7 个答案:

答案 0 :(得分:12)

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

  1. 远程过程调用 - 将通过网络接收的部分消息视为方法名称。
  2. 序列化和反序列化 - 将字段名称转换为字符串,以便您可以将对象的字段写入流中,然后将其转换回对象。
  3. 对象关系映射 - 维护对象中的字段与数据库中的列之间的关系。
  4. 与动态类型脚本语言的接口 - 将脚本语言生成的字符串值转换为对象上的字段或方法的引用。
  5. 它还可用于允许在语言中模拟语言功能。 考虑将字符串转换为类名的命令行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));
      }
    }
    

答案 1 :(得分:3)

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

答案 2 :(得分:3)

当需要进入另一个classes in deeper level时,会使用

反射。因此在大多数情况下,这些实现者都具有容器行为。例如,依赖注入主要通过使用反射来完成。如果您需要一个框架作为示例,Spring会在reflection API的帮助下完成其依赖注入工作。

  

您还可以在很多区域找到幕后使用的反射。   例如,如果您使用了JAXB,那么很多编组/解组   XML将使用反射完成。经常在代码中使用注释   在幕后使用的反射。进行单元测试时,   特别是在模拟类和/或方法时,通常会有很多反思   正在使用的代码。

答案 3 :(得分:2)

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

答案 4 :(得分:0)

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

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

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

答案 5 :(得分:0)

我被要求为以下声明创建解决方案。

&#34; 1)差异服务:    •可以计算两个对象之间的差异并返回结果      &#34; DIFF&#34;    •可以应用以前创建的&#34;差异&#34;对原始对象,所以      返回的对象与用于计算的修改对象匹配      差异。 &#34;

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

使用Java反射我可以阅读&#34; diff&#34;中的指令。对象并将它们应用于原始对象。 Java反射为我提供了更改原始对象的未知属性值所需的工具。如果原始属性为null,我可以调用setter方法并在需要时实例化类型,以在原始对象上设置修改后的值。

&#34;差异&#34; app适用于任何两个相同类型的对象,但它们可以是任何类型,两个对象只需要是同一类型。

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

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

答案 6 :(得分:0)

以下是在

中使用反射的一些情况
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;
    }