Java - 泛型通配符问题

标签 java generics bounded-wildcard

我的目标很简单。我有一个SetInterface<T> :

public interface SetInterface<T>
{   
    public T duplicateSet();
}

然后我还有一个 ExerciseInterface <T extends SetInterface<?>>

public interface ExerciseInterface <T extends SetInterface<?>>
{   
    public T getSet(int pos);
    public void addSet(T set);
}

到目前为止一切都很顺利。

问题出现在我尝试创建一个包含不同类的通用集合(Generic Collection),而这些类都实现了ExerciseInterface。

我对泛型相当陌生,我一直认为我已经解决了一些问题,但我所做的只是插入错误。

这个问题几乎可以通过我的 addA() 来总结。和addB()方法

public class Workout {  

    private String name;
    private List <? extends ExerciseInterface<SetInterface<?>>> exerciseList;

// Constructor
public Workout(String name) 
{
    this.name = name;
    exerciseList = new ArrayList<ExerciseInterface<SetInterface<?>>>();
}   

public String getName() {
        return name;
    }

public void setName(String name) {
        this.name = name;
    }

public void addExerciseA(ExerciseInterface<SetInterface<?>> exercise {
        exerciseList.add(exercise);
    }

public <T extends ExerciseInterface<SetInterface<?>>> void addExerciseB(T  exercise {
        exerciseList.add(exercise);
    }

public ExerciseInterface<SetInterface<?>> getExercise(int pos) {
        return exerciseList.get(pos);
    }
}

第一个add()给出以下错误..

The method add(capture#2-of ? extends ExerciseInterface<SetInterface<?>>) in the type List<capture#2-of ? extends ExerciseInterface<SetInterface<?>>> is not applicable for the arguments (ExerciseInterface<SetInterface<?>>)

第二个add()给出这个错误..

The method add(capture#2-of ? extends ExerciseInterface<SetInterface<?>>) in the type List<capture#2-of ? extends ExerciseInterface<SetInterface<?>>> is not applicable for the arguments (ExerciseInterface<SetInterface<?>>)

重申一下,我有一个不同类型的 Set 实现的 SetInterface。

我还有不同的练习来反射(reflect)这些组合。例如:

BodyWeightExercise implements <SetInterface<BodyweightSet>>

WeightsExercise implements <SetInterface<WeightsSet>>

所以我的目标是拥有不同练习的集合以及允许我添加到该集合的方法。

任何帮助将不胜感激,我已经为此掉了几根头发。

干杯。

编辑:如果这不可行,任何指向更可行方向的指针将不胜感激。

编辑2:我将列表更改为 List <ExerciseInterface<SetInterface<?>>> exerciseList;并且 add() 方法上的错误都消失了。

但是,使用此测试代码..

WeightsSet weightsSet = new WeightsSet();       
WeightsExercise weightsExercise = new WeightsExercise();

weightsExercise.addSet(weightsSet);

Workout workout = new Workout("Wok");
workout.addExerciseA(weightsExercise);     <-- ERROR

我正在尝试将 WeightsExercise 添加到锻炼列表中,但现在收到此错误..

Bound mismatch: The generic method addExerciseB(T) of type Workout is not applicable for the arguments (WeightsExercise). The inferred type WeightsExercise is not a valid substitute for the bounded parameter <T extends ExerciseInterface<SetInterface<?>>>

编辑3:扩展ExerciseInterface和SetInterface的示例类(具体方法也在上面的接口(interface)中更新)

public class WeightsExercise implements ExerciseInterface<SetInterface<WeightsSet>>
{
@Override
public SetInterface<WeightsSet> getSet(int pos)    {return null;}

@Override
public void addSet(SetInterface<WeightsSet> set)    {}  
}

public class WeightsSet implements SetInterface<WeightsSet>
{
@Override
public WeightsSet duplicateSet()    {return null;}  
}

已解决:此解决方案似乎正确包含了所有内容。

public class Workout
{   
private String name;
private List <ExerciseInterface<? extends SetInterface<?>>> exerciseList;

// Constructor
public Workout(String name) 
{
    this.name = name;
    exerciseList = new ArrayList<ExerciseInterface<? extends SetInterface<?>>>();
}   

public String getName()                                                                         {return name;}
public void setName(String name)                                                                {this.name = name;} 
public void addExerciseA(ExerciseInterface<? extends SetInterface<?>> exercise)                 {exerciseList.add(exercise);}
public ExerciseInterface<? extends SetInterface<?>> getExercise(int pos)                        {return exerciseList.get(pos);}

}

最佳答案

您应该将列表声明更改为:

List<ExerciseInterface<SetInterface<?>>> exerciseList;

当您使用上限通配符时(我认为您在这里并不真正需要),除了 null 以及之前从列表中获取的元素之外,您无法向列表中添加任何内容。

那是因为,您不确切知道它实际引用的具体参数化类型的列表。例如: List<? extends CharSequence> 可以引用 ArrayList<String>ArrayList<StringBuffer> 。因此,您无法向该列表添加任何内容,因为它不是类型安全的。您可能会将 StringBuffer 对象添加到 ArrayList<String> ,这将在运行时失败。

<小时/>

更新后:

我猜你正在尝试创建一个 parallel class hierarchy ,并且搞砸了。也许,您希望 ExerciseInterface 看起来像:

// Notice the use of `T` in `SetInterface<T>` instead of `SetInterface<?>`
interface ExerciseInterface<T extends SetInterface<T>> {
    SetInterface<T> getSet(int pos);
    void addSet(SetInterface<T> set);
}

然后你的类 WeightsExercise 将被修改如下:

class WeightsExercise implements ExerciseInterface<WeightsSet> {
    @Override
    public SetInterface<WeightsSet> getSet(int pos)    {return null;}

    @Override
    public void addSet(SetInterface<WeightsSet> set)    {}  
}

您还需要将 Workout 类设为通用,如下所示:

public class Workout<U extends SetInterface<U>, T extends ExerciseInterface<U>> {

}

然后将 ExerciseInterface<SetInterface<?>> 类中所有出现的 ExerciseInterface<U> 替换为 Workout

并创建 Workout 的实例,如下所示:

Workout<WeightsSet, WeightsExercise> workout = new Workout<>("Wok");
workout.addExerciseA(weightsExercise);

在我看来,这才是正确的设计。

<小时/> 推荐帖子:

引用文献:

关于Java - 泛型通配符问题,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/18495153/

相关文章:

java.util.MissingResourceException : Can't find resource for bundle java. util.PropertyResourceBundle,键

javascript - 如何从 <select> 检索值并将其放入隐藏的 JSTL 中

java - 是否可以从 jax-rs 获取 TLS 客户端身份验证证书信息?

java - Typesafe forName 类加载

java - 在 Play 框架中将 Promise 列表转换为 List 的 Promise

Java 泛型 : Multiple Inheritance in Bounded Type Parameters <T extends A & I>

java - 用于拆分数据行的 String.split 无法正常工作

C# 为泛型类创建隐式转换?

java - 什么是 PECS(生产者扩展消费者 super )?

java - 显式类型参数可以冗余吗?