在不知道公共类名的情况下编译.java文件

时间:2016-08-20 00:19:49

标签: java

我想知道如何在不知道公共类名的情况下编译.java文件。

提供示例用例:我正在操作沙箱,允许用户向我发送一个字符串。我将该字符串写入.java文件,我编译该文件,评估结果类并回复输出。

···。java的

public class HelloWorld {
    public static void main(String[] args) {
        System.out.println("Hello, World");
    }
}

如果我要随机分配?????.java名称,例如 test.java 并运行命令javac test.java,那么它将会失败

错误:类HelloWorld是公共的,应该在名为HelloWorld.java的文件中声明,如下所示:

HelloWorld.java

public class HelloWorld {
    public static void main(String[] args) {
        System.out.println("Hello, World");
    }
}

这可能吗?我应该放弃编译Java的能力,还是有替代解决方案?

6 个答案:

答案 0 :(得分:1)

嗯......为了能够评估自定义代码,您还必须使用main方法知道类名。

我认为最便宜的方法是强迫用户遵守某种代码约定,即“包名称应该是foo.bar.baz,类名是Qux,主类是强制性的”。在这种情况下,您可以直接从编译器向用户传递错误消息并显示代码约定。

不那么快的方法是做一些肮脏的技巧,比如用另一个已知名称的类正确包装收到的代码,弄乱包名,然后尝试对内部类main方法进行反射调用,但在这种情况下你正确的错误报告会出现问题而且容易出错。

正确且可能很长的方法是使用java源代码解析器(如this,构建AST,找出顶级类,根据包/类名重命名文件,执行javac(甚至从AST生成字节码)。

修改

你也可以参加java-repl项目。这可以让你评估类似脚本的程序。

希望有所帮助!

答案 1 :(得分:1)

如果源文件的基本名称与源代码中的类名不匹配,则没有简单的方法来编译“.java”文件。如果您不知道文件名应该是什么,那么您唯一的选择是(部分)解析源代码以找到它。

但说实话,这是你应该以不同方式解决的问题:

  • 如果您自己生成了源代码,那么 应该知道类名称的时间,因此您应该能够推断出正确的名称“.java”文件。

  • 如果您正在编译“为您提供”的文件,那么您可以(并且IMO应该)坚持在具有适当文件名的“.java”文件中提供它。如果文件名与类名不匹配,那就错了......你不知道错误是文件名还是类名!

这是一个适合你的思考实验。假设某人为您提供了源代码文件:

  • A.java ...包含班级A
  • B.java ...还包含课程A

你应该怎么做?如果您试图从文件中的类名中找出“正确”的文件名,您可能会错过用户在B.java中犯了错误并将错误的类名放入源代码中!

简而言之,您有两条相互矛盾的信息。它们中的任何一个都可能不正确。如果你让一个人自动优先于另一个,你会错过错误。

答案 2 :(得分:0)

如果你没有将它声明为公共类,你实际上可以编译该类。

示例:

class Test {
   public static void main(String[] args) {
       System.out.println("Hello world");
   }
}

将文件另存为.java,并在cmd

上进行编译
javac .java

您可以使用班级名称

继续运行
java Test

答案 3 :(得分:0)

  

如果我要随机分配?????。java一个名称如test.java并运行命令javac test.java那么它就会失败

     

错误:类HelloWorld是public,应该在名为HelloWorld.java的文件中声明

好的,请查看错误消息!编译器有助于告诉您文件的名称应该是什么。不要扔掉那些信息。解析错误消息以找到正确的文件名,重命名该文件,然后重试。

答案 4 :(得分:0)

我有个建议。当有人发送给你xxxx.jar文件时,你必须将它保存到某个地方,所以你知道文件夹路径。然后你可以使用下面的代码来获取名称。获得文件名和路径后,使用java反射技术获取方法并调用方法。

final static void showAllFiles(File dir) throws Exception
{
   File[] fs = dir.listFiles();
   for(int i=0; i<fs.length; i++)
   {
      // here you can get file name and path, then use reflection to get the instance and methods.
   }
}

答案 5 :(得分:-3)

要保持相同名称编译的类的名称,在“公共类HelloWorld”中,“HelloWorld”是类名,同时,它的名称是 编译。

public class Hello{
        public static void main(String[] args) {
           System.out.println("Hello, World");
    }
}


您可以在cmd javac Hello.java上进行编译。
运行java Hello

public class Hello2{
        public static void main(String[] args) {
           System.out.println("Hello, Man");
    }
}

你可以在cmd javac Hello2.java上这样遵守
运行java Hello2