我想知道如何在不知道公共类名的情况下编译.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的能力,还是有替代解决方案?
答案 0 :(得分:1)
嗯......为了能够评估自定义代码,您还必须使用main
方法知道类名。
我认为最便宜的方法是强迫用户遵守某种代码约定,即“包名称应该是foo.bar.baz,类名是Qux,主类是强制性的”。在这种情况下,您可以直接从编译器向用户传递错误消息并显示代码约定。
不那么快的方法是做一些肮脏的技巧,比如用另一个已知名称的类正确包装收到的代码,弄乱包名,然后尝试对内部类main
方法进行反射调用,但在这种情况下你正确的错误报告会出现问题而且容易出错。
正确且可能很长的方法是使用java源代码解析器(如this),构建AST,找出顶级类,根据包/类名重命名文件,执行javac(甚至从AST生成字节码)。
修改强>
你也可以参加java-repl项目。这可以让你评估类似脚本的程序。
希望有所帮助!
答案 1 :(得分:1)
如果源文件的基本名称与源代码中的类名不匹配,则没有简单的方法来编译“.java”文件。如果您不知道文件名应该是什么,那么您唯一的选择是(部分)解析源代码以找到它。
但说实话,这是你应该以不同方式解决的问题:
如果您自己生成了源代码,那么 应该知道类名称的时间,因此您应该能够推断出正确的名称“.java”文件。
如果您正在编译“为您提供”的文件,那么您可以(并且IMO应该)坚持在具有适当文件名的“.java”文件中提供它。如果文件名与类名不匹配,那就错了......你不知道错误是文件名还是类名!
这是一个适合你的思考实验。假设某人为您提供了源代码文件:
A
。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