Generics + Map: Duvidas sobre como obter um entry set[Resolvido]

9 respostas
Mantu

Olá pessoal!
Estou criando uma classe que implementa a interface Map. Esta classe, na verdade, delega as implementações das operações da interface Map para um campo do tipo TreeMap. Estou encontrando problemas para obter um entry set deste meu campo. Vejam:

1	public class ClassMemberUsageMap
2		implements
3			Map<ClassMemberUsageDescriptor, Long>
4	{
5		private Map<ClassMemberUsageDescriptor, Long> treeMap;
6
7		public ClassMemberUsageMap() {
8			treeMap = new TreeMap<ClassMemberUsageDescriptor, Long>();
9		}
10
11		//...
12
13		public void putAll(Map<? extends ClassMemberUsageDescriptor, ? extends Long> map) {
14			Set<Entry<ClassMemberUsageDescriptor, Long>> entrySet = map.entrySet();
15		}
16
17		//...
18	}

Na linha 14, o Eclipse grifa o seguinte erro:

Eclipse:

Type mismatch: cannot convert from
Set<Map.Entry<capture-of ? extends ClassMemberUsageDescriptor,capture-of ? extends Long>> to
Set<Map.Entry<ClassMemberUsageDescriptor,Long>>

Realmente não entendi onde está a incompatibilidade. Poderia jurar que
Set<Map.Entry<ClassMemberUsageDescriptor,Long>>
se “encaixava” em
Set<Map.Entry<capture-of ? extends ClassMemberUsageDescriptor,capture-of ? extends Long>>
O que estou fazendo de errado?

9 Respostas

T

Que problema louco. Acabei lendo o Generics FAQ da Angelika Langer e aquelas seções que começam por http://www.angelikalanger.com/GenericsFAQ/FAQSections/TechnicalDetails.html#Wildcard%20Capture .
No fim das contas não cheguei a um acordo - só que não consigo declarar uma variável que seja compatível com map.entries(). Que droga.

import java.util.*;

class ClassMemberUsageDescriptor {
}

	public class ClassMemberUsageMap
		implements
			Map<ClassMemberUsageDescriptor, Long>
	{
		private Map<ClassMemberUsageDescriptor, Long> treeMap;
		
		// burocracia
		public Set<Map.Entry><ClassMemberUsageDescriptor,Long>&gt 	entrySet() {return treeMap.entrySet();}
		public Collection<Long> 	values() { return treeMap.values(); }
		public Set<ClassMemberUsageDescriptor> 	keySet() { return treeMap.keySet(); }
    public void clear() {treeMap.clear();}
    public Long remove(Object obj) { return treeMap.remove (obj); }
    public Long	put(ClassMemberUsageDescriptor key, Long value) { return treeMap.put (key, value); }
    public Long	 	get(Object key) { return treeMap.get (key); }
    public boolean containsValue (Object value) { return treeMap.containsValue(value); }
    public boolean containsKey (Object key) { return treeMap.containsValue(key); }
    public boolean isEmpty () { return treeMap.isEmpty(); }
    public int size () { return treeMap.size(); }
    // ... etc ...
		

		public ClassMemberUsageMap() {
			treeMap = new TreeMap<ClassMemberUsageDescriptor, Long>();
		}

	//...

		public void putAll(Map&lt? extends ClassMemberUsageDescriptor, ? extends Long&gt map) {
		  treeMap.putAll (map);

/* Erro:
found   : java.util.Set<java.util.Map.Entry><capture#560 of ? extends ClassMember
UsageDescriptor,capture#309 of ? extends java.lang.Long>&gt
required: java.util.Set<java.util.Map.Entry>&lt? extends ClassMemberUsageDescriptor
,? extends java.lang.Long&gt&gt
 */		  
		  Set<Map.Entry>&lt? extends ClassMemberUsageDescriptor, ? extends Long&gt &gt myEntrySet1 = map.entrySet();
/* Erro:
found   : java.util.Set<java.util.Map.Entry><capture#684 of ? extends ClassMember
UsageDescriptor,capture#49 of ? extends java.lang.Long>&gt
required: java.util.Set<java.util.Map.Entry><ClassMemberUsageDescriptor,java.lang
.Long>&gt
 */		  
		  Set<Map.Entry><ClassMemberUsageDescriptor, Long> &gt myEntrySet2 = map.entrySet();
/* Erro:
found   : java.util.Set<java.util.Map.Entry><capture#552 of ? extends ClassMember
UsageDescriptor,capture#955 of ? extends java.lang.Long>&gt
required: java.util.Set<java.util.Map.Entry>&lt? super ClassMemberUsageDescriptor,?
 super java.lang.Long&gt&gt
 */		  
			Set<Map.Entry>&lt? super ClassMemberUsageDescriptor, ? super Long&gt&gt entrySet3 = map.entrySet();

/* Erro:
found   : java.util.Set<java.util.Map.Entry><capture#388 of ? extends ClassMember
UsageDescriptor,capture#640 of ? extends java.lang.Long>&gt
required: java.util.Set<java.util.Map.Entry>&lt?,?&gt&gt
 */		  
			Set<Map.Entry>&lt?,?&gt&gt entrySet4 = map.entrySet();
// Não dá erro...			
      Set&lt?&gt entrySet5 = map.entrySet();
// mas não posso fazer isto:      
      entrySet5.addAll (map.entrySet());
// nem isto      
      for (Map.Entry<ClassMemberUsageDescriptor, Long> entry : entrySet5) {
          
      }			
// pelo jeito temos de usar o mapa sem jogá-lo em uma variável. Isto funciona
      for (Map.Entry&lt? extends ClassMemberUsageDescriptor, ? extends Long&gt entry : map.entrySet()) {
          System.out.println (entry);
      }      
		}

		//...
	}
Mantu

Mas que coisa, não!!? :shock:
Muito estranho isso!!! :?
Em todo caso, a solução que você encontrou não usando a variável Set já resolve o problema aqui (Como sempre, aliás… :thumbup: ).
Muito obrigado, Thingol!

Mantu

Um cara lá do forum da sun achou o problema. Dá até raiva:

public void putAll(Map<? extends ClassMemberUsageDescriptor, ? extends Long> map) {
    Set<? extends Entry<? extends ClassMemberUsageDescriptor, ? extends Long>> es = map.entrySet();

Vê se pode!!!

T

Que coisa mais pirada. Acho que preciso mandar esse caso para a dona Angelika Langer, para ela poder mostrar no FAQ dela.

Ela vai olhar e dizer: “mas é óbvio!”, só que não é nada óbvio para a gente que não está acostumada a níveis e níveis de wildcards.

Como ela é instrutora deve então mostrar isso como um exemplo.

Mantu

Poste aqui o link deste FAQ para nos!

Luca

Olá

Veja http://www.guj.com.br/posts/list/47081.java#246240

[]s
Luca

Mantu

Putz… que vergonha… :oops: :oops: :oops: :oops: :oops: :oops: :oops: :oops: :oops: :oops: :oops: :oops: :oops: :oops:
Vou guardar esse tópico como um contra-exemplo… :lol:

A

Você pode postar o link para a thread no fórum da Sun?

Mantu

http://forum.java.sun.com/thread.jspa?threadID=790533

Criado 29 de novembro de 2006
Ultima resposta 30 de nov. de 2006
Respostas 9
Participantes 4