Java:哪些场景需要使用反射?

Java:哪些场景需要使用反射?,java,reflection,Java,Reflection,因此,通过阅读一些文章,我从中得到的信息是能够实时修改字段并为类设置值,而无需重新编译 那么,是否有可能对没有源代码的第三方java库创建的类执行此操作/是否有可能在运行时使用反射修改类实例 反射通常在哪些其他场景中使用 我试图理解反射是如何适用的。另一个案例是开发诸如eclipse/netbeans等IDE,以确定抽象类中的哪些方法需要由子类实现,并自动为您编写缺少的方法调用(一个示例).像或Spring这样的注入框架使用反射来帮助您在运行时构建对象的实例。任何时候您在运行时处理字符串,并希望

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

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

反射通常在哪些其他场景中使用


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

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

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

任何时候您在运行时处理字符串,并希望将该字符串的一部分作为语言中的标识符

  • 远程过程调用——将通过网络接收的消息的一部分作为方法名处理
  • 序列化和反序列化——将字段名转换为字符串,以便将对象的字段写入流,然后再将其转换回对象
  • 对象关系映射——维护对象中的字段和数据库中的列之间的关系
  • 与动态类型脚本语言的接口——将脚本语言生成的字符串值转换为对对象上的字段或方法的引用
  • 它还可以用于允许在语言中模拟语言功能。 考虑命令行<代码> java com。示例。MyClass < /C> >将字符串转换为类名。这不需要反射,因为
    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));
      }
    }
    
    类包装器{
    公共静态void main(字符串…argv)引发异常{
    //执行一些初始化或其他工作。
    Class delegate=Class.forName(argv[0]);
    方法main=delegate.getMethod(“main”,字符串[].class);
    apply(null,Arrays.asList(argv).subList(1,argv.length.toArray(argv));
    }
    }
    
    反射在需要进入更深层次的其他
    类时使用。因此,在大多数情况下,这些实现者具有容器行为。例如,依赖项注入主要是通过使用反射来完成的。如果您需要一个框架作为示例,Spring将借助
    反射API
    完成其依赖项注入工作

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


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

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

    这使得将XML代码映射到实际方法的锅炉板代码最小化,因为反射可以发现报告方法并使其直接可用。

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

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

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

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

    “diff”应用程序可以在同一类型的任意两个对象上运行,但它们可以是任意类型,两个对象必须是同一类型

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


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

    下面是一些使用反射的案例

    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 ";
        }
    }
    
    公共类主{
    公共静态void main(字符串[]args){
    显示属性(Stage.class);
    }
    公共静态void显示属性(类){
    布尔hasParam=false;
    布尔hasrurn=false;
    ArrayList propMethods=新的ArrayList();
    方法[]methods=clazz.getMethods();
    用于(方法m:方法){
    参数[]paraType=m.getParameters();
    
    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());
    
            }
        }
    
    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;
        }