如何在编译/运行时有条件地删除部分应用程序?

时间:2010-11-12 00:14:36

标签: java conditional-compilation

我有一个在嵌入式设备上运行的Java应用程序。由于不同的设备运行不同版本的设备SDK,因此我必须针对~5种不同的设备SDK组合进行构建。

其中一个组合不支持现有对象的特定方法,并完全从SDK中省略另一个对象。

我在我的程序中使用这个方法和对象,但只在某个配置中,所以我想回退到不支持它的设备上的另一个配置。

我很乐意在编译或运行时执行此回退行为。

有条件删除此代码的最简单方法是什么?

代码在其他方面是相同的,所以我不想为这两个SDK创建两个单独的代码分支。

我使用Ant脚本构建我的应用程序。

我的应用程序必须构建一个相当旧的JDK版本(1.1.8 / 1.2),如果这是相关的。

2 个答案:

答案 0 :(得分:2)

一个想法是创建两个具有相同接口的类,一个完整的实现和一个存根,两者都使用isSupported()方法,并且存根中的所有其他方法都会抛出UnsupportedOperationException。然后我可以在我的Ant脚本编译期间有条件地包含正确的类。

我选择使用这个而不是更有活力的方法@Stephen C,因为它非常适合我们的目的,我们对设备(包括设备文件系统)的访问非常有限,因此很难部署多个jar,设置类路径等。

我最终做的事情如下:

  1. 将需要存根的类移动到单独的包中。
  2. 创建一个新目录mypackagenamestub并将要保留的文件复制到其中。确保您的IDE不会更改要存根的文件的包声明。
  3. 我们已经根据构建应用程序的SDK在我们的Ant脚本中设置了SDK路径属性,因此我添加了另一个属性omit.unsupportedmode(释义)并在适当的时候将其设置为true。
  4. 使用条件任务设置值以传递给javac的排除属性,例如**/MyPackageStub/****/MyPackage/**基于omit.unsupportedmode

答案 1 :(得分:2)

@Lawrence Johnston的自我回答草拟了如何在构建时执行此操作。我认为这基本上是正确的想法,但您可能不希望插件API抛出已检查的异常。理想情况下,您希望旧平台的实现能够“尽力”尝试执行所请求的功能。

如果您想在运行时做出决定,您可以:

  • 将不同版本的类放入单独的JAR文件中,并使用包装器脚本在应用程序类路径中包含相应的JAR。

  • 使用Class.forName()动态加载适合该平台的类版本。

在任何一种情况下,您都需要确保基本应用程序类(适用于所有平台)不依赖于任何更高级的SDK / JDK。

最后,我倾向于支持古老的Java版本。多年前它们“终结”,支持它们的要求显然阻碍了你。例如,核心应用程序中向后兼容性的要求意味着它无法利用最近Java版本中添加的许多新功能。有多少客户仍在使用这些古老的Java版本?为什么他们不能升级他们的平台?他们真的需要最新版本的应用程序吗?