在1.7版本中,javax.sql.CommonDataSource中新增了一种方法。

24

试图在java 1.7中编译我的应用程序时,我发现javax.sql.CommonDataSource(因此在j.s.DataSource中)新增了一种方法 - getParentLogger()。你可以比较CommonDataSource:1.7CommonDataSource:1.6

对我来说,这个变化肯定会破坏向后兼容性。例如,我的应用程序(其中包含DataSource的实现)甚至在不改变代码的情况下无法针对1.7进行编译。

我认为,这样做应该有非常强的原因-但我无法在谷歌上找到一个。能否有人解释一下这个变化背后的原因?如何正确处理它-对我来说,这是我第一次遇到Java的向后不兼容性,因此我在这里没有任何“最佳实践”……


1
这不是第一次了。每当他们更新JDBC时,这种情况总会发生。我同意这不是一个好的事情(商标)。例如,许多驱动程序需要维护单独的版本,仅因为此原因。这很痛苦,但它应该只会导致编译错误,而不是运行时错误(即您可以为JDK6构建并仍然在JDK7上运行它)。 - Thilo
2
JDBC 接口在过去几次(通过添加方法)变得不兼容向后。您应该能够向您的类中添加附加方法,并且它们应该在 1.7 之前的环境中正常工作,没有任何问题。 - JB Nizet
嗯...这不会破坏二进制兼容性吗?我的DS实现是针对旧的DS编译的,没有添加新方法--这似乎是二进制不兼容的改变,不是吗? - BegemoT
1
编译旧API并在新JDK上运行是可行的(当然,除非有人调用了那些新方法)。反过来(编译新的,在旧的上运行)可能会导致ClassNotFoundExceptions。 - Thilo
3个回答

7

如果你还没准备好支持将应用程序编译为Java 7,你仍然可以使用Java 7编译器编译为Java 1.6。你需要安装一个Java 1.6运行时环境(或SDK)。如果你尝试使用Java 7编译器编译实现了存根DataSourceMyDataSource.java类,你可能会看到以下内容:

$ java -version 
java version "1.7.0"
Java(TM) SE Runtime Environment (build 1.7.0-b147)
Java HotSpot(TM) Server VM (build 21.0-b17, mixed mode)
$ javac -version
javac 1.7.0
$ javac MyDataSource.java 
MyDataSource.java:7: error: MyDataSource is not abstract and does not override abstract method getParentLogger() in CommonDataSource
public class MyDataSource implements DataSource {
       ^
1 error

你需要告诉编译器,你想使用为Java 1.6编写的源文件,生成Java 1.6字节码,并告诉它在哪里找到Java 1.6运行时JAR文件:

$ javac -source 1.6 -target 1.6 -bootclasspath <path to Java 1.6 JRE>/lib/rt.jar MyDataSource.java 
$ file MyDataSource.class 
MyDataSource.class: compiled Java class data, version 50.0 (Java 1.6)
$ javap MyDataSource
Compiled from "MyDataSource.java"
public class MyDataSource implements javax.sql.DataSource {
  public MyDataSource();
  public java.io.PrintWriter getLogWriter() throws java.sql.SQLException;
  public void setLogWriter(java.io.PrintWriter) throws java.sql.SQLException;
  public void setLoginTimeout(int) throws java.sql.SQLException;
  public int getLoginTimeout() throws java.sql.SQLException;
  public <T extends java/lang/Object> T unwrap(java.lang.Class<T>) throws java.sql.SQLException;
  public boolean isWrapperFor(java.lang.Class<?>) throws java.sql.SQLException;
  public java.sql.Connection getConnection() throws java.sql.SQLException;
  public java.sql.Connection getConnection(java.lang.String, java.lang.String) throws java.sql.SQLException;
}

6

首先添加所需的新方法,不要使用 @Override 注释。

如果您不介意支持新方法,请简单地抛出 SQLFeatureNotSupportedException 异常。

如果您正在包装另一个 DataSource 并希望支持 6 和 7,请使用反射调用这些方法(如果存在)。


0

另一种处理方法是更改PATH和JAVA_HOME的环境变量。

以下是在Mac上处理它的方法:

export JAVA_HOME=/System/Library/Frameworks/JavaVM.framework/Versions/1.6.0/Home

export PATH=/System/Library/Frameworks/JavaVM.framework/Versions/1.6.0/Home/bin/:$PATH


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接