Qual a diferença de instanciar uma variável como tipo List para instanciar uma variável do tipo ArrayList?

Eu sempre aprendi que, para se instanciar um ArrayList, por exemplo, de Strings, a gente usa a seguinte sintaxe:

ArrayList<String> al = new ArrayList<String>();

Mas, recentemente, vi bastante gente nos fóruns de programação instanciando da seguinte maneira:

List al = new ArrayList<String>();

Qual é a diferença de instanciar a variável como sendo do tipo ArrayList e receber um construtor do mesmo tipo (primeiro exemplo) para instanciar a variável como sendo do tipo List e receber um construtor do tipo ArrayList?

1 curtida

Nós não instanciamos variáveis. O que vc quis dizer foi:

“Qual a diferença entre declarar uma variável como sendo do tipo List e ArrayList?”

Fazemos isso pra não deixar nosso código preso à uma implementação especifica.

List é uma interface, ArrayList é uma das implementações desta interface. Quando vc declara uma variável como List, vc poderia armazenar nela uma instancia de qualquer classe que a implemente.

Vamos dizer que no futuro, sua aplicação cresce e vc nota que o ArrayList está causando lentidão no sistema e vc decide implementar sua própria versão dele, uma versão mais rápida. A primeira coisa que vc vai fazer é criar uma nova classe que implementa List. A segunda coisa será implementar cada método que List exige.

Usando List, posteriormente, vc ficaria livre pra substituir o ArrayList por um outro tipo de estrutura, tipo uma LinkedList, ou uma Stack.

6 curtidas

Que resposta excelente e esclarecedora! Muito obrigado mesmo! Vou declarar a variável sempre sendo do tipo List então! Poderia só me esclarecer só mais uma coisa:

Qual a diferença (se é que tem alguma) entre, por exemplo, fazer

List<> al = new ArrayList<String>();

e

List<String> al = new ArrayList<>();
1 curtida

O operador diamante <> é usado para, dentro dele, você declarar que tipo de informações aquela lista recebe.

Então se lê:

List<String> al = new ArrayList();

como

Lista de String al recebe uma nova ArrayList

Esse conceito faz parte do Polimorfismo em Java. Recomendo que leia sobre isso! :smiley:

[]'s

Na verdade o operador diamante faz parte do conceito de tipos de dados genéricos.

Polimorfismo é justamente você ter uma variável declarada como sendo de um tipo de dado mas sua referência ser de outro tipo mais específico.

1 - Isso não funciona, se tentar, gera erro:

List<> al = new ArrayList();

O compilador espera o nome de um tipo ali entre < e >.

2 - Isso funciona, porém, se usar assim, estará abrindo mão de um recurso muito útil que são os Generics.

List al = new ArrayList<>();
// sem o <> é o mesmo resultado:
List al = new ArrayList();

Uma lista não-genérica aceita qualquer tipo de objeto.

List l = new ArrayList();
l.add("uma string");
l.add(123);
l.add(new JFrame());

Isso pode ser um problema, pois normalmente o que se deseja é uma lista de objetos que tenham alguma relação entre si.

Por exemplo, num app de lista telefonica vc iria querer uma lista apenas de Contatos. Num app de restaurante vc iria querer uma lista apenas de Pratos.

Generics nos permite limitar o tipo de dado que queremos em nossa lista.

// Aceita só String
List<String> a = new ArrayList<String>();
// Só números inteiros
List<Integer> b = new ArrayList<Integer>();
// Só Contatos
List<Contatos> c = new ArrayList<Contatos>();

// É possível omitir o tipo na instanciação das classes
// o resultado é o mesmo que no trecho acima.
List<String> a = new ArrayList<>();
List<Integer> b = new ArrayList<>();
List<Contatos> c = new ArrayList<>();

O uso de Generics vai além disso. É possível criar métodos genéricos também. E quando vc não sabe exatamente com que tipo vc está lidando, pode usar wildcards. Recomendo o tutorial abaixo para maiores informações:

https://docs.oracle.com/javase/tutorial/extra/generics/index.html

Não ficou muito claro, mas era sobre a declaração da interface List ao invés do tipo específico ArrayList que eu estava falando. Boa observação.

1 curtida

E qual a vantagem de declarar a interface em vez da implementação?

A vantagem é justamente você não depender da implementação e sim da interface.

Imagina que você tem o atributo List minhaLista.
Se futuramente você quiser usar por exemplo um LinkedList ao invés de ArrayList, não precisará sair modificando todo seu código fonte.

Dê uma olhada aqui: