Alura > Cursos de Programação > Cursos de Java > Conteúdos de Java > Primeiras aulas do curso Java: trabalhando com listas e coleções de dados

Java: trabalhando com listas e coleções de dados

Coleção de filmes - Apresentação

Jacqueline: Olá, tudo bem? Eu sou a Jacqueline Oliveira, instrutora na Alura, e te dou boas-vindas a mais um curso de Java, onde aprofundaremos nossos conhecimentos em Orientação a Objetos, Coleções e várias coisas que você precisa saber para trabalhar como pessoa desenvolvedora em Java.

Sou uma mulher branca com cabelos loiros longos, com uma camiseta azul com o logo da Alura.

Estou aqui com o Paulo.

Paulo: Oi Jaque. Eu sou o Paulo Silveira, um dos líderes da Alura. Estou muito contente em poder dar esse avanço na formação de Java.

Sou um homem branco, na faixa dos 40 anos, com cabelos curtos, barba e bigode, todos pretos, além de uma camiseta preta, que costumo utilizar bastante.

Neste curso, veremos coisas imprescindíveis no dia-a-dia de trabalho de uma pessoa que desenvolve com Java. Veremos desde as Listas e Coleções, onde trabalharemos com um punhado de objetos, até o aprofundamento em Orientação a Objetos e Construtores.

Tudo isso sendo conectado aos outros cursos da Formação Java, que está incrível.

Estou feliz em dar mais um passo em Java.

Jacqueline: Eu vou te acompanhar. Espero você para continuarmos o curso.

Coleção de filmes - Lista de filmes com ArrayList

Paulo: Trabalhamos com muitos títulos em nosso sistema de streaming Screen Match. Além de filmes, podemos ter séries e até músicas.

Se pegarmos o caso do filme, onde temos o código da classe Principal.java, podemos criar uma série de filmes, com filme1, filme2, e assim por diante.

Contudo, ainda não trabalhamos com uma sequência, coleção ou conjunto de objetos. Não pegamos vários filmes e colocamos em um objeto maior para realizar buscas, ver qual tem maior duração, ordená-los por nome ou simplesmente listá-los na web.

No momento, temos uma variável para cada. Entretanto, normalmente temos um Array (arranjo), um vetor, conjunto ou uma estrutura de dados que sabe manipular um monte de objetos.

Toda linguagem de programação tem essa estrutura — algumas possuem bibliotecas úteis e fáceis de usar, outras nem tanto.

Lá na década de 90, entre 1994 e 95, o Java nasceu com poucas bibliotecas. Posteriormente, o Java 2 nasceu com a biblioteca Java Collections, que fica dentro do java.util. Este foi um passo muito importante.

Para começarmos a usar uma lista de filmes, podemos revisar a classe Principal e quais as classes criadas nos cursos anteriores?

Jacqueline: Podemos, sim, Paulo.

Nosso projeto Screen Match é uma empresa de streaming, com filmes e séries, a qual fomos modelando de acordo com as nossas regras e necessidades.

Voltando ao IntelliJ, vemos dentro da pasta "modelos" os seguintes arquivos:

Neste caso, trabalhamos com herança.

Na pasta "br.com.alura.screenmatch", temos a classe Principal, onde criamos alguns filmes no meuFilme, como, por exemplo, "O poderoso chefão".

Nela também avaliamos os filmes. Para isso, dentro da pasta "calculos", criamos a classe CalculadoraDeTempo.

Além disso, na classe Principal temos formas de realizar recomendações de filmes.

Com isso tudo, nosso projeto está bem completo.

Paulo: Para quem deu um tempo entre a realização de cada curso, está disponível a página do Github deste projeto, onde temos o código finalizado no curso anterior, assim como as anotações para entender a partir de onde estamos começando.

Temos um conjunto de classes importantes, em especial Filme e Serie. Depois, temos o Titulo, que está por cima e que possui alguns métodos para saber o nome, a duração e o ano do filme.

Jacqueline: Exatamente. Se pensarmos no Screen Match de forma geral, vamos precisar de listas para muitas coisas que vão além dos filmes. Entre elas: listas do que já assistimos, do que classificamos, do que buscamos, e até mesmo de atores e atrizes.

Portanto, essa parte de listas e coleções será frequente no projeto.

Na minha classe principal, temos:

