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.