【问题标题】:Update a New Java Library Without Affecting Existing Systems在不影响现有系统的情况下更新新的 Java 库
【发布时间】:2016-01-18 18:11:12
【问题描述】:

假设我创建了一个库并将其分发到整个公司并在每个项目中使用。

库是 1.0,假设我有一个接口 Componentble。

public interface Componentble {
    public String getComponentId();
}

我做了一些修改并更新了 1.1 的 jar 和 Componentble 接口修改如下。

public interface Componentble {
    public String getComponentId();
    public Componentble getParentComponent();
}

当这个 jar 应用到现有项目时,它会给出编译错误。 我想做这个修改并更新 jar。但情况是它不应该影响现有项目。

最好的方法是什么。 创建 ComponentbleV2 并在新项目中要求使用 ComponentbleV2 而不是 Componentble。

或者创建自定义类加载器并做需要的事情。

我想要的答案是我们如何进行 api 修改并应用于现有项目,而不会对现有项目产生任何编译问题。

【问题讨论】:

  • 创建新界面。弃用旧的,但允许人们继续使用它(为了向后兼容)。这可能需要在某些地方进行一些修改。在几个版本中,删除旧界面。

标签: java api class interface classloader


【解决方案1】:

一种方法是使用@Deprecated 注释旧接口中的方法,并在 javadocs 中解释要改用什么。

有关这方面的更多文档,请参阅Oracle documentation on @Deprecated

为了向后兼容,您现在必须保留这两个接口。这可能需要在接口的实现中进行一些定制。过一段时间,在您使用了几个版本之后,您可以删除旧界面。

确保正确记录您已弃用的方法,以便使用它的开发人员知道要改用什么以及在哪里找到它。

【讨论】:

    【解决方案2】:

    从 Java 8 开始,您可以为接口方法提供默认实现。它们正是为您的问题而发明的。

    public interface Componentble {
        public String getComponentId();
        public default Componentble getParentComponent() {
            return null;
        }
    }
    

    【讨论】:

      【解决方案3】:

      两个接口

      没有必要弃用旧版本。 创建两个接口,新接口扩展旧接口。

      public interface Componentble {
          public String getComponentId();
      }
      

      public interface ComponentbleWithStructure extends Componentble {
          public Componentble getParentComponent();
      }
      

      实现一个接口应该意味着实现者遵循该接口的约定。

      这样你就知道任何实现这两者的类都已被重新设计以适应新合同,而只实现旧合同的类仍然遵循旧合同。

      使用示例:

      void doStuff(Componentble component){
          if(component instanceof ComponentbleWithStructure){
              Componentble parent=((ComponentbleWithStructure)component).getParentComponent();
              ....
          }
          ....
      }
      

      默认实现

      java8 方式仅在可以使用旧接口表达新功能时才有用。例如,如果您有一个可以查找父母的服务,您可以编写。

      public interface Componentble {
          public String getComponentId();
          public default Componentble getParentComponent() {
              return ParentLookUpService.getParent(getComponentId());
          }
      }
      

      这样你就会知道所有使用新接口的实例都有一个正确的实现。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2021-12-06
        • 1970-01-01
        • 2021-09-10
        • 2015-12-03
        • 1970-01-01
        • 1970-01-01
        • 2014-03-20
        • 1970-01-01
        相关资源
        最近更新 更多