如何使以下方法通用?

时间:2015-12-11 13:59:43

标签: java generics

我目前正在攻读面向对象编程,我目前正在研究泛型一章。我有一个来自Java类的以下代码,我要求的是使最后一个方法 calculateSquares 泛型。我真的很困惑,我可以告诉你。

以下是课程:

public class OefeningWildcards {

public static void main(String[] args){
    new OefeningWildcards().run();
}

public OefeningWildcards(){

}

public void run(){
    Number[] numbers = {2, 3.1, 5, 12, 2.3};
    List<Number> numbersList = new ArrayList<>();
    for (Number n : numbers){
        numbersList.add(n);


    List<Number> dest = new ArrayList<>();
    calculateSquares(dest, numbersList);

    Double[] doubles = {3.2, 5.6, 4.4, 6.5, 12.2};
    List<Double> doublesList = new ArrayList<>();

    List<Number> dest2 = new ArrayList<>();
    calculateSquares(dest2, doublesList);

    List<Double> dest3 = new ArrayList<>();
    calculateSquares(dest3, doublesList);

    }
}


//This method needs to become generic
public void calculateSquares(List<Number> dest, List<Number> src){
    dest.clear();
    for (Number n : src) {
        dest.add(n * n.intValue());
        dest.add(n.doubleValue() * n.doubleValue());
    }
}

我发现列表编号需要成为列表?扩展数字,如下所示:

public void calculateSquares(List<? extends Number> dest, List<? extends Number> src){
    dest.clear();
    for (Number n : src) {
        dest.add(n * n.intValue());
        dest.add(n.doubleValue() * n.doubleValue());
    }
}

事情是,我不知道如何处理for循环:

for (Number n : src) {
        dest.add(n * n.intValue());
        dest.add(n.doubleValue() * n.doubleValue());
    }
}

我的逻辑猜测是:

for (? extends Number n : src) {
        dest.add(n * n.intValue());
        dest.add(n.doubleValue() * n.doubleValue());
    }
}

但这似乎是不正确的。我应该怎么做for循环?

2 个答案:

答案 0 :(得分:2)

你实际要求的是不可能的。至少您无法将目的地列表更改为? extends Number。因为那时你不知道列表是哪种类型。如果是List<Integer>,则无法在其中添加Double值。但是,你可以做的是使源通用。

要做的是将泛型类型添加到方法声明

public void <T extends Number> calculateSquares(List<Number> dest, List<T> src){
    dest.clear();
    for (T n : src) {
        dest.add(n * n.intValue());
        dest.add(n.doubleValue() * n.doubleValue());
    }
}

实际上,一旦离开目的地,您也可以离开旧方法。它仍然有效:

public void calculateSquares(List<Number> dest, List<? extends Number> src){
    dest.clear();
    for (Number n : src) {
        dest.add(n * n.intValue());
        dest.add(n.doubleValue() * n.doubleValue());
    }
}

因为您似乎想要向目标添加List<Double>List<Number>。通过更改第一个List并使用超级运算符,可以再次实现这一点:

public void calculateSquares(List<? super Double> dest, List<? extends Number> src){
    dest.clear();
    for (Number n : src) {
        dest.add((double)n * n.intValue());
        dest.add(n.doubleValue() * n.doubleValue());
    }
}

答案 1 :(得分:0)

首先,不需要传递dest List。改变参数值不是一个好习惯。我们可以将返回类型更改为List,自己创建一个新List并返回它。

其次,意味着您可以传递任何扩展数字的列表,但不能在其中添加任何内容。如果要添加,则需要将其更改为。有关详细说明,请参阅this SO答案。

第三,我们不需要添加两次方块。只需添加一次即可。请参阅以下示例:

public List<Number> calculateSquares(List<? extends Number> src){
        List<Number> squares = new ArrayList<>();
        for (Number n : src) {
            squares.add(n.doubleValue() * n.doubleValue());
        }
        return squares;
    }