Java动态实现抽象方法

时间:2012-10-30 12:52:37

标签: java dynamic runtime

我正在尝试在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的实现。我可能错了,可能有更好的方法......

1 个答案:

答案 0 :(得分:3)

也许你想要的是BeanShell

  

BeanShell是一个小型,免费,可嵌入的Java源代码解释器,具有用Java编写的对象脚本语言功能。 BeanShell动态执行标准Java语法,并使用常见的脚本编写方便性扩展它,例如松散类型,命令和方法闭包,如Perl和JavaScript中的那些。

     

您可以交互式地使用BeanShell进行Java实验和调试,以及以新的方式扩展应用程序。脚本Java适用于各种各样的应用程序,包括快速原型设计,用户脚本扩展,规则引擎,配置,测试,动态部署,嵌入式系统,甚至Java教育。

     

BeanShell很小且可嵌入,因此您可以从Java应用程序调用BeanShell以在运行时动态执行Java代码或在应用程序中提供可扩展性。或者,您可以使用独立的BeanShell脚本来操作Java应用程序;动态地使用Java对象和API。由于BeanShell是用Java编写的,并且与应用程序在同一个VM中运行,因此您可以自由地将对“实时”对象的引用传递给脚本并将其作为结果返回。

     

简而言之,BeanShell是动态解释的Java,加上脚本语言和灵活的环境都集成在一个干净的包中。

     

功能摘要

     
      
  • 动态执行完整的Java语法,Java代码片段,以及松散类型的Java和其他脚本编写方便。
  •   
  • 透明访问所有Java对象和API。
  •   
  • 以四种模式运行:命令行,控制台,小程序,远程会话服务器。
  •   
  • 可以在安全受限的环境中工作,而无需为大多数功能生成类加载器或字节码。
  •   
  • 解释器是小~150K jar文件。
  •   
  • 纯Java。
  •   
  • 这是免费的!!
  •   

另一种方法是使用我编写的库,它包装了编译器API,以便在内存中编译并加载到当前的ClassLoader中(默认情况下)

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);
相关问题