首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >Java - Generics通配符问题

Java - Generics通配符问题
EN

Stack Overflow用户
提问于 2013-08-28 18:05:50
回答 1查看 236关注 0票数 1

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

代码语言:javascript
复制
public interface SetInterface<T>
{   
    public T duplicateSet();
}

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

代码语言:javascript
复制
public interface ExerciseInterface <T extends SetInterface<?>>
{   
    public T getSet(int pos);
    public void addSet(T set);
}

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

问题来了,我试图创建一个包含不同类的泛型集合,这些类都实现了ExerciseInterface。

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

这个问题可以用我的addA()addB()方法来概括。

代码语言:javascript
复制
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()给出以下错误。

代码语言:javascript
复制
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()给出了这个错误。

代码语言:javascript
复制
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<?>>)

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

我也有不同的练习,这反映了布景。例如:

代码语言:javascript
复制
BodyWeightExercise implements <SetInterface<BodyweightSet>>

代码语言:javascript
复制
WeightsExercise implements <SetInterface<WeightsSet>>

因此,我的目标是有一个不同的练习集合和一个方法,让我可以添加到这个集合。

任何帮助都将是衷心的感谢,我已经为此失去了一些头发。

干杯。

编辑:,如果这是不可做的,在一个更可行的方向上的任何指针都会被感激。

EDIT2: I将列表更改为List <ExerciseInterface<SetInterface<?>>> exerciseList;,添加()方法上的错误都不出现。

但是,使用此测试代码。

代码语言:javascript
复制
WeightsSet weightsSet = new WeightsSet();       
WeightsExercise weightsExercise = new WeightsExercise();

weightsExercise.addSet(weightsSet);

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

我正在尝试将一个WeightsExercise添加到Workout的列表中,但是我现在得到了这个错误。

代码语言:javascript
复制
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的示例类(上面接口中的具体方法也更新)

代码语言:javascript
复制
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;}  
}

解决了:这个解决方案似乎正确地涵盖了一切。

代码语言:javascript
复制
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);}

}

EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2013-08-28 18:10:42

应将列表声明更改为:

代码语言:javascript
复制
List<ExerciseInterface<SetInterface<?>>> exerciseList;

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

这是因为,您不知道它实际上引用了哪些具体的参数化列表类型。例如:List<? extends CharSequence>可以引用ArrayList<String>ArrayList<StringBuffer>。所以,您不能在列表中添加任何内容,因为它不是类型安全的。您可能会在ArrayList<String>中添加一个ArrayList<String>对象,这将在运行时失败。

更新后的

我想您正在尝试创建一个并行类层次结构,但却搞砸了。也许,您希望您的ExerciseInterface看起来像:

代码语言:javascript
复制
// 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将被修改如下:

代码语言:javascript
复制
class WeightsExercise implements ExerciseInterface<WeightsSet> {
    @Override
    public SetInterface<WeightsSet> getSet(int pos)    {return null;}

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

您还需要使您的Workout类泛化如下:

代码语言:javascript
复制
public class Workout<U extends SetInterface<U>, T extends ExerciseInterface<U>> {

}

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

并像这样创建Workout的实例:

代码语言:javascript
复制
Workout<WeightsSet, WeightsExercise> workout = new Workout<>("Wok");
workout.addExerciseA(weightsExercise);

这将使一个正确的设计,海事组织。

推荐职位:

参考资料:

  • Java泛型常见问题- Angelika Langer
    • 什么是有界通配符?
    • 泛型是否有助于设计并行类层次结构?

票数 2
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/18495153

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档