Java 如何将方法与泛型和继承一起使用?

Java 如何将方法与泛型和继承一起使用?,java,generics,reflection,Java,Generics,Reflection,具有以下类别: public interface Step<C extends Config> { void setConfig(C config); } 及 及 及 及 及 因此,应用程序需要动态实例化Step子类对象,相应地设置配置并运行该步骤,如下所示 List<Config> configs = loadConfigsFromRepository(); // contain all subtypes of Config for (Config conf: c

具有以下类别:

public interface Step<C extends Config> {
  void setConfig(C config);
}

因此,应用程序需要动态实例化Step子类对象,相应地设置配置并运行该步骤,如下所示

List<Config> configs = loadConfigsFromRepository(); // contain all subtypes of Config
for (Config conf: configs) {
  Step<? extends Config> step = conf.type().getDeclaredConstructor().newInstance();

  step.setConfig(conf); // compiler complains

}
错误消息:


的方法setConfigcapture8?扩展类型中的配置 步骤不适用于 参数配置

查看文档,在这种情况下,Java看起来不友好:

克服此代码限制步骤的可能解决方案有哪些。setConfigconf

编辑[解决方案]


代码可在此处查看:

您的方法不完全正确。我建议你在真正需要之前不要使用反射

请注意,所有这些实现都应该隐藏在包中,并且只有Step接口应该是公共的。配置实现保存了创建步骤类所需的所有数据,所以只需将其委托给该类即可

package steps

public interface Step<C extends Config> {
  void run(Context context);
}

private final class ValidationStep implements Step<ValidationConf> {
    private final ValidationConf config;
    
    public ValidationStep(ValidationConf config) {
        this.config = config;
    }
}

private class ProcessStep implements Step<ProcessConf> {
    private final ProcessConf config;
    
    public ValidationStep(ProcessConf config) {
        this.config = config;
    }    
}

public interface Config {
    
    Step<? extends Config> createStep();
  
}

private class ValidationConf implements Config {
    
    public Step<ValidationConf> createStep() {
        return new ValidationStep(this);
    }
}

private class ProcessConf implements Config {
    public Step<ValidationConf> createStep() {
        return new ProcessConf(this);
    }
}

package foo

List<Config> configs = loadConfigsFromRepository();

for (Config config : loadConfigsFromRepository()) {
  config.createStep().run(context);
}

你的方法不完全正确。我建议你在真正需要之前不要使用反射

请注意,所有这些实现都应该隐藏在包中,并且只有Step接口应该是公共的。配置实现保存了创建步骤类所需的所有数据,所以只需将其委托给该类即可

package steps

public interface Step<C extends Config> {
  void run(Context context);
}

private final class ValidationStep implements Step<ValidationConf> {
    private final ValidationConf config;
    
    public ValidationStep(ValidationConf config) {
        this.config = config;
    }
}

private class ProcessStep implements Step<ProcessConf> {
    private final ProcessConf config;
    
    public ValidationStep(ProcessConf config) {
        this.config = config;
    }    
}

public interface Config {
    
    Step<? extends Config> createStep();
  
}

private class ValidationConf implements Config {
    
    public Step<ValidationConf> createStep() {
        return new ValidationStep(this);
    }
}

private class ProcessConf implements Config {
    public Step<ValidationConf> createStep() {
        return new ProcessConf(this);
    }
}

package foo

List<Config> configs = loadConfigsFromRepository();

for (Config config : loadConfigsFromRepository()) {
  config.createStep().run(context);
}

去掉通配符。你不需要它

Step<Config> step = (Step<Config>) conf.type().getDeclaredConstructor().newInstance();

去掉通配符。你不需要它

Step<Config> step = (Step<Config>) conf.type().getDeclaredConstructor().newInstance();
由于Step.setConfig是一个“使用者”,解决“不适用于参数配置”错误的一种方法是

由于Step.setConfig是一个“使用者”,解决“不适用于参数配置”错误的一种方法是