public class Principal {

public static void main(String[] args) {
        Filme meuFilme = new Filme();
        meuFilme.setNome("O poderoso chefão");

// Código omitido

        Serie lost = new Serie();
        lost.setNome("Lost");

// Código omitido

    Filme outroFilme = new Filme();
    outroFilme.setNome("Avatar");

// Código omitido

    }
}

Queremos criar uma lista com estes filmes que assistimos e determinamos na classe principal.

Paulo: Podemos criar um terceiro: o "Filme do Paulo".

Jacqueline: Exatamente. Vamos criar um terceiro filme no final do arquivo, duas linhas abaixo de filtro.filtra(episodio).

public class Principal {

public static void main(String[] args) {

// Código omitido

        filtro.filtra(episodio);

        Filme filmeDoPaulo = new Filme();
    }
}

Paulo: Já que estamos ensinando coisas novas, vamos abordar a estranheza que as pessoas sentem quando criamos a variável da esquerda, a qual chamamos de variável referência. Junto a ela, à direita, estamos criando o objeto e guardando a referência deste objeto na variável referência filmeDoPaulo.

Quando temos uma regra bem clara, no Java, podemos escrever var para não precisar repetir. Isso funciona?

Jacqueline: Funciona. O Java, apesar de ser fortemente tipado, permite que criemos uma variável utilizando o var. Isso não significa que ela mudará o tipo em algum momento.

        var filmeDoPaulo = new Filme();

Paulo: Eu não posso fazer filmeDoPaulo = 5, por exemplo.

Jacqueline: Não pode. Ele sabe que filmeDoPaulo é um Filme. A variável var realiza uma inferência do tipo declarado. Não precisamos dizê-lo.

Paulo: É para simplificar.

Jacqueline: O filmeDoPaulo não varia de tipo e será sempre um Filme.

Paulo: Em outras linguagens, isso funcionaria, mas o Java é bem restrito.

Jacqueline: Isso aí.

Paulo: Agora podemos colocar o nome do filme, a duração em minutos e o ano.

Jacqueline: Exato. Então, filmeDoPaulo.setDuracaoEmMinutos(). Qual a duração, Paulo?

Paulo: É duzentos.

Jacqueline: Vamos adicionar entre parênteses o 200. Abaixo dessa linha, adicionaremos um filmeDoPaulo.setNome().

Paulo: O filmeDoPaulo será "Dogville". O ano de lançamento é 2003.

Jacqueline: Entre parênteses, colocaremos o nome. Abaixo dessa linha, adicionaremos um filmeDoPaulo.setAnoDeLancamento(2003).

Qual a nota que você dá para este filme, Paulo?

Paulo: Eu dou 10.

Jacqueline: Na linha de baixo, vamos adicionar um filmeDoPaulo.avalia(10).

        var filmeDoPaulo = new Filme();
        filmeDoPaulo.setDuracaoEmMinutos(200);
        filmeDoPaulo.setAnoDeLancamento(2003);
        filmeDoPaulo.avalia(10);

Queremos criar uma lista com estes filmes e trabalhar com ela. Para isso, no Java, utilizamos uma classe chamada ArrayList.

Paulo: Existem várias estruturas, como listas e conjuntos. Uma das mais utilizadas é certamente o ArrayList.

Se trata de uma lista que trabalha com uma sequência de objetos, por dentro da qual temos uma Array primitiva. Podemos falar sobre esta última depois.

Jacqueline: Isso. E como a declaramos aqui? Começamos sempre pelo tipo, portanto adicionaremos abaixo dos nossos filmes um ArrayList.

// Código omitido

        filmeDoPaulo.avalia(10);

ArrayList

Se colocarmos o cursor em cima desta palavra, o sistema abre uma caixa de sugestões onde coloca um E entre sinais de maior e menor.

public class ArrayList<E>

Este se refere ao tipo do elemento, ou seja, o tipo daquilo que armazenaremos na lista.

Portanto, entre os sinais de maior e menor, diremos que vamos armazenar elementos do tipo Filme. À sua direita, criaremos a listaDeFilmes.

Temos que invocar o nosso construtor para criar este ArrayList. Então, à direita de listaDeFilmes, colocaremos um = new ArrayList<>().

Quando digitarmos parte deste comando, o sistema abrirá uma caixa de sugestões, dentre as quais selecionaremos ArrayList<> do java.util, permitindo que o IntelliJ complete o nosso código e crie para nós o ArrayList.

