从 JDK8 升级到 JDK11 后出现奇怪的 java.lang.InstantiationException 和 java.lang.NoSuchMethodException
Weird java.lang.InstantiationException and java.lang.NoSuchMethodException after upgrading from JDK8 to JDK11
我有以下代码可以在 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
有人可以解释一下不满意的地方以及如何解决吗?
Could somebody please explain what it's unhappy about and how to fix it?
将 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);
}
};
}
}
... the following code which builds and works fine under JDK8
我认为问题出在捕获机制上,该机制与 E
泛型类型不兼容,并且与 JLS 8.1.2. Generic Classes and Type Parameters:
处的语句有关
It is a compile-time error if a generic class is a direct or indirect subclass of Throwable (§11.1.1).
This restriction is needed since the catch mechanism of the Java Virtual Machine works only with non-generic classes.
坦率地说,这是一个猜测,我不知道为什么这可以用 JDK 11 重现而不是 JDK 8 - 这很奇怪。
我希望我至少帮助你解决了这个问题。
我有以下代码可以在 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
有人可以解释一下不满意的地方以及如何解决吗?
Could somebody please explain what it's unhappy about and how to fix it?
将 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);
}
};
}
}
... the following code which builds and works fine under JDK8
我认为问题出在捕获机制上,该机制与 E
泛型类型不兼容,并且与 JLS 8.1.2. Generic Classes and Type Parameters:
It is a compile-time error if a generic class is a direct or indirect subclass of Throwable (§11.1.1).
This restriction is needed since the catch mechanism of the Java Virtual Machine works only with non-generic classes.
坦率地说,这是一个猜测,我不知道为什么这可以用 JDK 11 重现而不是 JDK 8 - 这很奇怪。
我希望我至少帮助你解决了这个问题。