我正致力于将一个大型代码库从一个api版本移植到另一个版本(特别是hadoopcdh3到hadoopcdh4)。
在这些库的“升级”过程中,有人决定将一个常用的具体类(jobcontext)更改为一个接口,并将其所有功能移动到一个子类(jobcontextimpl)中。通常这是一个相当直截了当的提议。但是,我们仍然需要维护对库的旧版本的支持,从而将类作为一个具体的和接口来支持。
很明显,我们可以有两套不同的jar,我们可以根据使用的hadoop版本进行交换,但这会给我们带来很多不必要的头痛。我想创建一个版本,将运行两个hadoop版本。
当然,工厂模式会首先出现在您的脑海中,但问题是新版本中的实现类在以前的版本中不存在,因此代码一次只能针对一组库进行编译,只能针对一组库运行。
接下来,我尝试使用groovyscript和一些巧妙的反射来检测类路径中的库的哪个版本。我可以示例化对象,但使用一个我没有编译的库可以得到:
不兼容ClassChangeError:找到接口org.pain.mycontext,但应为类
编辑:总之,我需要能够示例类,可以是一个具体的类或接口。如果它是一个接口,我可以检测它是哪个,我知道实现在哪里,但是如果是具体的,那么实现类就不存在。
1条答案
按热度按时间t9aqgxwy1#
无法让jvm忽略二进制不兼容;i、 e.同一类型的相互矛盾的定义。
也许可以解决这个问题,但这会非常尴尬。
您需要做的是:
消除所有直接和间接引用
JobContext
从源代码初始化,替换所有类型的变量
JobContext
与Object
替换对采用JobContext
作为参数,或使用反射方法或构造函数调用将其作为结果返回Class<?>
为了JobContext
你使用Class.forName(...)
.简言之,如果您可以去掉代码使用或依赖静态加载的
JobContext
,那你就什么都得不到了IncompatibleClassChangeError
该类的例外情况。老实说,我认为您最好只是针对两个hadoopapi分别编译代码库。