java怎么在运行时从字符串形式的代码创建对象?

想要在运行时动态拼接出一个类的代码,然后编译后创建对象,java动态编译可以吗,能提供一个简单的例子吗。或者用其他完全兼容java的jvm上的语言来编译然后创建对象也可以,我只搜到了用groovy的方式,但是好像不是完全兼容java语法的,我发现用java语法声明的数组,用groovy就没法编译。

  • 你可以看下这个问题的回答https://ask.csdn.net/questions/7684476
  • 这篇博客你也可以参考下:完成一个简单的Java计算器程序,控制台进行输入,打印计算结果,注意Java代码规范
  • 你还可以看下java参考手册中的 java-集合 - 关于使用和扩展Java集合框架的课程。- 聚合操作 代表你对集合进行迭代,这使你能够编写更简洁和有效的代码,处理存储在集合中的元素。 -平行主义
  • 除此之外, 这篇博客: 除 Java 外,还有哪些编程语言蹭了 JVM 的车票?中的 Groovy丨轻量级却强大 部分也许能够解决你的问题, 你可以仔细阅读以下内容或跳转源博客中阅读:
  • 在这里插入图片描述
    2003 年由 Apache 推出的轻量级动态语言,吸收了 Python、Ruby 和 Smalltalk 语言的优秀特性,语法简洁,可有效提升开发效率。与 Java 完全互融,可互调对方支持库,由ASM生成普通的java字节码文件后通过JVM执行

    class Fuck{
        static void main(String[] args){
            println "Hello,World!!!";
        }
    }
    

    官网:https://www.groovy-lang.org/


  • 您还可以看一下 汤小洋老师的手把手搭建Java旅游管理系统【附源码】(毕设)课程中的 旅游管理系统的部署运行小节, 巩固相关知识点
  • 以下回答由chatgpt基于相关博客总结生成:

    答案:

    Java支持动态编译,可以使用Java程序来实现。下面是一个简单的例子,展示如何在Java中使用动态编译来创建对象。

    import java.io.BufferedReader;
    import java.io.ByteArrayOutputStream;
    import java.io.File;
    import java.io.FileInputStream;
    import java.io.IOException;
    import java.io.InputStreamReader;
    import java.lang.reflect.InvocationTargetException;
    import java.lang.reflect.Method;
    import java.net.URI;
    import java.nio.charset.StandardCharsets;
    import java.util.ArrayList;
    import java.util.List;
    
    import javax.tools.JavaCompiler;
    import javax.tools.JavaFileObject;
    import javax.tools.SimpleJavaFileObject;
    import javax.tools.ToolProvider;
    
    public class DynamicCompile {
    
        private static String className = "DynamicObj";
        private static String packageName = "package com.example;";
        private static String code;
    
        static {
            StringBuilder sb = new StringBuilder();
            sb.append(packageName);
            sb.append(" public class " + className + " {\n");
            sb.append("   public int i;\n");
            sb.append("   public int j;\n");
            sb.append("   public " + className + "(int i, int j) {\n");
            sb.append("       this.i = i;\n");
            sb.append("       this.j = j;\n");
            sb.append("   }\n");
            sb.append("   public int add() {\n");
            sb.append("       return this.i + this.j;\n");
            sb.append("   }\n");
            sb.append(" }");
            code = sb.toString();
        }
    
        public static void main(String[] args) throws IOException, ClassNotFoundException, IllegalAccessException, InstantiationException, InvocationTargetException {
            // 获取编译器
            JavaCompiler compiler = ToolProvider.getSystemJavaCompiler();
            // 文件管理器
            DynamicClassLoader classLoader = new DynamicClassLoader(DynamicCompile.class.getClassLoader());
            // 内存中的源代码文件
            List<JavaFileObject> sources = new ArrayList<>();
            sources.add(new StringSourceFileObject(className, code));
            // 编译任务
            JavaCompiler.CompilationTask task = compiler.getTask(null, null, null, null, null, sources);
            // 执行编译任务
            if (task.call()) {
                // 加载Class文件
                Class<?> clazz = classLoader.loadClass(packageName + className);
                // 创建对象
                Object obj = clazz.getDeclaredConstructor(int.class, int.class).newInstance(1, 2);
                // 调用方法
                Method method = clazz.getDeclaredMethod("add");
                int result = (int) method.invoke(obj);
                System.out.println(result);
            }
        }
    
        /**
         * 内存中的源代码文件
         */
        private static class StringSourceFileObject extends SimpleJavaFileObject {
    
            private String code;
    
            /**
             * 构造方法
             * 
             * @param className 类名
             * @param code 源代码
             */
            protected StringSourceFileObject(String className, String code) {
                super(URI.create("string:///" + className.replace('.', '/') + Kind.SOURCE.extension), Kind.SOURCE);
                this.code = code;
            }
    
            /**
             * 返回源代码
             */
            @Override
            public CharSequence getCharContent(boolean ignoreEncodingErrors) throws IOException {
                return code;
            }
        }
    
        /**
         * 自定义ClassLoader,从指定的ClassPath中查找类
         */
        private static class DynamicClassLoader extends ClassLoader {
    
            private static final String CLASS_SUFFIX = ".class";
            private String classPath;
    
            /**
             * 构造方法
             * 
             * @param parent 父ClassLoader
             */
            protected DynamicClassLoader(ClassLoader parent) {
                super(parent);
                classPath = System.getProperty("java.class.path");
            }
    
            /**
             * 查找指定的类
             */
            @Override
            public Class<?> findClass(String name) throws ClassNotFoundException {
                // 查找ClassPath上对应的类文件
                String fileName = name.replace('.', '/') + CLASS_SUFFIX;
                File file = new File(classPath, fileName);
                if (file.exists()) {
                    try (FileInputStream fis = new FileInputStream(file);
                            ByteArrayOutputStream baos = new ByteArrayOutputStream()) {
                        byte[] buffer = new byte[1024];
                        int len = -1;
                        while ((len = fis.read(buffer)) != -1) {
                            baos.write(buffer, 0, len);
                        }
                        byte[] bytes = baos.toByteArray();
                        // 重新定义类
                        return defineClass(name, bytes, 0, bytes.length);
                    } catch (IOException e) {
                        e.printStackTrace();
                    }
                }
                return super.findClass(name);
            }
        }
    }
    

    此外,还可以使用其他语言来编译生成Java类文件,比如Groovy。下面是一个使用Groovy的例子,展示如何在Groovy中使用Java语法来动态编译生成Java类文件,并在Java中创建对象。

    class DynamicObj {
        int i
        int j
        DynamicObj(int i, int j) {
            this.i = i
            this.j = j
        }
        int add() {
            return this.i + this.j
        }
    }
    
    // 编译groovy代码生成class文件
    import groovy.lang.GroovyClassLoader
    import java.io.File
    
    String code = """package com.example;
                   |class DynamicObj {
                   |    int i
                   |    int j
                   |    DynamicObj(int i, int j) {
                   |        this.i = i
                   |        this.j = j
                   |    }
                   |    int add() {
                   |        return this.i + this.j
                   |    }
                   |}""".stripMargin() // groovy代码,使用Java语法
    GroovyClassLoader loader = new GroovyClassLoader()
    Class clazz = loader.parseClass(code)
    File file = loader.getBytecode(clazz).file
    println(file) // class文件所在路径
    
    // 创建对象
    ClassLoader parent = null // 父ClassLoader,一般为null即可
    DynamicClassLoader classLoader = new DynamicClassLoader(parent)
    Class<?> clazz = classLoader.loadClass("com.example.DynamicObj")
    Object obj = clazz.getDeclaredConstructor(int.class, int.class).newInstance(1, 2)
    Method method = clazz.getDeclaredMethod("add")
    int result = (int) method.invoke(obj)
    println(result)
    

    以上代码展示了如何使用Groovy动态编译生成Java类文件,并在Java中使用ClassLoader加载,创建对象并调用方法。注意,在使用Groovy时需要引入相应的依赖包。

编译过后创建对象,你在其他没编译的地方也用不了,是要做什么功能呢?