Гость
Целевая тема:
Создать новую тему:
Автор:
Форумы / Java [игнор отключен] [закрыт для гостей] / Метод с арг. Set<? super SomeClass>: не работает for-each, но работает старый Iterator / 10 сообщений из 10, страница 1 из 1
19.09.2013, 17:35:38
    #38401893
ozzmosis
Гость
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Метод с арг. Set<? super SomeClass>: не работает for-each, но работает старый Iterator
Здравствуйте.

Есть класс "Химический элемент" с наследником - "Металл".
Создаю коллекцию металлов, дальше передаю её в метод addSome(), в котором в эту коллекцию добавляется еще один металл.

Если пробовать затем перебирать эту коллекцию через for-each, то обломится (см ниже).
Если же пройтись по ней итератором, то всё пучком.

Это почему так ?
Код: java
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
21.
22.
23.
24.
25.
26.
27.
28.
29.
30.
31.
32.
33.
34.
35.
36.
37.
38.
39.
40.
41.
42.
43.
44.
45.
46.
47.
48.
49.
50.
51.
52.
53.
54.
55.
56.
57.
58.
59.
60.
61.
62.
63.
import java.util.*;
class GenericTest02 {

class Element { // chemical element
  final String name;
  final int z; // sequential number in Mendeleev table;
  Element(String n, int z) { name = n; this.z = z; }
  public String toString() { return "name="+name+"_seqNo="+z; }
  public boolean equals(Object o) { return (o instanceof Element) && (this.name.equals( ((Element)o).name)); }
  public int hashCode() { return name.hashCode() + 31*z; }
}
class Metal extends Element {
  final double mohsHardness;
  Metal(String n, int z, double h) { super(n, z); mohsHardness = h; }
  public String toString() { return super.toString()+"_hardness="+mohsHardness; }
}

class ElementComparator implements Comparator<Element> {
  public int compare(Element e1, Element e2) {
    return e1.name.compareTo(e2.name);
  }
}

  public static void main(String[] aa) {
    new GenericTest02().go();
  }
  void go() {
    Set<Element> e = new TreeSet<Element>( new ElementComparator() );

    e.add( new Metal( "ferrum",  26, 4)  );
    e.add( new Metal( "chrom",  24,  8.5 ) );
    e.add( new Metal( "titan",   22, 6   ) );

    showAll( "initially my old collection:", e );

    addSome( e ); // pass collection declared as "Set<Element>" - super class for Metal

    showAll( "after all, my new collection is:", e );

  }

  void showAll( String title, Set<? extends Element> e) { 
    System.out.println( "\n"+title );
    for (Element x : e) System.out.println( x );
  };


  void addSome( Set<? super Metal> m ) {

    m.add( new Metal( "cuprum", 29, 3 ) );
    
    System.out.println( "\nafter adding one element:" );
    for(Iterator i = m.iterator(); i.hasNext(); ) { System.out.println( i.next() ); }

    // incompatible types  found: java.lang.Object required: GenericTest02.Metal
    // -!- for ( Metal x : m) System.out.println( x ); // Why ?

    // incompatible types  found: java.lang.Object required: GenericTest02.Element
    // -!- for ( Element x : m) System.out.println( x ); // Why ?

  }

}



Ouitput:

Код: plaintext
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
initially my old collection:
name=chrom_seqNo=24_hardness=8.5
name=ferrum_seqNo=26_hardness=4.0
name=titan_seqNo=22_hardness=6.0

after adding one element:
name=chrom_seqNo=24_hardness=8.5
name=cuprum_seqNo=29_hardness=3.0
name=ferrum_seqNo=26_hardness=4.0
name=titan_seqNo=22_hardness=6.0

after all, my new collection is:
name=chrom_seqNo=24_hardness=8.5
name=cuprum_seqNo=29_hardness=3.0
name=ferrum_seqNo=26_hardness=4.0
name=titan_seqNo=22_hardness=6.0
...
Рейтинг: 0 / 0
19.09.2013, 17:47:53
    #38401915
javapecker
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Метод с арг. Set<? super SomeClass>: не работает for-each, но работает старый Iterator
ozzmosis,
Код: java
1.
Set<? super Metal> m

В такой генерик можно только писать, прочитать из такой коллекции можно только Object, потому что неизвестно какой именно предок металла находится в коллекции.
...
Рейтинг: 0 / 0
19.09.2013, 17:49:30
    #38401917
Blazkowicz
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Метод с арг. Set<? super SomeClass>: не работает for-each, но работает старый Iterator
В Java туториале всё подробно описано
http://docs.oracle.com/javase/tutorial/java/generics/lowerBounded.html

Имеем список любых элементов. А почему любых, если мы делаем списое металлов?
Set<Element> e;

