Java向后兼容性不起作用

时间:2013-09-12 12:16:40

标签: java gradle

我已经创建了用于编码/解码属性文件的库。图书馆有两个主要目的:

  1. 对属性文件进行编码并将其保存到另一个文件中。
  2. 从编码文件返回键值(解码文件,将结果存储为内存中的字符串,将字符串加载到Properties对象并从属性对象返回结果)。
  3. 一切似乎都运行正常,但今天我注意到这个库在java 1.5上不起作用。我注意到解码端出现问题,所以让我们关注这段代码。假设负责解码的代码如下:

    String props = "key1=val1\nkey2=val2";
    Properties p = new Properties();
    p.load(new StringReader(props));
    p.list(System.out);
    

    经过几次测试后,我发现问题在于这一行:

    p.load(new StringReader(props));
    

    我发现java 1.5中的Properties类没有load(Reader)声明。为了满足java 1.5 API要求,我将此行更改为load(InputStream)。现在一切正常,但问题就在这里。

    我使用gradle编译项目,我知道这个库应该可以在java 1.5+上运行(我在我的计算机上安装了java 1.7)所以我添加了build.gradle这两行

    sourceCompatibility = '1.5'
    targetCompatibility = '1.5'
    

    我认为java编译器会知道我想编译兼容java 1.5的代码并显示相应的错误。为了确保它不是gradle问题,我从命令行编译了java代码,但结果相同(编译器没有显示任何错误)。那么为什么编译器在编译时没有显示任何错误呢?

    Java 1.5属性类API:http://docs.oracle.com/javase/1.5.0/docs/api/java/util/Properties.html

    Java 1.6 Properties class API:http://docs.oracle.com/javase/6/docs/api/java/util/Properties.html

    [UPDATE]

    -source-target都不会检查API兼容性。如果是这样,我怎么能在gradle中检查它? 正如millimoose写道,maven有这个插件(http://mojo.codehaus.org/animal-sniffer-maven-plugin/index.html)但是gradle有什么用?

2 个答案:

答案 0 :(得分:4)

请参阅名为“交叉编译”和“交叉编译示例”的javac文档部分。

http://docs.oracle.com/javase/7/docs/technotes/tools/solaris/javac.html#crosscomp-options

特别是这部分:

  

使用-bootclasspath和-extdirs非常重要   交叉编译;请参阅下面的交叉编译示例.......如果不这样做   指定正确版本的bootstrap类,编译器会   使用旧语言规则(在此示例中,它将使用版本1.6   (Java编程语言)与新的bootstrap相结合   类,这可能导致类文件在旧版本上不起作用   平台(在本例中为Java SE 6)因为引用不存在   方法可以包括在内。

答案 1 :(得分:2)

-source开关仅指示编译器在使用指定版本不支持的语言构造时发出编译错误。例如,使用带有-source 1.6的try-with-resources将导致编译错误,因为它仅在Java 7及更高版本中受支持。它的使用更多是一种健全性检查(即:我的代码仍然与Java版本1.x兼容)

-target开关指示编译器发出与指定版本兼容的字节代码。即:已编译的代码可以在指定版本的虚拟机上运行。

但是,这些开关都不会使编译器检查与早期Java版本的Java库的兼容性。这就是为什么自Java 7以来,如果您使用-target 1.6(或更早),编译器会发出警告,您还应该指定-bootclasspath指向该Java版本的Java运行时库集,以便它可以检查您的代码是否仅使用该Java版本的类和方法。