2011-06-20 116 views
4

我有两个在语义上非常相似但语法不同的java类。差异是次要的,就像 -两个Java类的比较

变化的变量名,

变化某些语句(中间无依赖线)的位置,

额外进口等

我需要比较这两个类来证明它们的确在语义上是相同的。大量的java文件对需要完成相同的工作。

第一种从两个文件中读取数据并比较这些数据行与处理上述差异的逻辑似乎效率不高。有什么其他方式可以实现这一任务吗?那里有任何有用的APIs?

回答

1

在没有调试信息的情况下编译这两个类,然后将它们反编译回源文件。反编译的文件应该比原始源文件更加类似。

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

虽然某些语句的位置变化很难检测到。

1

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

但是,如果你想逻辑的差异,恐怕你可能不得不手动。

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

1

这里有很多相似性检查器,直到现在还没有完美的工具。每个人都有自己的优点/缺点。这些方法通常分为两类:基于标记的或基于树的。

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

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

1

逐行比较不会工作。我想你可能需要使用解析器。我建议你看看ANTLR。它应该有一个Java语法,你可以把你的行为做比较。

1

据我所知现在有方法可以比较两个Java类的语义。举个例子如下两种方法:

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

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

的一部分从变量和方法名称的变化,他们的招牌是一样的:相同的返回类型,以及相同的输入类型。然而,这并不能保证这两种方法在语义上是等价的。例如,m1可能会返回由a的第一个b个字符组成的字符串,而m2可能会返回由y重复的x组成的字符串。正如你所看到的,虽然只有变量和名称会改变,但这两种方法的语义完全不同。

我看不出您的问题的简单方法。你可以或许做一些假设,试试下面的办法:

  • 假定在这两个类中的方法名是相同的
  • 写测试用例(例如使用JUnit)在第一类中的所有方法
  • 运行在第二类
  • 测试用例确保第二类不具有其他(未经测试)的方法(例如使用反射)

这种方法提供了有关的想法等价的语义,但它是有力的假设。

作为最后一句话,让我补充一点,指定程序的语义是一个有趣且开放的研究课题。这方面的一些有趣的发展包括对Semantic Web Services的研究。一种广泛采用的将机器可处理的语义赋予程序的方法是指定其IOPE:输入和输出类型(如上面的Java方法int)及其先决条件和效果。先决条件本质上是符合成功调用程序的逻辑条件,而效果是对成功执行程序引起的变化(在世界的状态)的形式描述。即使有IOPE,也存在很多问题......我在这个简短的描述中略过。