2

有没有办法从java代码级别直接向解析器和词法分析器发出指令?如果不是,那么一个人怎么可能做到这一点呢?

问题是我想让解析器评估一个变量,备份,然后将该变量的值分配为对象名称。像这样:

String s = "text";

SomeClass (s) = new SomeClass();

解析器读取--> 好的,s 评估为“文本”...解析器回溯,同时将“文本”保存在内存中并将“文本”分配为 SomeClass 的新实例的名称,因此现在可以这样做:

text.callSomeMethod();

我需要这样做,因为我必须实例化任意数量的 SomeClass 对象。每个人都必须有一个唯一的名称,最好是这样做:

while (someArbitrarySet.hasNext()) {
    String s = "token" + Math.random();
    SomeClass (s) = new SomeClass();
    (s).callSomeMethod();
}

我希望这是有道理的...

4

5 回答 5

1

您要的是某些语言称为 MACROS 的内容。它们有时也称为预处理器定义,或简称为“定义”。

决定在 Java 中不包含包含和宏等,因为它引入了额外的代码维护问题,设计人员认为这些问题会导致代码不符合他们想要的风格。

然而,仅仅因为它没有内置在编译器中并不意味着你不能将它添加到你的构建脚本中。

作为构建的一部分,您将所有文件复制到 src-comp 目录,然后按照定义替换令牌。

我不建议这样做,但这并不意味着它是不可能的。

于 2011-02-23T00:41:46.543 回答
1

您所描述的(在运行时创建新的命名变量)在 JavaScript、Lua、Bash 等解释语言中是可能的,但在 Java 等编译语言中则不然。当循环执行时,没有源代码可以操作,所有命名变量都必须先定义。

除此之外,您的变量不需要“唯一”名称,如果您按顺序(一个接一个)使用它们,您也可以像这样编写循环:

while (someArbitrarySet.hasNext()) {
    SomeClass sC = new SomeClass();
    sC.callSomeMethod();
}

如果您确实同时需要您的对象,请将它们放入某种数据结构中。最简单的是一个数组,如果你想通过键再次找到它们,你可以使用一个集合(如 ArrayList)或映射(如 CajunLuke 所写)。

实际上,数组(在 Java 中)只不过是变量的集合(所有类型都相同),您可以通过 int 对其进行索引。

(并且允许在运行时创建新变量的脚本语言也使用某种映射字符串→(任何东西)来实现这一点,其中该映射是方法/脚本本地或属于某个周围对象。)


您在对该问题的评论中写道(最好将这些内容添加到问题本身,它有一个“编辑”按钮):

在不涉及太多细节的情况下,我正在编写一个在更大程序中运行的应用程序。通常,在我处理完这些对象后,它们会被垃圾收集,但是更大的程序会维护它们,因此需要为每个对象指定一个唯一的名称。如果我不给每个对象一个唯一的名称,旧对象将被覆盖,但在更大程序的上下文中仍然需要它。

那么,您想保留对象以避免垃圾收集吗?使用数组(或列表或其他任何东西)。

问题是,如果您希望更大的程序能够使用这些对象,无论如何您都必须以某种方式将它们交给这个更大的程序。然后这个程序必须保留对这些对象的引用,从而避免垃圾收集。所以看起来你想通过不存在的方式解决一个不存在的问题:-)

于 2011-02-23T00:47:59.840 回答
0

不是您提出的问题的真正答案,而是您问题的可能解决方案:使用地图。

Map variables = new HashMap();
while (someArbitrarySet.hasNext()) {
    String s = "token" + Math.random();
    variables.put(s, new SomeClass());
    variables.get(s).callSomeMethod();
}

这样,您可以使用“变量名”作为映射中的键,并且可以在不弄乱词法分析器/解析器的情况下顺利进行。

我真的希望有一种方法可以专门执行您在 Java 中声明的内容 - 这真的很酷。

于 2011-02-23T00:38:11.477 回答
0

不,那是不可能的。

即使您可以,我也想不出调用它们的方法,因为不会编译可以成功引用它们的代码。

因此,这些选项是 CanjuLuke 描述的选项,或者创建您自己的 Java 解析器,可能使用ANTRL 示例 Java 语法并在那里挂钩您需要的内容。

考虑地图解决方案。

于 2011-02-23T00:47:54.593 回答
0

这在How do you use Java 1.6 Annotation Processing to perform compile time weaving 中得到了解答?.

简而言之,有一个注解处理工具可以让您扩展 java 语法,并创建编译成 java 注解的 DSL。

在 JDK 1.5 下,您必须使用apt代替javac,但在 1.6 下,这些会受到-processorto 标志的影响javac。来自javac -help

-processor <class1>[<class2>,<class3>...]Names of the annotation processors to run; bypasses default discovery process
-processorpath <path>      Specify where to find annotation processors
于 2011-02-23T01:05:21.960 回答