java - 参数化类 'ABC' 的原始使用

标签 java generics type-erasure suppress-warnings raw-types

我有以下界面:

public interface AsynchronousJobRunner<T extends AsynchronousJob> extends Runnable {
    public void kill();
    public void addJobExecutionListener(JobExecutionListener listener);
    public void removeJobExecutionListener(JobExecutionListener listener);
    public AsynchronousJobRunner withJob(T job);
}

AsynchronousJob 是一个抽象类,可以通过以下抽象方法扩展以表示其他作业:

public abstract class AsynchronousJob implements JSONSerializable, HasId {...}

    /**
     * Returns the class of the {@link AsynchronousJobRunner} that runs this type of job.
     * @return The appropriate class of the job runner for this class.
     */
    public abstract Class<? extends AsynchronousJobRunner> jobRunnerClass();

我还有以下 ExportJob,它扩展了基类并具有以下签名和方法:

public class ExportJobRunner extends BaseJobRunner<ExportJob> { ...}

    @Override
    public Class<? extends AsynchronousJobRunner> jobRunnerClass() {
        return ExportJobRunner.class;
    }

两个 jobRunnerClass() 方法都有 Raw use of parameterized class 'AsynchronousJobRunner' 警告。

使警告消失的简单解决方案是:

public abstract Class<? extends AsynchronousJobRunner<?>> jobRunnerClass();


@Override
public Class<? extends AsynchronousJobRunner<?> jobRunnerClass() {
    return ExportJobRunner.class;
}

但是什么是正确的解决方案,为什么/如何?

编辑:

我最终只是将界面的代码更改为:

public interface AsynchronousJobRunner<T extends AsynchronousJob<T>> extends Runnable {
    void kill();
    void addJobExecutionListener(JobExecutionListener listener);
    void removeJobExecutionListener(JobExecutionListener listener);
    AsynchronousJobRunner<T> withJob(T job);
}

AsynchronousJob 类的更改:

public abstract class AsynchronousJob<T> implements JSONSerializable, HasId { ...
 /**
     * Returns the class of the {@link AsynchronousJobRunner} that runs this type of job.
     * @return The appropriate class of the job runner for this class.
     */
    public abstract Class<? extends AsynchronousJobRunner<? extends AsynchronousJob<T>> jobRunnerClass();

}

ExportJob 类:

public public class ExportJob extends AsynchronousJob<ExportJob> {...
    @Override
    public Class<? extends AsynchronousJobRunner<? extends AsynchronousJob<ExportJob>>> jobRunnerClass() {
        return ExportJobRunner.class;
    }
}

ExportJobRunner 类保持不变。

我还忘了说,由于作业被序列化到数据库中,所以存在一些注入(inject)魔法:

    /**
     * Instantiates an {@link AsynchronousJobRunner} instance for the provided job.
     * <p>
     * In order for the creation of the runner to succeed, the {@link AsynchronousJob#jobRunnerClass()}
     * method of the job must specify the appropriate class for its runner.
     *
     * @param job job to create runner for
     * @return job runner configured for the specified {@code job} parameter
     */
    private <T extends AsynchronousJob<T>> AsynchronousJobRunner<T> createJobRunner(T job) {
        return ((AsynchronousJobRunner<T>)injector.getInstance(job.jobRunnerClass())).withJob(job);
    }

我接受了@Andrew Vershinin 的回答,因为他让我走上了正确的思路。

最佳答案

我认为,您可以使用 AsynchronousJob 的递归声明:

public abstract class AsynchronousJob<T extends AsynchronousJob<T>> 
    implements JSONSerializable, HasId {

    public abstract Class<? extends AsynchronousJobRunner<T>> jobRunnerClass();
//...
}

不要忘记相应地更新 AsynchronousJobRunner 定义:

public interface AsynchronousJobRunner<T extends AsynchronousJob<T>> //...

然后,在您的作业类中,您可以在返回类型中使用该类本身:

public class ExportJob extends AsynchronousJob<ExportJob> {
    @Override
    public Class<? extends AsynchronousJobRunner<ExportJob>> jobRunnerClass() {
        return ExportJobRunner.class;
    }
}

通过这种方式可以确保类型一致性:T 类型的作业返回运行器类型,运行此类作业的类型 - 使用 无法确保这一点?在 jobRunnerClass 签名中扩展 AsynchronousJob,因为您可以返回任何运行器类型并且它会编译。

关于java - 参数化类 'ABC' 的原始使用,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/65796415/

相关文章:

Java 和类型删除

java - Thymeleaf - 如何删除字符串的最后一个字符

java - 无法在 GAE 上部署 - 使用 vaadin-gwt-polymer-elements 1.7.0.0 的应用程序

java - KDB 到 JKS keystore 转换

generics - 无法为通用结构实现 Into 特征

java - 为什么java允许我将一个Box(原始类型)添加到List<Box<?扩展项目>>

java - 通用方法类型安全

java - 在 GWT 中创建 JSON 字符串的更好方法?

generics - 将通用结构视为特征对象

scala - 如何在 Scala 中获取泛型函数的实际类型?