// Código omitido

ArrayList<Filme> listaDeFilmes = new ArrayList<>();

Paulo: Perfeito. Quem conhece outras linguagens como o Python deve lembrar que lá se utiliza uma sintaxe curta e tudo é criado quase que magicamente.

No Java, por outro lado, criamos um objeto que é uma lista, e que tem por trás de si um arranjo. Vamos ver isso quando abrirmos a documentação.

Aqui poderíamos ter usado inclusive o var, criando o comando var listaDeFilmes = new ArrayList<>(). Contudo, posteriormente, voltaremos com as interfaces e queremos deixar explícito que tudo se encaixa na Orientação a Objetos e que o Java a utiliza muito bem.

Agora, podemos adicionar filmes no arranjo, não é?

Jacqueline: Podemos. Como faremos isso?

Vimos que nossas classes têm métodos. Portanto, desceremos uma linha e escreveremos listaDeFilmes. e veremos na lista do sistema os métodos disponíveis.

Entre eles, temos o add() que adiciona um filme. Vamos dar "Enter" nesta opção, o que a adicionará automaticamente ao nosso código.

Entre os seus parênteses, adicionaremos o filmeDoPaulo que entrará em primeiro lugar, pois é nota 10.

// Código omitido

ArrayList<Filme> listaDeFilmes = new ArrayList<>();
listaDeFilmes.add(filmeDoPaulo);

Abaixo dele, podemos adicionar os outros, copiando o método e mudando o filme entre os parênteses.

// Código omitido

ArrayList<Filme> listaDeFilmes = new ArrayList<>();
listaDeFilmes.add(filmeDoPaulo);
listaDeFilmes.add(meuFilme);
listaDeFilmes.add(outroFilme);

Paulo: Podemos inclusive dar um System.out.println() com o listaDeFilmes.size() para ver quantos elementos foram adicionados.

Jacqueline: Exatamente. Vamos fazer isso na linha de baixo. Entre os parênteses, adicionaremos o texto "Tamanho da lista", concatenando-o com o listaDeFilmes.size().

// Código omitido

ArrayList<Filme> listaDeFilmes = new ArrayList<>();
listaDeFilmes.add(filmeDoPaulo);
listaDeFilmes.add(meuFilme);
listaDeFilmes.add(outroFilme);
System.out.println("Tamanho da lista" + listaDeFilmes.size());

Paulo: Podemos mostrar também outro método. Vamos imprimir o nome do primeiro filme. Na linha de baixo, adicionaremos o System.out.println(), pegaremos o primeiro filme e devolveremos o seu nome.

Jacqueline: Exatamente. Vamos adicionar um novo System.out.println() que receberá entre parênteses o texto "Primeiro filme", concatenado com a listaDeFilmes.get(0), onde get(0) retorna a posição desejada, que neste caso é a primeira (em Java, iniciamos a lista na posição 0).

// Código omitido

ArrayList<Filme> listaDeFilmes = new ArrayList<>();
listaDeFilmes.add(filmeDoPaulo);
listaDeFilmes.add(meuFilme);
listaDeFilmes.add(outroFilme);
System.out.println("Tamanho da lista" + listaDeFilmes.size());
System.out.println("Primeiro filme" + listaDeFilmes.get(0));

Paulo: Uhum. Se fizermos get(1), ele retornará o meuFilme. No caso de get(2), será o outroFilme.

Jacqueline: Exatamente. Podemos adicionar um .getNome() à esquerda do listaDeFilmes.get(0).

// Código omitido

ArrayList<Filme> listaDeFilmes = new ArrayList<>();
listaDeFilmes.add(filmeDoPaulo);
listaDeFilmes.add(meuFilme);
listaDeFilmes.add(outroFilme);
System.out.println("Tamanho da lista" + listaDeFilmes.size());
System.out.println("Primeiro filme" + listaDeFilmes.get(0).getNome());

Paulo: Esta sintaxe é interessante. Fizemos listaDeFilmes.get(0).getNome(). É comum invocarmos métodos conectados, quase que concatenados.

Quando invocamos algo no get(0), recebemos um filme. Dado este filme, podemos adicionar outro ., o que nos fornecerá uma lista de autopreenchimento do sistema que elenca os métodos de filme, mostrando que ele já sabe que um filme virá por aí.

