Java - 从Generic方法返回正确的类型

时间:2011-01-15 17:10:01

标签: java generics class-design return-type

我有以下类结构:

public class Team {
    ...
}

public class Event {

}

public abstract class Fixture<T extends Team> implements Event {
   ...
}

public abstract class Forecast<Event> {

}

public class MyPrediction<T extends Fixture<? extends Team>> extends Forecast<Fixture<? extends Team>>{

}

我正在尝试模拟所有类型的体育赛事(即'夹具'是针对两个参赛者之间的特定比赛相互比赛,而另一种类型的'赛事'可能有很多参赛者),以及预测特定'事件'的结果。我有一个通用的方法:

public <T> MyPrediction<Fixture<? extends Team>> getMyPrediction(Fixture<? extends Team> fixture) {

}

我希望能够返回具有MyPrediction参数的泛型类型的fixture实例,但我似乎无法这样做。例如,如果我执行以下操作,那么我会收到编译错误:

SoccerFixture<EnglishSoccerTeams> soccerMatch = new ScoccerFixture<EnglishSoccerTeams>();
MyPrediction<SoccerFixture<EnglishSoccerTeams>> = getMyPrediction(soccerMatch);

我愿意改变我的类结构以包含此功能。我怎么能这样做?

2 个答案:

答案 0 :(得分:0)

由于类型擦除(通用参数在运行时不可用),Java的类型系统不够强大,无法直接执行您的建议。

通常的解决方案是创建一个单独的EventFactory类,然后可以将其传递给需要创建特定Event子类型实例的任何方法。

答案 1 :(得分:0)

getMyPrediction的签名更改为

public <T extends Fixture<? extends Team>> MyPrediction<T> getMyPrediction(T fixture)

这告诉编译器参数和结果中的fixture类型是相同的,允许类型检查通过。

这是一个完整的示例,还有一些其他的小改动可以让它编译。它引入了用于保存Predictor方法的类getMyPrediction和用于显示示例用法的doit方法:

public interface Team {
}

public interface Event {
}

public abstract class Fixture<T extends Team> implements Event {
}

public abstract class Forecast<T> {
}

public class MyPrediction<T extends Fixture<? extends Team>> extends
        Forecast<Fixture<? extends Team>> {
}

public class SoccerFixture<T extends SoccerTeam> extends Fixture<T> {
}

public class SoccerTeam implements Team {
}

public class EnglishSoccerTeam extends SoccerTeam {
}

public class Predictor {

    public <T extends Fixture<? extends Team>> MyPrediction<T> getMyPrediction(T fixture) {
        return new MyPrediction<T>();
    }

    public void doit() {
        SoccerFixture<EnglishSoccerTeam> soccerMatch = new SoccerFixture<EnglishSoccerTeam>();
        MyPrediction<SoccerFixture<EnglishSoccerTeam>> myPrediction = getMyPrediction(soccerMatch);
    }
}

如其他地方所述,您可能需要引入一个或多个工厂对象,以便在MyPrediction实现中执行有意义的工作。