代码之家  ›  专栏  ›  技术社区  › 

想法:在Java中嵌入数据/DSL作为注释,并用APT生成Java代码

  •  2
  •  · 技术社区  · 7 年前

    我有一个主意,我想让你帮我做一些反馈。请看一下下面的内容,让我知道你的想法,不管是积极的还是消极的。

    我一直希望有一种方法在Java代码中嵌入某些数据,而不必总是遵循Java的规则。我最近听到很多关于领域特定语言(DSL)的讨论,如果我们能每天更多地利用它们,那将是多么的棒。我想我知道如何以一种相当优雅的方式来做这件事。

    下面是一些我知道的例子,这些例子在Java代码(和其他类似C语言的语言)中表示我想要解决的问题:

    作为字符串数组的短字符串列表

    String[] ar = { "Item1", "Item2", "Item3", "Item4" };
    

    作为字符串数组的长字符串列表

    String[] ar = { "The quick brown\n fox jumped over\n the lazy dog.",
    "The quick brown\n fox jumped over\n the lazy dog.",
    "The quick brown\n fox jumped over\n the lazy dog.",
    "The quick brown\n fox jumped over\n the lazy dog.",  };
    

    作为多维字符串数组的字符串表:

    String[][] ar = { { "InvoiceID", "Date", "SubTotal", "Tax", "Total" },
    { "1", "1/2/2009", "300, "21", "321" },
    { "2", "1/4/2008", "100", "7", "107" },
    { "3", "1/6/2008", "200", "14", "214" } };
    

    键值对列表

    Map states = new HashMap();
    states.add("FL", "Florida");
    states.add("OH", "Ohio");
    states.add("GA", "Georgia");
    states.add("NY", "New York");
    states.add("SC", "South Carolina");
    

    HTML代码单个字符串

    String html = "<a href=\"www.somesite.com\">Some site</a>";
    

    具有适当文本格式的HTML文本块

    String html = "Hi, John,\r\n<br>\r\n<br>Thank you for writing to us. We do not currently carry that specific product.\r\n<br>\r\n<br>Regards,\r\n<br>";
    

    我已经对下面描述的解决方案进行了一些研究,我相信可以创建一个可用的库,使您能够优雅地实现这一点。在Java 5和6中,有一种称为注释处理器工具(APT)的东西(与Debian APT不一样)。您可以创建自己的源代码处理器,它将在编译代码时被调用,以便您有机会重写源代码。在重写代码之后,它会像往常一样被编译。

    必须执行以下操作才能使用APT: 1。把这个库的jar放在ant类路径上。 2。将这个库的jar放在项目类路径上。 三。调用apt任务而不是javac,并添加preprocessdir参数来指定生成的文件必须放在哪里。

    DSL代码可以放置在一个注释之后,在代码的结果所在的变量之后。当处理器运行时,它可以在下一个注释的代码中向前看,提取代码,通过处理器运行它,生成代码并进行编译。

    这又是一个列表,这次是它的样子:

    作为字符串数组的短字符串列表

    @DslTextArray
    String[] ar = null; /* Item1, Item2, Item3, Item4 */
    

    作为字符串数组的长字符串列表

    @DslMultilineTextArray
    String[] ar = null;
    /*
    The quick brown
    fox jumped over
    the lazy dog.
    
    The quick brown
    fox jumped over
    the lazy dog.
    
    The quick brown
    fox jumped over
    the lazy dog.
    
    The quick brown
    fox jumped over
    the lazy dog.
    */
    

    作为多维字符串数组或JTable的字符串表:

    @DslTextTable
    String[][] ar = null;
    /*
    InvoiceID,Date,SubTotal,Tax,Total
    1,1/2/2009,300,21,321
    2,1/4/2008,100,7,107
    3,1/6/2008,200,14,214
    */
    

    键值对列表

    @DslMap
    Map states = null; /* FL=Florida, OH=Ohio, GA=Georgia, NY=New York, SC=South Carolina */
    // Could also put each pair on a new line
    

    HTML代码单个字符串

    @DslText
    String html = null; /* <a href="www.somesite.com">Some site</a> */
    

    具有适当文本格式的HTML文本块

    @DslText
    String html = null;
    /*
    Hi, John,
    
    Thank you for writing to us. We do not currently carry that specific product.
    
    Regards,
    Mike
    */
    

    对于这个解决方案,我可以想到一些要求/特点:

    必须声明变量以保存脚本在Java源代码中生成的数据。这允许其他源代码了解结果数据,即使编译器不知道它来自何处。

    • 不能违反Java语言,IDE和Javac不会显示错误。
    • 使用现有的所有Java代码。无需替换任何现有代码。只要把这些片段添加到你喜欢的任何地方。
    • 必须易于使用其他类型进行扩展。
    • 以后必须能够对IDE进行扩展,允许源代码突出显示和自动完成。
    • 编译时发生翻译,因此必须生成有效的Java代码。
    • 对于列表、多行文本块(如css、sql)等,转换为string和string[]
    • 转换和编码XML、HTML
    • 重写代码时保留相同的行号。不要添加任何行,这样调试和读取错误就不会成为一种痛苦。
    • 在运行时运行用任何bsf语言编写的代码。允许它将任何参数传递给脚本,并将任何Java类或原语返回到Java。
    • 在编译时运行用任何bsf语言编写的代码以生成java源代码。类似于m4在linux上的使用。
    • 稍后:允许您将多个调用的字符串结果链接在一起,以生成长字符串。有些是编译时的,有些是运行时的。

    再说一遍,我真的很希望能得到一些反馈。这是个愚蠢的主意吗?外面已经有这样的东西了吗?你会费心用这样的东西吗?还是我应该把它留给自己?

    2 回复  |  直到 15 年前
        1
  •  2
  •   Aaron Walker    15 年前

    我将使用google collections api现在是番石榴图书馆的一部分 http://code.google.com/p/guava-libraries/ 它有很棒的列表和地图支持。它支持您试图实现的那种结构

    public static final ImmutableList<Color> GOOGLE_COLORS
       = new ImmutableList.Builder<Color>()
           .addAll(WEBSAFE_COLORS)
           .add(new Color(0, 191, 255))
           .build();
    
        2
  •  1
  •   Jens Schauder    17 年前

    这当然是可行的,但我必须说我不太喜欢。

    它使数据结构的初始化更加容易,

    但是

    • 我很少需要用编译时常量初始化这样的数据结构。因此,NEXHT到类/Java文件的单独文件会更有用。

    • 对于开发人员来说,这一点都不透明。没有人希望评论转化为数据。实际上,如果a遇到这样的注释,我可能会认为它注释了旧代码并立即删除它

    • atp是一个强大而有趣的工具,但是缺乏ide集成。所以你必须一直使用Ant来构建和运行你的应用程序,这并不像Hitten F11或者IDE为此提供的任何快捷方式那么快

    因此,基本上,您需要在开发基础架构复杂性上付出巨大的努力,才能在输入速度上获得最小的收益。

    不过,这个想法还是很有趣的。实际上,我会特别注意一个变体,在这里可以定义一个类型为“dsl”的注释,允许用注释声明定义的任意语言将代码放入该注释中。当然,这将是一个重大的语言变化,短期内不会发生,而且可能根本不会发生。