Jacqueline: Exato.

Paulo: Poderíamos ter quebrado este comando em duas linhas, dizendo "Primeiro filme" + listaDeFilmes.get(0) e em seguida "Primeiro filme" + listaDeFilmes.getNome(), mas a verdade é que ninguém escreve assim.

É obvio que quando estamos aprendendo somos mais didáticos. Aqui, poderíamos escrever só filmes. É bastante raro no mundo real utilizarmos um nome extenso como listaDeFilmes.

No entanto, tomamos esta liberdade aqui para que tudo fique bem claro e simplificado.

Podemos rodar o código. Ficou interessante.

Reparem que eu e a Jaque sabemos os dois métodos utilizados de cor, pois os utilizamos todo dia. Você verá que todo mundo que utiliza o Java, sabe alguns.

Jacqueline: Isso. Quando abrirmos a documentação, veremos outros deles.

Vamos rodar o código clicando no botão "Run" para ver o que acontecerá no nosso Principal.

Na aba "Run", aberta pelo sistema abaixo da aba de código, veremos a seguinte mensagem:

Tamanho da lista3

Primeiro filmeDogville

Faltaram os espaços após "lista" e "filme". Voltando ao código, daremos o espaçamento no final de "Tamanho da lista" e de "Primeiro filme".

System.out.println("Tamanho da lista " + listaDeFilmes.size());
System.out.println("Primeiro filme " + listaDeFilmes.get(0).getNome());

Apesar disso, vemos que ele sabe que temos 3 itens na lista e que o primeiro filme é Dogville. Ele nos mostrou o tamanho com size e o nome do primeiro filme da lista, que obtivemos da posição 0.

Agora, podemos imprimir toda a lista para ver o que acontece.

Se fizermos System.out.println() e mandarmos o listaDeFilmes, ele saberá imprimir isso?

// Código omitido

System.out.println("Primeiro filme " + listaDeFilmes.get(0).getNome());
System.out.println(listaDeFilmes);

Eu sei que posso imprimir o texto, chamar um método e concatenar variáveis. Mas se eu mandar a lista inteira? Será que vai sair tudo? Vamos ver, clicando no botão "Run" e rodando o código.

Na aba "Run", aberta pelo sistema abaixo da aba de código, veremos uma mensagem que já vimos antes:

[br.com.alura.screenmatch.modelos.Filme@378bf509, br.com.alura.screenmatch.modelos.Filme@7699a589, br.com.alura.screenmatch.modelos.Filme@58372a00]

Ele retornou entre colchetes o nome da classe, uma arroba e três endereços. Pode ser que não esteja muito claro o motivo pelo qual ele imprime assim. No próximo vídeo, entenderemos o porquê.

Paulo: O principal deste vídeo é que começamos a trabalhar com uma classe muito usada no dia-a-dia: a ArrayList. A partir de agora, tiraremos vários ensinamentos e entenderemos que tudo o que foi visto sobre heranças, interfaces e encapsulamento é utilizado por todo mundo.

Tanto que a biblioteca principal do Java é escrita usando esses princípios.

Deixamos uma charada com o último retorno para pensarmos nos motivos por trás dele. Para entender melhor, abriremos a documentação, entenderemos o que é este arroba, quem é a ArrayList e onde ela está.

Além de aprender a trabalhar com uma coleção de objetos — tarefa fundamental —, queremos que você aprenda a raciocinar com base em modelos de classes de Orientação a Objetos. Isso é muito importante, não só no Java, mas como em diversas linguagens e frameworks.

Você enxergará que existem diversos lugares nos quais os conceitos de Orientação a Objetos são utilizados.

Isso vai te ensinar a usar esses conceitos no seu sistema, pois você verá que as grandes bibliotecas principais, especialmente as mais recentes, foram pensadas com base em interfaces, em classes, em heranças e até mesmo nos construtores que veremos posteriormente.

Veremos várias coisas que começarão a se encaixar. Por isso, esta formação está muito interessante.

Jacqueline: Isso aí. Até daqui a pouco!

Coleção de filmes - Entendendo a hierarquia de classes e métodos

Paulo: Jaque, nós mostramos a lista de filmes e saiu um monte de coisa estranha. Também usamos os métodos size() e get() da classe ArrayList.