编译器抱怨的确切含义是什么?错误消息是什么?类型步骤中扩展配置的方法setConfigcapture8不适用于参数ConfigWhat is Context in Step.runContext ctx?它神奇地再次出现在for循环中:“Step.runContext”“。它是如何实现的?你没有说清楚。另外,你定义了一个泛型类:”“Step”。但是在Config中,你指定了使用它的方法,以使用原始类型:”“class”…它与这里的问题无关。。。“-在这种情况下,您是否考虑过将其从问题中删除?编译器抱怨的确切含义是什么?错误消息是什么?类型步骤中的方法setConfigcapture8扩展配置不适用于参数ConfigWhat is Context in Step.runContext ctx?它神奇地再次出现在for循环中:“step.runcontext”。它是如何实现的?您没有明确说明。此外,您定义了一个泛型类:“step”。但在Config中,您指定了使用它的方法,以使用原始类型:“class”…它与此处的问题无关。。。“-在这种情况下,您是否考虑过将其从问题中删除?我得到一个错误:类型不匹配:无法从capture7转换?将步骤扩展到步骤。我明白了。这是因为您从类型到配置获得了一个粒度类型。此时,您可以将其强制转换。我已更新了我的答案。啊,好吧!现在使用强制转换,我只收到一条警告消息:Type。”安全性:从?的capture7未经检查的强制转换将一步一步扩展到另一步。让我运行并检查它是否有效。从给定的内容来看,不管它是什么类型的配置,所以可以放弃到配置。乔治,你同意还是不同意,如果可能,最好避免显式强制转换?在我看来,应用PECS原则是一个更好的方法。针对@danieldestro的错误提供了更安全的类型解决方案。公平地说,这是吗?我得到了一个错误:类型不匹配:无法从capture7转换?将一步扩展到另一步。我明白了。这是因为您从类型到配置都获得了一个粒度类型。此时,您可以强制转换它。我已经更新了我的答案。啊,好吧!现在通过强制转换,我只收到一条警告消息:Type safety:Unchecked cast from capture7 of?将一步一步扩展到另一步。让我运行并检查它是否有效。从给定的内容来看,它是什么类型的配置并不重要,因此可以放弃配置。乔治,你同意还是不同意,如果可能,最好避免显式强制转换?在我看来,应用PECS原则是一个更好的选择r i.e.针对@Danieldstro的错误提供了更安全的类型解决方案。这是否公平?如果我这样做,我会得到:类型不匹配:无法从capture8转换为?扩展步骤到步骤…我得到:类型不匹配:无法从capture8转换为?扩展步骤到步骤Yep。我尝试过了,效果很好。谢谢!太棒了Danieldstro!我很高兴能帮助你。更多r最近@Nikolas的答案刚刚被接受并被投票表决。这个答案基本上与我几个小时前向你提出的答案相同。你同意或不同意我的答案比你问题的其他两个答案更容易接受吗?如果你不同意,那么你能让我知道吗?请问:我的答案有哪些改进为了
您是否已将其标记为已接受?为什么这三个你都不能接受?TIA.Hi@dedupler-我想说这两种解决方案都令人满意,工作正常。我同意您的解决方案在我看来可能更优雅一些,避免了强制转换,但两者都只是合成糖。如果我这样做,我得到:类型不匹配:无法从的capture8转换?将步骤扩展到步骤“I get:类型不匹配:无法从的capture8转换?”?将步骤扩展到步骤Yep。我试过了,效果很好。谢谢真棒的丹尼尔斯特罗!我很高兴能帮助你。最近,@Nikolas的一个回答刚刚被接受并被投票通过。这个答案与我几个小时前向你们提出的答案基本相同。你同意还是不同意我的回答比你问题的其他两个答案更容易接受?如果你不同意,那么请让我知道:为了让你将我的答案标记为已接受,我的答案如何改进?为什么这三个你都不能接受?TIA.Hi@dedupler-我想说这两种解决方案都令人满意,工作正常。我同意你的解决方案在我看来可能更优雅一点,避免铸造,但两者都只是合成糖。
List<Config> configs = loadConfigsFromRepository(); // contain all subtypes of Config
for (Config conf: configs) {
  Step<? extends Config> step = conf.type().getDeclaredConstructor().newInstance();

  step.setConfig(conf); // compiler complains

}
package steps

public interface Step<C extends Config> {
  void run(Context context);
}

private final class ValidationStep implements Step<ValidationConf> {
    private final ValidationConf config;
    
    public ValidationStep(ValidationConf config) {
        this.config = config;
    }
}

private class ProcessStep implements Step<ProcessConf> {
    private final ProcessConf config;
    
    public ValidationStep(ProcessConf config) {
        this.config = config;
    }    
}

public interface Config {
    
    Step<? extends Config> createStep();
  
}

private class ValidationConf implements Config {
    
    public Step<ValidationConf> createStep() {
        return new ValidationStep(this);
    }
}

private class ProcessConf implements Config {
    public Step<ValidationConf> createStep() {
        return new ProcessConf(this);
    }
}

package foo

List<Config> configs = loadConfigsFromRepository();

for (Config config : loadConfigsFromRepository()) {
  config.createStep().run(context);
}
Step<Config> step = (Step<Config>) conf.type().getDeclaredConstructor().newInstance();
…  
List< ? extends Config > configs = loadConfigsFromRepository( ); // contain all subtypes of Config
  
for ( Config conf: configs ) {
    Step< ? super Config > step = conf.type( ).getDeclaredConstructor( ).newInstance( );

      step.setConfig( conf ); // *set* makes Step a „consumer“
}
…
static List< ? extends Config > loadConfigsFromRepository(){ 
    
    return of( new ValidationConf( ), new ProcessConf( ) );        
}