【问题标题】:Idea: Embed data/DSLs in Java as comments and generate Java code with APT想法:在 Java 中嵌入数据/DSLs 作为注释并使用 APT 生成 Java 代码
【发布时间】:2009-03-17 04:33:15
【问题描述】:

我有一个想法,我想由你运行它以获得一些反馈。请仔细阅读以下内容,让我知道您的想法,无论是积极的还是消极的。

我一直希望有一种方法可以在 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 放到项目的classpath 上。 3.调用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 代码。无需替换任何现有代码。只需将这些 sn-ps 添加到您喜欢的位置即可。
  • 必须易于使用其他类型进行扩展。
  • 以后必须能够对允许源代码突出显示和自动完成的 IDE 进行扩展。
  • 翻译发生在编译时,因此必须生成有效的 Java 代码。
  • 对于列表、CSS、SQL 等多行文本块等内容,转换为 String 和 String[]
  • 转换和编码 XML、HTML
  • 重写代码时保留相同的行号。不要添加任何行,以免调试和读取错误变得痛苦。
  • 在运行时运行以任何 BSF 语言编写的代码。允许它向脚本传递任何参数并将任何 Java 类或原语返回给 Java。
  • 在编译时运行以任何 BSF 语言编写的代码以生成 Java 源代码。类似于在 Linux 上使用 M4。
  • 稍后:允许您将多次调用的字符串结果链接在一起,以构建一个长字符串。有些可能是编译时的,有些可能是运行时的。

再次,我非常感谢您对此提供一些反馈。这是一个愚蠢的想法吗?那里已经有类似的东西了吗?你会费心使用这样的东西还是我应该把它留给自己?

【问题讨论】:

    标签: java dsl


    【解决方案1】:

    我会使用现在是番石榴库http://code.google.com/p/guava-libraries/ 的一部分的google collections api,它有很棒的列表和地图支持。它支持您尝试实现的构造类型

    public static final ImmutableList<Color> GOOGLE_COLORS
       = new ImmutableList.Builder<Color>()
           .addAll(WEBSAFE_COLORS)
           .add(new Color(0, 191, 255))
           .build();
    

    【讨论】:

      【解决方案2】:

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

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

      但是

      • 我极少需要像这样使用编译时常量初始化数据结构。所以类/java文件旁边的单独文件会更有用

      • 这对开发人员来说根本不透明。没有人期望 cmets 转化为数据。其实如果遇到这样的评论,我可能会认为它评论了旧代码并立即删除它

      • ATP 是一个强大而有趣的工具,但缺乏 IDE 集成。因此,您必须始终使用 ANT 构建和运行您的应用程序,这不如 hitten F11 或您的 IDE 为此提供的任何快捷方式那么好和快

      因此,基本上你会在开发基础架构的复杂性方面受到巨大的打击,以最大限度地提高打字速度。

      这个想法仍然很有趣。我实际上会理解一种变体,其中可以定义“DSL”类型的注释,允许以注释声明定义的任意语言将代码放入该注释中。当然,这将是一个重大的语言变化,不会很快发生,而且可能根本不会发生。

      【讨论】:

      • 在 cmets 中执行的代码肯定会给开发人员带来问题,但我认为这可以通过向新贡献者提及这一点来控制。我的示例实际上不包含任何 BSF 脚本,这可能是大多数人使用它的目的。我会看看添加那个。
      • Netbeans 确实使用了 ant 和 build.xml,因此您可以修改它并将 javac 替换为 apt。 Eclipse 不使用 ant 构建它吗?你在谈论不同的IDE吗?同意,我怀疑他们会在语言中原生支持这样的功能。
      • No Eclipse 不使用 ANT 进行构建。它做它自己的增量构建事情。它有一个 APT 构建器(我认为),但它没有与增量构建很好地集成。至少这是我大约一年前收集到的信息
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2017-07-08
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多