Chegou a hora de abrir a Documentação dessa classe, algo que fazemos com muita frequência.

Se posicionarmos o mouse por cima desse get(), ele mostra um pouco da documentação, nos dizendo que:

Observação: Atente-se à versão do Java utilizada. Busque utilizar a mesma versão que as pessoas instrutoras para evitar erros no código.

Temos uma breve explicação no IntelliJ, mas existe uma página HTML chamada Javadoc (Documentação do Java), muito utilizada, e que já mostramos anteriormente.

Várias linguagens possuem páginas HTML onde documentam o funcionamento de suas classes e métodos.

Jacqueline: Exatamente, Paulo. Vamos abri-la no navegador.

É extremamente importante termos este hábito de posicionar o mouse em cima do código, buscar a classe fonte de cada método e verificar na documentação o que podemos usar.

Aqui na página da ArrayList dentro do Javadoc, veremos o que temos pronto para não precisarmos refazer um processo que já existe.

Paulo: Disponibilizamos o link da página aqui, mas em outros casos, basta digitar "javadoc array list" no Google, que ele te direcionará para esta página (provavelmente em outra versão do Java). Se a versão for diferente, basta trocar o número da versão na URL.

Temos o link para a Home do Javadoc, o qual indicamos manter sempre salvo nos favoritos.

Na época em que a internet era mais complicada, fazíamos download e guardávamos a documentação localmente. O Java nasceu nesta época!

Hoje, quando instalamos o JDK, a documentação vem junto.

Voltando à página da ArrayList, no início temos o resumo da classe, como ela funciona, um tal de java.lang.Object, um java.util.AbstractCollection<E>.

Mais abaixo, temos uma documentação que dá informações sobre o ArrayList:

Ela também nos dá exemplos de como utilizar uma lista em casos de multithread, e no diz que esta classe existe desde a versão 1.2 do Java. Inclusive, ele nos mostrará quais são seus construtores e métodos.

Ele mal informa sobre atributos, pois, como já aprendemos, na maioria dos casos, os atributos de uma classe são privados. Por causa disso, não temos acesso. Se não temos acesso, não há motivo para que constem na documentação.

Jacqueline: Exatamente.

Paulo: Neste curso que você e o time prepararam, Jacque, vamos encaixando muita coisa. Isso que é o legal no Java.

Tudo o que ensinamos até aqui acontece no mundo real. Vamos observar o método add(), por exemplo.

Jacqueline: Exatamente. Temos o add(), o addAll()

Paulo: Temos até uma versão de add() que recebe um int. Com ele, poderíamos adicionar um elemento em uma posição determinada. Ele faria isso empurrando os outros.

Temos um monte de métodos, para várias tarefas, entre elas a remoção e a troca de posição do elemento.

Jacqueline: Vários métodos.

Paulo: Veremos que alguns serão muito utilizados, e outros, menos. Aqui, usaremos bastante alguns deles, e com isso ganharemos familiaridade.

É normal ter dúvidas entre, por exemplo, size, length e quantity, entre nomes de métodos e assim por diante. É normal no começo, pois cada linguagem costuma usar diferentes comandos.

Recomendamos, sempre que possível, adicionar um . no código, e consultar a lista de métodos sugerido pelo sistema.

Jacqueline: Exato. Voltando ao código, quando rodamos, vimos na impressão da lista, por meio do comando System.out.println(listaDeFilmes), foi exibido um retorno estranho.

Imaginamos que sairia a lista com todos os filmes, mas não saiu. Por quê?

Paulo: Podemos passar o mouse por cima desse tal de println().

Jacqueline: Faremos isso. Veremos na caixa aberta pelo sistema as funções deste método: ele imprime a versão textual de um objeto.

Vamos pressionar "Ctrl+clique" neste comando. Com isso seremos direcionados para o arquivo PrintStream.java, onde veremos o código completo do método public void println.

Paulo: Por meio do "Ctrl+clique" em um método — até mesmo naqueles que não criamos —, o IntelliJ abre o código-fonte do Java e nos mostra. Não vamos entendê-lo direito, mas é interessante entender como chegamos lá.

Jacqueline: No PrintStream.java, vemos várias versões do println(), as quais recebem entre seus parênteses, parâmetros diferentes: um recebe uma String x, outro um Object x, e assim por diante.

