参数化类“ABC”的原始使用

Raw use of parameterized class 'ABC'

提问人:QuirkyBit 提问时间:1/20/2021 最后编辑:QuirkyBit 更新时间:1/20/2021 访问量:3892

问:

我有以下界面:

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

我还忘了提到,由于作业被序列化到数据库,因此发生了一些注入魔术:

    /**
     * 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);
    }

我已经接受了 Vershinin @Andrew回答,因为他让我走上了正确的思想轨道。

Java 泛型类型 擦除 抑制警告原始 类型

评论

0赞 NomadMaker 1/20/2021
ABC 在哪里用作参数化类(或其他任何与此相关的类)?
0赞 QuirkyBit 1/20/2021
@NomadMaker,是的,最初,在这种情况下,ABC 是 .我想参数化自己也是有意义的。AsynchronousJobRunnerAsynchronousJob

答:

2赞 Andrew Vershinin 1/20/2021 #1

我认为,你可以采用这个递归声明: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? extends AsynchronousJobjobRunnerClass

评论

0赞 QuirkyBit 1/20/2021
解决方案最终与您提出的略有不同(并且递归较少),但您的回答让我走上了正确的轨道。
0赞 Andrew Vershinin 1/20/2021
@QuirkyBit 如果你不介意分享,你最终得到了什么?
0赞 QuirkyBit 1/20/2021
我在阅读您的答案后沉思了一下这个问题。
1赞 Andrew Vershinin 1/20/2021
@QuirkyBit,是的,这有效,但正如我所提到的,您不会对运行器作业类型进行编译时错误检查。
0赞 QuirkyBit 1/20/2021
是的,我可能需要对我需要更改的代码和类进行更长的思考。您的回答确实有帮助,再次感谢您!