2015-12-11 5 views
4

В настоящее время я изучаю объектно-ориентированное программирование, и сейчас я изучаю главу Generics. У меня есть следующий код из класса Java, и я прошу сделать это, чтобы сделать последний метод calculateSquares generic. Я действительно озадачен этим, могу вам сказать.Как сделать следующий метод общим?

Вот класс:

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 (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?

+0

В строке 3: ** dest.add (п * n.intValue()); ** это "плохие типы операндов для бинарного оператора '*'" ошибка. На строке 4: ** dest.add (n.doubleValue() * n.doubleValue()); ** Я получаю «Нет подходящего метода для добавления (двойной)» ошибки. –

+0

В случае второй ошибки компилятора вы не можете добавить в «Список », потому что вы не знаете, что? расширяет T'. Скажем 'T'' 'Number':'? extends Number' может быть 'Number', это может быть' Integer', или это может быть какой-то класс, который вы только что создали, который реализует 'Number'.Однако вы можете добавить в «Список ». (См. Http://stackoverflow.com/questions/2723397/java-generics-what-is-pecs) –

+0

В случае первой ошибки компилятора это связано с тем, что '*' применяется только к примитивным типам или типам, которые могут быть авто-распакованные. 'Number' не может быть. Вам нужно будет вызвать, скажем, 'n.intValue() * n.intValue()' или 'n.doubleValue() * n.intValue()'. –

ответ

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> к месту назначения. Это можно сделать, изменив первый список и используя супероператор:

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

Во-первых, нет необходимости передавать список dest. Изменение значений параметров не является хорошей практикой. Вероятно, мы можем изменить тип возврата на список, создать новый список и вернуть его.

Во-вторых, вы можете передать любой список, который расширяет число, но вы не должны не можете добавить. Если вы хотите добавить, вам нужно изменить его. Обратитесь к this. Ответьте на подробное объяснение.

В-третьих, нам не нужно добавлять квадрат дважды. Добавление только один раз должно сделать. См пример ниже:

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; 
    } 
Смежные вопросы