Posteriormente, entenderemos que Object é esse.

public void println(String x) {
    if (getClass() == PrintStream.class) {
        writeln(String.valueOf(x));
    } else {
        synchronized (this) {
            print(x);
            newLine();
        }
    }
}

// Código omitido

public void println(Object x) {
    String s = String.valueOf(x)
    if (getClass() == PrintStream.class) {
        // need to apply String.valueOf again since first invocation
        // might return null
        writeln(String.valueOf(s));
    } else {
        synchronized (this) {
            print(s);
            newLine();
        }
    }
}

Temos que ser investigativos. Se posicionarmos o mouse em cima do println, ele tenta fazer um String valueOf() de algum texto. Ali, vemos um link que nos mostra a tentativa de obter um valor de um local chamado toString()

See Also: Object.toString()

Paulo: Vamos com calma: a Jaque fez uma investigação como se não entendesse nada e precisasse entender o que está acontecendo. Queremos mostrar que dá para chegar em conclusões dessa forma.

O importante é entender o toString() e o Object.

A Jacque voltará ao Javadoc pelo navegador, digitará "object" no campo de busca e abrirá a documentação de uma classe chamada Object, localizada dentro do pacote java.lang. Este é o único pacote do Java que não precisamos importar escrevendo import.

A classe Object é muito importante no Java, pois todas as classes dão extends em Objects, ou seja são filhas dele — quer queiramos, ou não.

Voltando ao código, abriremos a classe Filme no arquivo File.java. No topo desse código, escrevemos extends Titulo, correto?

Jacqueline: Isso.

Paulo: Agora, abriremos a classe Titulo no arquivo Titulo.java. Escrevemos extends nela? Não.

Contudo, nos casos em que não estendemos nada, o Java cria um extends Object de forma invisível para nós. Se determinada classe não for filha de Object, será neta, bisneta, e assim por diante.

No geral, dizemos que Object é uma superclasse de todas as classes que escrevemos ou escreveremos no Java. Logo, todos os seus descendentes possuem os seus métodos.

Entre eles, temos o toString(), que pode ser visto da documentação. Esta diz que se trata de um método que devolve uma representação do objeto como String.

StringtoString()Returns a String representation of the object.

Se clicarmos no link toString() na coluna do meio, seremos levados à página do método toString(). Na seção "Implementation Requirements" (requisitos de implementação), temos o resumo informando que, no toString() para Object, ele devolve o nome da classe, uma arroba e um código hexadecimal.

getClass().getName() + '@' + Integer.toHexString(hashCode())

É exatamente isso que está acontecendo.

Investigamos e descobrimos que:

O legal de herdar métodos é poder reescrevê-los por meio de um @Override.

Jacqueline: Exatamente. Voltaremos ao código.

Se todo mundo descende de Object, acessaremos a classe Filme e diremos que o nosso toString() deverá mostrar coisas diferentes do retorno padrão.

Paulo: Antes disso, acessaremos a classe Principal, onde estamos imprimindo o nome do primeiro filme.

// Código omitido

System.out.println("Primeiro filme " + listaDeFilmes.get(0).getNome());

// Código omitido

Copiaremos e colaremos esta linha abaixo do println da lista, substituindo o .getNome() por .toString() do filme. Vamos ver se todo mundo realmente possui este método. Quando digitarmos o ponto, veremos na caixa de sugestões a opção toString(), provando que ela está disponível para ser utilizada aqui.

Para efeitos de discernimento, vamos trocar o texto de "Primeiro filme" para "toString do filme".

// Código omitido

System.out.println("Primeiro filme " + listaDeFilmes.get(0).getNome());
System.out.println(listaDeFilmes);
System.out.println("toString do filme " + listaDeFilmes.get(0).toString());

Se escrevêssemos toAbobrinha(), por exemplo, o código não compilaria.

Se rodarmos agora, o que aparecerá no toString() do filme 0 (Dogville)?

Jacqueline: Vamos rodar.

A aba "Run" abrirá e exibirá o resultado abaixo:

toString do filme br.com.alura.screenmatch.modelos.Filme@378bf509

Continuamos exibindo o formato estranho de filme, pois ainda não o modificamos.

Paulo: Em muitos casos, isto é o suficiente. Mas para questões de debug (depuração), vamos sobrescrever o toString do filme. Como faremos isso?

