[RESOLVIDO] Curiosidade: Bug no uso de Collections ou bug na API Collections? Ou estou ficando louco

Olá pessoal do GUJ.

Esses dias durante o meu trabalho, deparei-me com um trecho de código que estava causando bugs no projeto que estou desenvolvendo.
Até aí nada de novo, o problema é que nunca me deparei com um erro como esse… Como acho que estou ficando louco (pois já trabalho com Java há muito tempo) e como não encontrei nenhuma explicação lógica para o erro (a não ser “Ou eu estou errado… ou o Java está errado”), peço a ajuda e/ou opinião de vocês sobre o caso.

Abaixo segue um pequeno teste unitário que desenvolvi que aborda o problema:

import java.util.Collection;
import java.util.LinkedList;
import java.util.List;

import junit.framework.TestCase;

public class PolimorphismTest extends TestCase {
	public void testCollectionPointerBug() throws Exception {
		Collection<Object> collectionPointer = new LinkedList<Object>();
		List<Object> listPointer = (List<Object>) collectionPointer;

		listPointer.add(new Object());
		assertEquals(1, listPointer.size());
		listPointer.remove(0);
		assertEquals(0, listPointer.size());

		collectionPointer.add(new Object());
		assertEquals(1, collectionPointer.size());
		collectionPointer.remove(0);
		assertEquals(0, collectionPointer.size()); // <- Teste falha!!!
	}
}

Agora a pergunta… Por causa do polimorfismo, não deveria ser o mesmo resultado? A única diferença entre as duas operações são as referências… O objeto em teoria não deveria executar a mesma operação? Alguém tem o telefone de um psiquiatra?

Agradeço desde já!

Att.,

não é um bug. se vc olhar a API de Collection (Interface) vai ver que só existe o método “remove(Object o)”, que remove o objeto passado por parametro, se ele existir na coleção. Não existe o método “remove(int index)”, que só existe na interface List, que remove o objeto no indice passado como parametro.

no caso, o que acontece é q o 0 passado na segunda chamada de remove é convertido para um Integer wrapper, que como não existe na lista, não é removido. logo a lista fica com tamanho = 1.

espero ter sido claro, num sou muito bom em explicações… :lol:

Po cara… pior que foi muito claro sim… Agora vi a “pegadinha” que eu não tava pescando…
E olha que debugando isso ontem, cheguei a ver que dois métodos diferentes eram chamados, mas realmente não reparei no parâmetro passado! tsc tsc…
Acho que preciso mesmo marcar o tal psiquiatra…

Valeu pela ajuda!

Att.,

Collection.remove não aceita um parâmetro “int”, até porque você pode ter coleções não-indexadas, como Set (HashSet, TreeSet).
É que houve um “boxing” em collectionPointer.remove que você não enxergou.

import java.util.*;

 public class TesteCollection {  
     public static void main (String[] args) {  
         Collection<Object> collectionPointer = new LinkedList<Object>();  
         List<Object> listPointer = (List<Object>) collectionPointer;  
   
         listPointer.add(new Object());  
         System.out.println (listPointer.size());  
         System.out.println (listPointer);
         listPointer.remove(0);  
         System.out.println (listPointer.size());  
         System.out.println (listPointer);
   
         collectionPointer.add(new Object());  
         System.out.println (collectionPointer.size());  
         System.out.println (collectionPointer);
         // Não existe Collection.remove (int), apenas Collection.remove (Object). 
         collectionPointer.remove(0);  
         System.out.println (collectionPointer.size()); 
         System.out.println (collectionPointer);
         collectionPointer.remove(Integer.valueOf(0));  // equivale à linha collectionPointer.remove (0);
         System.out.println (collectionPointer.size()); 
         System.out.println (collectionPointer);
     }  
 }

Lists tem indexes.
Collections não.

Nossa… eu abro varias abas pra depois olhar… depois que posto vejo que voce já tem as respostas.