Это lower bounded wildcard.
Set<? super Metal> m
Значит что тут может быть Set<Object>, Set<Element> или Set<Metal>
Поэтому компилятор требует для foreach самого обещего типа - object.

Если бы это был аргумент
Set<? extends Element> m
Тогда там мог бы быть только Set<Element> или Set<Metal>. И компилятор при erasure мог бы ограничиться самым общим типом - Element.

В случае итератора ты просто выкинул Generic тип. О чем компилятор выдаёт warning.
...
Рейтинг: 0 / 0
19.09.2013, 17:52:37
    #38401923
javapecker
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Метод с арг. Set<? super SomeClass>: не работает for-each, но работает старый Iterator
Blazkowicz,
автор
Код: java
1.
2.
3.
Если бы это был аргумент
Set<? extends Element> m
Тогда там мог бы быть только Set<Element> или Set<Metal>. И компилятор при erasure мог бы ограничиться самым общим типом - Element.

Но тогда не удалось бы в этом методе записать ничего в сет.
...
Рейтинг: 0 / 0
19.09.2013, 18:00:24
    #38401949
Blazkowicz
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Метод с арг. Set<? super SomeClass>: не работает for-each, но работает старый Iterator
javapeckerНо тогда не удалось бы в этом методе записать ничего в сет.
Вопрос был про итератор. Не заметил, что там добавление.
В общем добавление и итерация разные вещи.
...
Рейтинг: 0 / 0
19.09.2013, 18:02:15
    #38401952
javapecker
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Метод с арг. Set<? super SomeClass>: не работает for-each, но работает старый Iterator
Blazkowicz,
согласен, это просто для полноты картины
...
Рейтинг: 0 / 0
19.09.2013, 19:02:20
    #38402015
ozzmosis
Гость
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Метод с арг. Set<? super SomeClass>: не работает for-each, но работает старый Iterator
BlazkowiczВ Java туториале всё подробно описано
http://docs.oracle.com/javase/tutorial/java/generics/lowerBounded.html нету там про for-each итерацию! и вот тута тоже нету (сказано только, что "You can get the iterator and invoke remove" - но про remove я и сам уже просёк :-)).

BlazkowiczЭто lower bounded wildcard.
Set<? super Metal> m
Значит что тут может быть Set<Object>, Set<Element> или Set<Metal>
Поэтому компилятор требует для foreach самого обещего типа - object. [Ключевая фраза. Всё ясно, спс!
Код: java
1.
2.
3.
4.
5.
6.
7.
  void addSome( Set<? super Metal> m ) {

    m.add( new Metal( "cuprum", 29, 3 ) );
    System.out.println( "\nafter adding one element:" );
    for ( Object x : m) System.out.println( x ); // OK
    //for(Iterator i = m.iterator(); i.hasNext(); ) { System.out.println( i.next() ); }
  }
...
Рейтинг: 0 / 0
19.09.2013, 19:14:13
    #38402027
javapecker
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Метод с арг. Set<? super SomeClass>: не работает for-each, но работает старый Iterator
ozzmosis,
автор
Код: java
1.
нету там про for-each итерацию

Итерация тут вообще ни при чем. Это по большому счету просто способ прочитать элемент из коллекции. Попробуйте просто прочитать get-ом. Получите то же самое
...
Рейтинг: 0 / 0
19.09.2013, 19:22:13
    #38402036
javapecker
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Метод с арг. Set<? super SomeClass>: не работает for-each, но работает старый Iterator
ozzmosis,
и еще я не понимаю, почему у вас читается коллекция в методе addSome(), который судя по названию предназначен не для того чтобы печатать содержимое коллекции. В методе ShowAll() итератор прекрасно будет работать.
...
Рейтинг: 0 / 0
19.09.2013, 19:33:28
    #38402049
ozzmosis
Гость
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Метод с арг. Set<? super SomeClass>: не работает for-each, но работает старый Iterator
javapeckerпочему у вас читается коллекция в методе addSome(), который судя по названию предназначен не для того чтобы печатать содержимое коллекции.да тут всё просто: пока что ваяю примеры из учебника в простом текстовом редакторе, учусь типа :-)
ну, вот и наткнулся, добавив for-each как "отладочный код".
...
Рейтинг: 0 / 0
Форумы / Java [игнор отключен] [закрыт для гостей] / Метод с арг. Set<? super SomeClass>: не работает for-each, но работает старый Iterator / 10 сообщений из 10, страница 1 из 1
Найденые пользователи ...
Разблокировать пользователей ...
Читали форум (0):
Пользователи онлайн (0):
x
x
Закрыть


Просмотр
0 / 0
Close
Debug Console [Select Text]