Jacqueline: Acessando a classe de filmes, em Filme.java, veremos que já fizemos isto antes: sobrescrevemos o método getDuracaoEmMinutos(), pois a série possui uma contagem diferente em relação ao filme.

Abaixo de getClassificacao(), escreveremos toString(). Quando começarmos a digitar, a IDE nos mostrará uma caixa com a opção toString, oferecendo a chance de sobrescrevê-lo. Se dermos "Enter", a estrutura do método será adicionada automaticamente, e acima dele virá um @Override.

@Override
public String toString() {
    return super.toString();
}

Esta estrutura devolve por padrão o mesmo que a mãe: um super.toString();. Contudo, conforme vimos anteriormente, não queremos este retorno.

No lugar deste, retornaremos um "Filme: " concatenado com this.getNome().

Paulo: Aqui podemos usar o this. Sugiro adicionar também o ano de lançamento entre parênteses, com um espaço antes do parêntese de abertura.

Jacqueline: Boa. Será "Filme: " + this.getNome() + " (" + this.getAnoDeLancamento(), e concatenamos com o fechamento de parênteses ")".

@Override
public String toString() {
    return "Filme: " + this.getNome() + " (" + this.getAnoDeLancamento() + ")";
}

Paulo: Para entender melhor:

  1. Abrimos e fechamos aspas com a palavra "Filme" em seu interior
  2. Adicionamos o nome do filme
  3. Entre aspas, adicionamos um espaço e a abertura dos parênteses
  4. Adicionamos o ano de lançamento
  5. Entre aspas, adicionamos o fechamento dos parênteses

É possível configurar este retorno de várias maneiras, conforme a forma de visualização desejada. Algumas pessoas usam os colchetes, ou chaves para parecer um JSON.

O importante é que o método precisa se chamar toString() e precisa ser reescrito. Se mudarmos o nome, não será uma mudança de comportamento do método original (um dos pilares do polimorfismo e da herança).

Jacqueline: Exato.

Paulo: Antes de rodar, voltaremos ao Principal.java para entender o que acontecerá.

Desta vez, quando chamarmos o toString() do get(0), esperamos que apareça o filme junto ao seu ano de lançamento.

Jacqueline: Exatamente. Vamos conferir, rodando o código.

[Filme: Dogville (2003), Filme: O poderoso chefão (1978), Filme: Avatar (2023)]

toString do filme Filme: Dogville (2003)

Paulo: O retorno exibiu o nome do filme e o ano, como esperado.

Isto não é tudo: o mais incrível é que a linha de cima, onde imprimimos a ArrayList, exibe agora o toString() de cada um dos filmes.

Por que isso ocorre? Se verificarmos a documentação do ArrayList, veremos que o seu toString() reescrito faz um for nos elementos e chama o toString() de cada um deles.

O bonito é que as coisas estão se cruzando. O toString() recém-aprendido é utilizado também pelo ArrayList.

Jacqueline: Isso.

Paulo: Vamos abrir o navegador, buscar por "arraylist" no site do Javadoc e abrir novamente a documentação do Array List. Nela, veremos que este comportamento é esperado.

Pressionaremos "Ctrl+F" na página e escreveremos "tostring" para buscar a seção deste método. Clicaremos no mesmo link toString() de antes para acessar novamente a página deste método.

Nela, veremos que o retorno é uma representação da coleção e todos os elementos chamam o valueOf(). Este, se investigarmos, é capaz de pegar o toString() ou o null, se a referência for nula.

Jacqueline: Isso. Ele cita também que realiza uma separação com vírgula dentro de colchetes.

Paulo: Nesta aula, vimos bastante conteúdo:

Tudo está encapsulado, e as coisas vão se encaixando. Este processo é muito bonito. A seguir, vamos mergulhar mais fundo nele.

Jacqueline: Isso aí. Até daqui a pouco.

Sobre o curso Java: trabalhando com listas e coleções de dados

O curso Java: trabalhando com listas e coleções de dados possui 131 minutos de vídeos, em um total de 53 atividades. Gostou? Conheça nossos outros cursos de Java em Programação, ou leia nossos artigos de Programação.

Matricule-se e comece a estudar com a gente hoje! Conheça outros tópicos abordados durante o curso:

Aprenda Java acessando integralmente esse e outros cursos, comece hoje!

Conheça os Planos para Empresas