Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/java/323.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
在java中有没有一种将代码存储为变量的方法?_Java_Oop_Variables - Fatal编程技术网

在java中有没有一种将代码存储为变量的方法?

在java中有没有一种将代码存储为变量的方法?,java,oop,variables,Java,Oop,Variables,在Java中,有没有一种方法可以存储、编辑、转换、打印、访问、评估和比较代码块(可能是用户输入的),同时还能执行它们 例如,如果有人编写了一个软件,该软件旨在教人们如何编写代码,用户将向系统输入代码,程序将检查用户开发的代码是否正确 我在找这样的东西: CodeBlock line20And21=`String x=“hello”;System.out.println(x);`;//存储一段代码 第20行和第21行。替换(“ln”和“)//编辑代码块 System.out.println(lin

在Java中,有没有一种方法可以存储、编辑、转换、打印、访问、评估和比较代码块(可能是用户输入的),同时还能执行它们

例如,如果有人编写了一个软件,该软件旨在教人们如何编写代码,用户将向系统输入代码,程序将检查用户开发的代码是否正确

我在找这样的东西:

CodeBlock line20And21=`String x=“hello”;System.out.println(x);`;//存储一段代码
第20行和第21行。替换(“ln”和“)//编辑代码块
System.out.println(line20和21.toString());//转换/打印代码块
代码块usersCode=Scanner.nextCodeBlock();//访问代码块
如果(!line20和21.wouldthowerror());//计算代码块
if(line20和21.woulddothesametingas(line18和19))//比较代码块
第20行和第21行。执行();//执行代码块
我将使用的代码当然比仅仅定义一个字符串并打印它要复杂得多,但我相信想法是一样的。 我真的很感激你在这方面的帮助。谢谢

大多数情况下:没有

Java代码经过一个编译步骤,代码需要在方法中(需要在类型中),而这需要花费相当长的时间来解释原因。编译器在运行时不需要在那里(通常也不需要)

所以,如果你真的想这样做:

  • 代码必须是“完整的”,包括包语句、类声明、方法等
  • 您需要随应用程序一起提供编译器。对于javac来说,这很棘手(GPL);您可以发布获得MIT许可的ecj(eclipse编译器)。这是一个相当大的进步
  • 然后可以将代码“存储”为字符串
  • 然后ecj可以为您将其转换为字节码,但您将有相当长的时间正确管理类路径,以使此代码正确编译
  • 然后,您可以使用一个类加载器动态加载这个字节码,这个类加载器本身有几天的学习曲线
  • 此外,在不执行代码的情况下查看代码以确定它是否会引发异常是不可能的,这称为停止问题。有证据表明这是无法解决的。你不能跑得比光速快。您无法从用“图灵完备”语言编写的任意代码(java是图灵完备的)判断它是否停止(或者在本例中,它是否抛出)


    类似的规则适用于“这会做与之相同的事情吗?”

    您可以使用BeanShell,一个用Java编写的Java解释器来做类似的事情:

    import bsh.Interpreter;
    
    class Test {
      public static void main(String[] args) throws Exception {
        String code = "String x = \"hello\"; System.out.println(x);";
        String newCode = code.replace("ln", "");
    
        System.out.println("Here's the result of running: " +newCode);
    
        Interpreter p = new Interpreter();
        p.eval(newCode);
      }
    }
    
    如果使用正确的依赖项编译和构建,则可以评估代码段:

    $ javac -cp bsh-2.0b4.jar:. Test.java && java -cp bsh-2.0b4.jar:. Test
    Here's the result of running: String x = "hello"; System.out.print(x);
    hello$
    

    您可以运行代码并获取其输出值或返回值,或者它是否引发异常。沙盒和比较两个代码段的输出取决于您。

    自Java 9以来,Java包含一个shell来评估代码段,称为JShell。JShell通过编程方式提供

    首先,您必须通过
    JShell js=JShell.create()创建一个JShell实例
    通过
    js.eval(“System.out.println(/“Hello World/”)将字符串作为Java代码(所谓的代码片段)进行评估
    ,它返回一个
    SnippetEvent
    的列表,您可以检查这些事件,以了解代码段的执行产生了什么影响

    由于代码存储为字符串,因此可以像编辑任何字符串一样对其进行编辑

    以下是JShell获取用户输入代码并存储/评估它的示例,取自,其中代码从stdin读取为字符串并执行:

     import java.io.ByteArrayInputStream;
     import java.io.Console;
     import java.util.List;
     import jdk.jshell.*;
     import jdk.jshell.Snippet.Status;
    
     class ExampleJShell {
         public static void main(String[] args) {
             Console console = System.console();
             try (JShell js = JShell.create()) {
                 do {
                     System.out.print("Enter some Java code: ");
                     String input = console.readLine();
                     if (input == null) {
                         break;
                     }
                     List<SnippetEvent> events = js.eval(input);
                     for (SnippetEvent e : events) {
                         StringBuilder sb = new StringBuilder();
                         if (e.causeSnippet == null) {
                             //  We have a snippet creation event
                             switch (e.status) {
                                 case VALID:
                                     sb.append("Successful ");
                                     break;
                                 case RECOVERABLE_DEFINED:
                                     sb.append("With unresolved references ");
                                     break;
                                 case RECOVERABLE_NOT_DEFINED:
                                     sb.append("Possibly reparable, failed  ");
                                     break;
                                 case REJECTED:
                                     sb.append("Failed ");
                                     break;
                             }
                             if (e.previousStatus == Status.NONEXISTENT) {
                                 sb.append("addition");
                             } else {
                                 sb.append("modification");
                             }
                             sb.append(" of ");
                             sb.append(e.snippet.source());
                             System.out.println(sb);
                             if (e.value != null) {
                                 System.out.printf("Value is: %s\n", e.value);
                             }
                             System.out.flush();
                         }
                     }
                 } while (true);
             }
             System.out.println("\nGoodbye");
         }
     }
    
    import java.io.ByteArrayInputStream;
    导入java.io.Console;
    导入java.util.List;
    导入jdk.jshell.*;
    导入jdk.jshell.Snippet.Status;
    类ExampleJShell{
    公共静态void main(字符串[]args){
    Console=System.Console();
    try(JShell js=JShell.create()){
    做{
    System.out.print(“输入一些Java代码:”);
    字符串输入=console.readLine();
    如果(输入==null){
    打破
    }
    列表事件=js.eval(输入);
    对于(事件片段:事件){
    StringBuilder sb=新的StringBuilder();
    如果(e.causeSnippet==null){
    //我们有一个代码段创建事件
    开关(如状态){
    有效案例:
    某人(“成功”);
    打破
    案例可恢复性定义:
    sb.附加(“未解决的引用”);
    打破
    案例可恢复\u未定义:
    附加(“可能可修复,失败”);
    打破
    案件被驳回:
    某人追加(“失败”);
    打破
    }
    如果(例如,previousStatus==状态。不存在){
    某人附加(“添加”);
    }否则{
    某人附加(“修改”);
    }
    某人附加(“of”);
    sb.append(例如snippet.source());
    系统输出打印LN(sb);
    如果(e.value!=null){
    System.out.printf(“值为:%s\n”,e.Value);
    }
    System.out.flush();
    }
    }
    }虽然(正确);
    }
    System.out.println(“\nGoodbye”);
    }
    }
    
    这是可能的,是的。但并不像你想象的那么容易。如果你想离婚