【问题标题】:Weird java.lang.InstantiationException and java.lang.NoSuchMethodException after upgrading from JDK8 to JDK11从 JDK8 升级到 JDK11 后出现奇怪的 java.lang.InstantiationException 和 java.lang.NoSuchMethodException
【发布时间】:2020-05-22 18:20:40
【问题描述】:

我有以下代码在 JDK8 下构建和工作正常:

@FunctionalInterface
public interface ThrowingFunction<T, R, E extends Throwable> {
    R apply(T t) throws E;

    static <T, R, E extends Throwable> Function<T, R> unchecked (ThrowingFunction<T, R, E> function) {
        return t -> {
            try {
                return function.apply(t);
            }
            catch (Throwable e) {
                throw new RuntimeException(e);
            }
        };
    }
}

还有:

@Component
public class CronJobDuplicationCheckStrategiesRegistry {

    private final Map<String, Set<CronJobDuplicationCheckStrategy>> duplicationStrategies;

    CronJobDuplicationCheckStrategiesRegistry(final CronJobsRegistry cronJobsRegistry) {
        duplicationStrategies = cronJobsRegistry.get()
            .stream()
            .collect(Collectors.toMap(
                clazz -> clazz.getName(),
                ThrowingFunction.unchecked(
                    clazz -> clazz.getDeclaredConstructor()
                                  .newInstance()
                                  .getDuplicationStrategies())));
    }

    public Set<CronJobDuplicationCheckStrategy> get(String jobClass) {
        return duplicationStrategies.get(jobClass);
    }
}

此代码在JDK11下编译失败,报错如下:

[ERROR] Failed to execute goal org.apache.maven.plugins:maven-compiler-plugin:3.3:compile (default-compile) on project cron-api: Compilation failure: Compilation failure: 
[ERROR] /java/org/foo/src/main/java/org/foo/jobs/CronJobDuplicationCheckStrategiesRegistry.java:[26,120] unreported exception java.lang.NoSuchMethodException; must be caught or declared to be thrown
[ERROR] /java/org/foo/src/main/java/org/foo/src/main/java/org/foo/cron/jobs/CronJobDuplicationCheckStrategiesRegistry.java:[27,109] unreported exception java.lang.InstantiationException; must be caught or declared to be thrown

有人可以解释一下它的不满意之处以及如何解决它吗?

【问题讨论】:

    标签: java generics exception lambda java-11


    【解决方案1】:

    有人可以解释一下它的不满意之处以及如何解决它吗?

    E 泛型类型替换为实际的Throwable

    @FunctionalInterface
    public interface ThrowingFunction<T, R> {
        R apply(T t) throws Throwable;
    
        static <T, R> Function<T, R> unchecked(ThrowingFunction<T, R> function) {
            return t -> {
                try {
                    return function.apply(t);
                } catch (Throwable e) {
                    throw new RuntimeException(e);
                }
            };
        }
    }
    

    ...以下代码在 JDK8 下构建和工作正常

    我认为问题出在捕获机制上,该机制与E 泛型类型不兼容,并且与JLS 8.1.2. Generic Classes and Type Parameters 处的声明有关:

    如果泛型类是 Throwable 的直接或间接子类(§11.1.1)

    这个限制是必要的,因为 Java 虚拟机的 catch 机制只适用于非泛型类。

    坦率地说,这是一个猜测,我不知道为什么这可以用 JDK 11 而不是 JDK 8 重现 - 这很奇怪。

    我希望我至少帮助你解决了这个问题。

    【讨论】:

    • 正如我所说,我相信存在某种关系,但这仍然是我的猜测。最好等待一个更合格和更完整的答案,并且不接受留下这个未解决的问题(取决于你,这取决于你是否对我提供的小问题感到满意)。不过,我很高兴你能找到它。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-10-25
    • 2013-08-21
    相关资源
    最近更新 更多