Java 跨多个版本实现接口

Java 跨多个版本实现接口,java,interface,Java,Interface,我试图创建一个实现Java库接口的类。结果集必须是特定的,尽管特定的接口不应该与问题相关。(我需要在提供一些附加功能的常规结果集上添加一个层,但我希望“常规”函数能够通过,并且我有两个函数应该能够接受常规结果集或我的“增强”结果集。) 我的问题是:有没有一种方法可以做到这一点,这样类就可以在Java5和Java6中成功编译 Java 6的ResultSet接口中声明了许多函数,这些函数返回Java 5中未定义的对象。如果我包含这些函数,我的类将不会在Java5中编译,因为我引用的是未定义的类型。

我试图创建一个实现Java库接口的类。结果集必须是特定的,尽管特定的接口不应该与问题相关。(我需要在提供一些附加功能的常规结果集上添加一个层,但我希望“常规”函数能够通过,并且我有两个函数应该能够接受常规结果集或我的“增强”结果集。)

我的问题是:有没有一种方法可以做到这一点,这样类就可以在Java5和Java6中成功编译

Java 6的ResultSet接口中声明了许多函数,这些函数返回Java 5中未定义的对象。如果我包含这些函数,我的类将不会在Java5中编译,因为我引用的是未定义的类型。但是如果我没有包含这些函数,那么我的类就不会用Java6编译,因为我没有完全实现接口。我似乎陷入了某种两难境地。实际上,我并不需要这些函数中的任何一个——事实上,我的实现只是为所有这些函数抛出了一个“未实现”的异常

我们的一些程序员正在运行Java5,一些正在运行Java6。我们的生产环境是Java5。我想在一个更完美的世界里,我们都会运行相同的版本。但是,即使我可以修改我们的环境,使这个问题在这种情况下没有实际意义,这个问题肯定会出现在开源项目中。如果我修改代码以使用Java5,那么当我们迟早升级到Java6时,类就会中断,这看起来很烦人

更新

谢谢你的回答。我很希望有人会告诉我,“哦,如果你在这里加上这个注释或键入字母‘W’,它会神奇地工作。”我想没有这种运气

收到的所有答案(无论如何,截至本次更新)都很有价值,因此我对所有答案进行了投票,并将“最佳答案”奖授予了最能表达我观点的答案。:-)


我认为我真正的解决方案是放弃实现ResultSet的想法,而是创建一个新接口,其中只包含ResultSet中的函数,这些函数必须实现才能让beast工作。我觉得这在情感上并不令人满意,但似乎比其他选择要好。

我认为您应该做的是使用类将服务实现为JDK代理

它从1.3开始就存在了,所以它可以在所有版本中工作

语法是:

ResultSet rs = Proxy.newProxyInstance(
                   ResultSet.class.getClassloader(),
                   new Class[]{ResultSet.class},
                   new ResultSetInvocationHandler()
);
ResultSetInvocationHandler
将是的一个实现,它使用自定义逻辑截取一些方法并传递其他方法


这里有一个古老的例子。

啊,是的,JDBC向后兼容性的大崩溃。你有权为这一次释放两品脱朝太阳方向的固体咒语

我认为您没有任何方法可以为5和6使用完全相同的实现类。但是,您是否可以做如下操作:

abstract class JaysBaseSuperResultSet /* does not implement ResultSet */ {
    // all needed methods for java 5
}

class JaysSuperResultSetForJava6 extends JaysBaseSuperResultSet implements ResultSet {
    // all additional java 6 methods
}

class JaysSuperResultSetForJava5 extends JaysBaseSuperResultSetForJava5 implements ResultSet {
    // class body can be empty; compile this only with java 5
}
您需要有一个稍微奇怪的构建过程:我认为最简单的事情是使用6编译器编译JaysSuperResultSetForJava5以外的所有内容,但使用
-target 5
,然后使用5编译器单独编译该类,或者使用6编译器编译该类,但连接到5个库(这可以完成,而且可能更简单)

然后,您将需要一个工厂类来检测当前版本并创建相应具体类的实例

然后你可以把所有的东西都打包在一个罐子里

这听起来有用吗


编辑:您可以使用三个类而不是四个类来完成此操作。

与其创建实现
ResultSet
的类,不如将
ResultSet
包装到一个新类中

一个警告:考虑使用泛型使其返回正确的子接口<代码>结果集< /代码>:

public class MyWrapper<T extends ResultSet> {
    T myResultSet;

    public MyWrapper(T myResultSet) {
        this.myResultSet = myResultSet;
    }

    public T getResultSet() {
        return myResultSet;
    }

    public void setResultSet(T myResultSet) {
        this.myResultSet = myResultSet;
    }

}
公共类MyWrapper{
T myResultSet;
公共MyWrapper(T myResultSet){
this.myResultSet=myResultSet;
}
公共T getResultSet(){
返回myResultSet;
}
公共无效集合结果集(T myResultSet){
this.myResultSet=myResultSet;
}
}
(注意,我还没有对此进行测试)

注:

从表面上看,创建一个实现
ResultSet
的新类可能听起来是个好主意,但由于
ResultSet
已经有了自己的子接口
RowSet
,而该子接口又有了自己的子接口
JdbcRowSet
,因此很快就会退化为疯狂。。。在这棵树的最后是作为数据库JDBC驱动程序一部分的实际对象。

我想代理建议是最好的答案,但让我添加两个注意事项:

首先,通过向接口添加方法来更改公共API,这些方法依赖于以前版本中不存在的类,这通常是一个令人憎恶的问题(实现该接口的开发人员,就像你自己一样,不可避免地会带来麻烦)。这种令人憎恶的现象很少见,第二个考虑因素削弱了它:


当然,JDBCAPI是一个公共API。但不是很公开。我的意思是,通常它的接口只能由JDBC驱动程序提供者实现。在这种情况下,对于不同的JDBC版本有不同的实现是可以忍受的。我的目的是不鼓励您实现一个实现/包装ResultSet的类,除非是非常特定(低级)的情况;在典型情况下,JDBC驱动程序实例化ResultSet,DAO方法使用它,但从不返回它。

这将破坏静态类型安全,并涉及编写大量样板文件。它容易出错,效率低下。但它肯定会起作用@Tom Anderson这会破坏静态类型的安全性,我知道,这就是我不喜欢它的原因