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

Есть класс "Химический элемент" с наследником - "Металл".
Создаю коллекцию металлов, дальше передаю её в метод 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
Метод с арг. Set<? super SomeClass>: не работает for-each, но работает старый Iterator
    #38401915
javapecker
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
ozzmosis,
Код: java
1.
Set<? super Metal> m

В такой генерик можно только писать, прочитать из такой коллекции можно только Object, потому что неизвестно какой именно предок металла находится в коллекции.
...
Рейтинг: 0 / 0
Метод с арг. Set<? super SomeClass>: не работает for-each, но работает старый Iterator
    #38401917
Фотография Blazkowicz
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
В 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
Метод с арг. Set<? super SomeClass>: не работает for-each, но работает старый Iterator
    #38401923
javapecker
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Blazkowicz,
автор
Код: java
1.
2.
3.
Если бы это был аргумент
Set<? extends Element> m
Тогда там мог бы быть только Set<Element> или Set<Metal>. И компилятор при erasure мог бы ограничиться самым общим типом - Element.

Но тогда не удалось бы в этом методе записать ничего в сет.
...
Рейтинг: 0 / 0
Метод с арг. Set<? super SomeClass>: не работает for-each, но работает старый Iterator
    #38401949
Фотография Blazkowicz
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
javapeckerНо тогда не удалось бы в этом методе записать ничего в сет.
Вопрос был про итератор. Не заметил, что там добавление.
В общем добавление и итерация разные вещи.
...
Рейтинг: 0 / 0
Метод с арг. Set<? super SomeClass>: не работает for-each, но работает старый Iterator
    #38401952
javapecker
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Blazkowicz,
согласен, это просто для полноты картины
...
Рейтинг: 0 / 0
Метод с арг. Set<? super SomeClass>: не работает for-each, но работает старый Iterator
    #38402015
ozzmosis
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
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
Метод с арг. Set<? super SomeClass>: не работает for-each, но работает старый Iterator
    #38402027
javapecker
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
ozzmosis,
автор
Код: java
1.
нету там про for-each итерацию

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


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