繁体   English   中英

有没有办法在 Java 中调用延迟实现?

[英]Is there a way to call a deferred implementation in Java?

我不确定这里的术语是否完全正确。

我有一个 class 和一些 static 方法,这些方法在很久以前编写的一些库代码中被其他几个类调用。

class 与 static 方法(由其他几个类调用)具有对第三方 class 的引用,该第三方现在具有版本 2。

有没有办法我可以编写这个 class 来执行类似“当调用这个 static 方法时,你需要调用一些东西来查看你应该使用哪个版本的库”?

这样,当我将此库代码作为 jar 文件拉入新项目时,我可以在每个项目中包含一些内容,这些内容将告诉库中的 class 使用特定版本的 static 方法。

这样我就不需要为我的库中的每个类提供 version1 和 version2。

我是否在延期的正确轨道上?

lambda function 也许?

您的问题有几种不同的解决方案,具体取决于您的第三方库的更改方式。

我假设您的第三方 class 的第 2 版具有您需要的第 1 版中没有的新方法?

最简单的解决方案是针对库的版本 2 实施 class,但处理LinkageError (或更具体的子类,例如NoSuchMethodError ),如果捕获到这些错误,则恢复到版本 1 调用。 如果它是完全不同的 class,您也可以通过处理NoClassDefFoundError来处理。

或者,如果性能不重要,您也可以使用反射

有点。 Java 不会加载 class ,除非您确实需要它。 这意味着您可以执行以下操作:

public String getFoo() {
  switch (versionRequired()) {
    case 1: return new Version1Impl().getFoo();
    default: return new Version2Impl().getFoo();
  }
}

boolean versionRequired() {
  // figure out which version is needed here.
  // if you're having trouble with this, you can use `Class.forName` to check
  // if a certain type is even available. Worst case scenario, you can
  // ask a class for its own bytecode and hash that. This is very tricky.
  return 1;
}

private static class Version1Impl {
  public String getFoo() {
    return new UseSomethingFromV1().getFoo();
  }
}

这里奇怪的“重定向到内部类”的线索是内部 class 在切换分支被采用之前不会被加载,只要例如Version2Impl永远不会加载,你也永远不会得到它所指的错误到不存在的 class (因为它是为该库的 v2 设计的,但只有 v1 可用)。


注意:关于那个版本检测方案:散列类的问题是 class 可能在 2 个主要版本之间没有变化(你希望它不同,但它不会)。 或者,另一方面,一个次要的版本更新可能已经改变了它(它现在不同了,但你不希望它如此)。 一个解决方案是 hash 很多类,这有助于第一种情况(您想注意更改),但会使第二种情况更糟。 您可以使用例如try (InputStream in = String.class.getResourceAsStream("String.class")) { - 适用于任何 class。 通过哈希器折腾这个输入流(如果你不知道如何搜索 web,这是一个非常常见的任务,有很多教程可以找到)。

许多库都有一种受支持的方式来询问它们是什么版本,但没有标准,因此请查看该库的文档。

现在,我已经创建了一个基于文件的解决方案。 在 class 路径上查找文件,如果存在,请从文件中读取指示的版本。 如果没有文件,请使用默认(原始)版本。

package com.nach.core.util.fhir.parser;

import java.io.File;

import org.hl7.fhir.instance.model.api.IBaseResource;

import com.nach.core.util.file.FileUtil;

import ca.uhn.fhir.context.FhirContext;
import ca.uhn.fhir.parser.IParser;
import lombok.extern.slf4j.Slf4j;

@Slf4j
public class FhirJsonParser {

    private static final FhirContext CTX;
    
    private static final IParser PARSER;

    static {
        File fhirContextFile = FileUtil.getFile("/fhir-context.txt");
        if (fhirContextFile != null && fhirContextFile.exists()) {
            String fhirContext = FileUtil.getAsString(fhirContextFile).trim();
            if ("Dstu3".equals(fhirContext)) {
                log.info("USING DSTU3 FOR FHIR PARSING");
                CTX = FhirContext.forDstu3();
            } else if ("R4".equals(fhirContext)) {
                log.info("USING R4 FOR FHIR PARSING");
                CTX = FhirContext.forR4();
            } else {
                CTX = FhirContext.forDstu3();
            }
        } else {
            CTX = FhirContext.forDstu3();
        }
        PARSER = CTX.newJsonParser();
    }

    /**
     * Generate a class from a json string.
     */
    public static <T extends IBaseResource> T parse(String jsonString, Class<T> cls) {
        try {
            IParser parser = CTX.newJsonParser();
            parser.setStripVersionsFromReferences(false);
            CTX.getParserOptions().setStripVersionsFromReferences(false);
            IParser jsonParser = CTX.newJsonParser();
            T rtn = jsonParser.parseResource(cls, jsonString);
            return rtn;
        } catch (Exception exp) {
            throw new RuntimeException(exp);
        }
    }

    /**
     * Generate a json string from a class.
     */
    public static String serialize(IBaseResource resource) {
        String rtn = PARSER.encodeResourceToString(resource);
        return rtn;
    }
    
}

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM