1

我正在尝试在 Java 中执行以下操作:

我有一个字符串集合(介于 1 到 10 000 之间),每个字符串包含一个类的相同抽象方法的不同方法体(它们是用 Java 代码编写的)。例如:

string1= "int a=1;" 
string2="System.out.println(\"HelloWorld\");"
...

每个字符串都可以是以下抽象方法的实现:

abstract class FOO{
    public abstract void doSomething();
}

对于每个字符串,我想生成一个 FOO 实例来使用。

我不太确定最好的方法是什么:我在网上搜索并提出了以下建议:

  • 使用 java 6 编译器 API 生成 .class 文件并加载它们
  • 使用像 cglib 这样的字节码操作库来修改编译代码

还有其他建议吗,因为这些看起来有点复杂(至少对我自己而言)......

谢谢你的帮助

编辑:

我可能在我的问题上走错路了。这是我最终想要实现的目标:

我有一个代表树中节点的接口

public  interface Node{
    public <T> void process(T input);

/* ... 与我的问题无关的其他方法 ...*/ }

当您向节点提供 T 的实例时,它会对其执行某些操作(有些可能需要访问 Node 的其他方法),并将其传递给子节点。

问题是(程序的规范):程序从文本文件中读取并构建节点,包括该方法主体(主体在 java 中)。然后它构建树并返回它。

我的印象是,要做到这一点,我必须以某种方式为文本文件中提供的每个方法生成 Node 的实现。我可能是错的,但可能有更好的方法......

4

1 回答 1

3

Perhaps what you want is BeanShell

BeanShell is a small, free, embeddable Java source interpreter with object scripting language features, written in Java. BeanShell dynamically executes standard Java syntax and extends it with common scripting conveniences such as loose types, commands, and method closures like those in Perl and JavaScript.

You can use BeanShell interactively for Java experimentation and debugging as well as to extend your applications in new ways. Scripting Java lends itself to a wide variety of applications including rapid prototyping, user scripting extension, rules engines, configuration, testing, dynamic deployment, embedded systems, and even Java education.

BeanShell is small and embeddable, so you can call BeanShell from your Java applications to execute Java code dynamically at run-time or to provide extensibility in your applications. Alternatively, you can use standalone BeanShell scripts to manipulate Java applications; working with Java objects and APIs dynamically. Since BeanShell is written in Java and runs in the same VM as your application, you can freely pass references to "live" objects into scripts and return them as results.

In short, BeanShell is dynamically interpreted Java, plus a scripting language and flexible environment all rolled into one clean package.

Summary of features

  • Dynamic execution of the full Java syntax, Java code fragments, as well as loosely typed Java and additional scripting conveniences.
  • Transparent access to all Java objects and APIs.
  • Runs in four modes: Command Line, Console, Applet, Remote Session Server.
  • Can work in security constrained environments without a classloader or bytecode generation for most features.
  • The interpreter is small ~150K jar file.
  • Pure Java.
  • It's Free!!

An alternative is to use a library I wrote which wraps the Compiler API so that it compiles in memory and loads into the current ClassLoader (by default)

http://sourceforge.net/projects/essence/files/Essence%20Java%20Config.%20Files/Essence%20JCF%201.02/

http://vanillajava.blogspot.co.uk/2010/11/more-uses-for-dynamic-code-in-java.html

// this writes the file to disk only when debugging is enabled.
CachedCompiler cc = CompilerUtils.DEBUGGING ?
        new CachedCompiler(new File(parent, "src/test/java"), new File(parent, "target/compiled")) :
        CompilerUtils.CACHED_COMPILER;

String text = "generated test " + new Date();
Class fooBarTeeClass = cc.loadFromJava("eg.FooBarTee", "package eg;\n" +
    '\n' +
    "import eg.components.BarImpl;\n" +
    "import eg.components.TeeImpl;\n" +
    "import eg.components.Foo;\n" +
    '\n' +
    "public class FooBarTee{\n" +
    "    public final String name;\n" +
    "    public final TeeImpl tee;\n" +
    "    public final BarImpl bar;\n" +
    "    public final BarImpl copy;\n" +
    "    public final Foo foo;\n" +
    '\n' +
    "    public FooBarTee(String name) {\n" +
    "        // when viewing this file, ensure it is synchronised with the copy on disk.\n" +
    "        System.out.println(\"" + text + "\");\n" +
    "        this.name = name;\n" +
    '\n' +
    "        tee = new TeeImpl(\"test\");\n" +
    '\n' +
    "        bar = new BarImpl(tee, 55);\n" +
    '\n' +
    "        copy = new BarImpl(tee, 555);\n" +
    '\n' +
    "        // you should see the current date here after synchronisation.\n" +
    "        foo = new Foo(bar, copy, \"" + text + "\", 5);\n" +
    "    }\n" +
    '\n' +
    "    public void start() {\n" +
    "    }\n" +
    '\n' +
    "    public void stop() {\n" +
    "    }\n" +
    '\n' +
    "    public void close() {\n" +
    "        stop();\n" +
    '\n' +
    "    }\n" +
    "}\n");

// add a debug break point here and step into this method.
FooBarTee fooBarTee = new FooBarTee("test foo bar tee");
Foo foo = fooBarTee.foo;
assertNotNull(foo);
assertEquals(text, foo.s);
于 2012-10-30T12:56:49.797 回答