简体   繁体   中英

How to make the following method generic?

I'm currently studying for Object-Oriented Programming and I'm currently studying the chapter Generics. I have the following code from a Java class and what I'm asked to do is to make the last method calculateSquares generic. I am really puzzled by it, I can tell you that.

Here is the class :

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());
    }
}

What I found out is that List Number needs to become List ? extends Number , like this :

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());
    }
}

Thing is, I don't know what to do with the for-loop :

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

My logical guess would have been :

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

But that seems to be incorrect. What should I do to the for-loop?

What you actually ask for is not possible. At least you can't change the destination list to ? extends Number ? extends Number . Because then you don't know which type the list is. If it is a List<Integer> you can't add a Double value there. However what you can do is make the source generic.

The way to go is to add the generic type to the method declaration

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());
    }
}

actually once you leave the destination you also can leave your old Method. It still works:

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());
    }
}

as it seems you want add a List<Double> or a List<Number> to destination. This is possible again by altering the first List and use the super-operator:

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());
    }
}

First, there is no need to pass the dest List. Altering values of parameters is not a good practice. We can probably change the return type to List, create a new List ourselves and return it.

Second, means that you can pass any list that extends number but you can't add anything into it. If you want to add then you need to change it to . Refer to this SO answer for in depth explanation.

Third, we don't need to add the square twice. Adding just once should do. Refer to below example:

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;
    }

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM