两个Java类的比较

两个Java类的比较,java,compiler-construction,syntax,semantics,Java,Compiler Construction,Syntax,Semantics,我有两个java类,它们在语义上非常相似,但在语法上却不同。差别很小,比如- 变量名的更改 某些语句位置的变化(中间没有从属行) 额外进口等 我需要比较这两个类,以证明它们在语义上确实相同。对于大量java文件对,也需要这样做 第一种方法是读取两个文件并比较行,用逻辑处理上述差异,这种方法似乎效率低下。有没有其他方法可以完成这项任务?有什么有用的API吗?如果您想检查代码中的更改,请尝试e或 但是,如果您想要逻辑上的差异,恐怕您必须手动执行 我建议使用这些工具中的一种来查找文本更改,然后查找逻辑

我有两个java类,它们在语义上非常相似,但在语法上却不同。差别很小,比如-

变量名的更改

某些语句位置的变化(中间没有从属行)

额外进口等

我需要比较这两个类,以证明它们在语义上确实相同。对于大量java文件对,也需要这样做


第一种方法是读取两个文件并比较行,用逻辑处理上述差异,这种方法似乎效率低下。有没有其他方法可以完成这项任务?有什么有用的API吗?

如果您想检查代码中的更改,请尝试e或

但是,如果您想要逻辑上的差异,恐怕您必须手动执行


我建议使用这些工具中的一种来查找文本更改,然后查找逻辑差异。

有很多相似性检查工具,到目前为止,还没有完美的工具用于此。每种方法都有自己的优点/缺点。这些方法通常分为两类:基于令牌的或基于树的

基于标记的相似性检查通常使用正则表达式完成,但也可以使用其他方法。在我大学的一个项目中,我们利用生物信息学领域的对齐策略开发了一个。这种技术的缺点主要是如果两个源的大小不相等


基于树的更像是一个编译器,所以通常使用一些编译技术可以(或多或少)检查这一点。基于树的方法的缺点是比较复杂度呈指数级。

逐行比较是行不通的。我认为您可能需要使用解析器。我建议你去看看。它应该有一个java语法,您可以在其中放置您的操作来进行比较。

编译这两个类而不包含调试信息,然后将它们反编译回源文件。反编译的文件应该比原始源文件更相似

您可以通过对编译的文件运行一些优化来进一步改进这一点。例如,您可以使用刚刚启用的收缩来删除未使用的代码


但有些语句的位置变化可能很难检测到。

据我所知,现在有办法比较两个Java类的语义。以以下两种方法为例:

public String m1(String a, int b) { ... }

由于变量和方法名称的变化,它们的签名是相同的:相同的返回类型和相同的输入类型。然而,这并不能保证这两个方法在语义上是等价的。例如,
m1
可以返回由
a
的第一个
b
字符组成的字符串,而
m2
可以返回由
y
重复的
x
组成的字符串。正如您所看到的,虽然只有变量和名称发生变化,但这两个方法的语义是完全不同的

我看不出解决你问题的捷径。您可以做一些假设,尝试以下方法:

  • 假设两个类中的方法名称相同
  • 为第一个类中的所有方法编写测试用例(例如使用JUnit)
  • 在第二个类上运行测试用例
  • 确保第二个类没有其他(未测试的)方法(例如使用反射)
这种方法为您提供了一个关于等价语义的概念,但它做出了强有力的假设

最后,让我补充一句,指定程序的语义是一个有趣且开放的研究主题。这方面的一些有趣的发展包括对生物多样性的研究。为程序提供机器可处理语义的一种广泛采用的方法是指定它们的IOPE:输入和输出类型(如上面的Java方法所示),以及它们的前提条件和效果。先决条件本质上是成功调用程序所必须满足的逻辑条件,而效果则是对程序成功执行所导致的变化(世界状态)的正式描述。即使使用IOPE,也存在很多问题。。。在这个简短的描述中我跳过了

public String m2(String x, int y) { ... }