Exercícios práticos de
Linguagens de Programação I - 2005/2006

Página actualizada às . Comentários para pedro.coutinho@dsi.uminho.pt 

Os exercícios incidem sobre as teóricas da semana anterior. Os enunciados são baseados nos exercício do livro "Objects First with JAVA" (Primeira Edição).

Semanas 1º Semestre

26 Setembro 3 Outubro 10 Outubro 17 Outubro 24 Outubro 31 Outubro
7 Novembro 14 Novembro 21 Novembro 28 Novembro 5 Dezembro 12 Dezembro


1º Semestre


Semana de 19 Setembro

Sumário

Horário especial de abertura do segundo ano da LIG: não há aulas excepto apresentação da disciplina 3ª feira (EE 0.10, 10h às 12h) e marcação de turnos (EE0.10, 15h às 17h)

Semana de 26 Setembro

Sumário

Ajustes de turnos, apresentação do laboratório.  Primeiro contacto com ferramenta BlueJ: criar objectos, invocar métodos, inspeccionar estado de um objecto.

Projecto shapes (chapter 1) 

Exercício 1.7 

Crie vários objectos círculo. Poderá fazê-lo seleccionando new Circle() do menu associado à classe Circle. Faça com que os círculos criados fiquem visíveis, depois mova-os pela janela de apresentação utilizando os métodos “move”. Transforme um dos círculos num círculo grande e amarelo ("yellow"), e outro num círculo pequeno e verde ("green"). Tente o mesmo com outro tipo de formas geométricas: crie alguns triângulos e quadrados. Altere as suas posições, tamanhos e cores. 

Exercício 1.8 

Tendo em conta os objectos criados no Exercício 1.7, faça inspecção aos seus estados. Tente alterar o estado de um objecto (por exemplo, por invocação do método moveLeft) enquanto o “object inspector” estiver aberto. Deverá observar os valores no “object inspector” a serem alterados.

Semana de 3 Outubro

Sumário

Exploração da  ferramenta BlueJ (continuação): interacção entre objectos, criar novos métodos, ler e entender assinaturas dos métodos.

Projecto picture (chapter 1) 

Exercício 1.13 [Resolução]

No código fonte da classe Picture, encontre a parte que realmente desenha a figura. Altere-a para que o Sol seja azul em vez de amarelo.

Exercício 1.16 [Resolução]

Implemente um método para simular o pôr-do-sol. De acordo com o exercício 1.15, esse método deverá fazer com que o Sol na figura se movimente lentamente para baixo. Nesse exercício é sugerida a utilização do método slowMoveVertical da classe Circle. Assim sendo, poderemos invocar o método draw para a apresentar a imagem original (com o Sol no céu) e depois invocar o novo método para simular o pôr-do-sol (sunset).

Projecto lab-classes (chapter 1) 

Exercício 1.19 

Crie um objecto da classe LabClass. Observe a assinatura do construtor. Especifique o número máximo de alunos na aula criada (um inteiro). 

Exercício 1.21 

Observe a assinatura do método enrollStudent e verifique que o parâmetro esperado é do tipo Student. Crie agora alguns objectos de estudantes (Student). Invoque o método enrollStudent do objecto instância de LabClass criado anteriormente (Exercício 1.19), seleccionado o valor a passar ao parâmetro com um click sobre um dos objectos instância de Student já criados. Faça o mesmo para outros estudantes. 

Exercício 1.25 

No objecto da classe LabClass criado no Exercício 1.19, atribua-lhe um docente (instructor), uma sala (room) e uma hora (time). Invoque o método printList para imprimir a informação referente à aula, incluindo a lista de alunos inscritos.


Semana de 10 Outubro

Sumário

Construção de métodos, métodos acessionais e mutantes, estruturas condicionais.

Projecto better-ticket-machine (chapter 2)

Exercício 2.26 [Resolução]

Implemente o método empty que simula o efeito de retirar todo o dinheiro da bilheteira. O método não retorna nada (void), limitando-se apenas a colocar a zero o valor do campo total. Será que o método necessita de algum parâmetro? Teste o método empty. Para tal crie uma bilheteira, insira dinheiro, emita bilhetes, teste o total de dinheiro inserido e depois retire todo o dinheiro da bilheteira. Considera o método empty um método mutante?

Exercício 2.36 [Resolução]

Implemente o método emptyMachine que simula o efeito de retirar todo o dinheiro da bilheteira. Este método deve retornar o total de dinheiro inserido até ao momento, para além de colocar a zero o valor do campo total.

Exercício 2.37 [Resolução]

Como classifica o método emptyMachine: acessional, mutante ou ambos?

Projecto lab-classes (chapter 1)

Exercício 2.40 [Resolução]

Qual será o valor retornado pelo método getLoginName de um estudante com nome (name) “José Silva” e número (id) “123456”?

Exercício 2.41 [Resolução]

Crie uma estudante chamada “Ana” com número “654321”. O que acontece quando é invocado o método getLoginName? Porque é que acontece?

Exercício 2.43 [Resolução]

Altere o método getLoginName da classe Student de forma a gerar sempre um nome de acesso (login name), mesmo quando os campos do nome (name) e do número (id) não sejam suficientemente grandes. Para strings menores do que o necessário, utilize toda a string.


Semana 17 Outubro

Sumário

Utilização do debugger do BlueJ. Interacção entre objectos. Apresentação do enunciado do trabalho prático da disciplina.

Projecto mail-system (chapter 3)

Exercício 3.21

No projecto mail-system (chapter 3) crie uma instância de MailServer (o servidor de mensagens). Crie depois duas instâncias de MailClient. Durante a criação das instâncias de MailClient é necessário indicar a instância do MailServer que lhe fica associado, ou seja o servidor de correio electrónico do cliente que se está a criar. Para além do servidor, será ainda necessário especificar o nome do utilizador do cliente de correio electrónico, ficado cada cliente associado a um único utilizador.
Explore os objectos MailClient criados: experimente enviar mensagens de um cliente para outro (método sendMessage) e receber mensagens (método getNextMailItem ou printNextMailItem).

Exercício 3.22

Desenhe um diagrama de objectos que descreva a situação após a criação de um servidor e de três clientes de correio electrónico. Nota: não se esqueça de observar o código fonte das diversas classes! (mas não muito...)

Exercício 3.23, 3.24, 3.25, 3.26, 3.27, 3.28

Esta sequência de exercícios permite explorar o debugger do BlueJ.
3.23 - Cenário de utilização: criar um servidor de correio electrónico; criar dois clientes para os utilizadores "Ana" e "Paulo" (para facilitar a utilização das instâncias, os seus próprios nomes deveriam ser "ana" e "paulo", respectivamente). Agora envie uma mensagem do utilizador "Ana" (método sendMessage na instância "ana") para o utilizador "Paulo". ATENÇÃO: Não leia já a mensagem na instância "paulo"! Isso vai ser feito nos exercícios seguintes, mas com utilização do debugger do BlueJ.
3.24 - Ponto de paragem (breakpoint): Edite a classe MailClient e adicione um breakpoint na primeira linha efectiva do método printNextMailItem.
3.25 - Passo-a-passo simples (step): Na instância "paulo" invoque o método printNextMailItem. Observe o valor do estado de execução da janela do debugger e avance apenas uma linha na execução do código (botão Step).
3.26 - Questão: Antes de voltar a avançar com o botão Step, preveja qual será a próxima linha a ser executada. Avance agora mais uma linha com o botão step. A sua previsão estava certa ou errada? O que é que aconteceu e porquê?
3.27 - Questão: Depois de terminar a execução do método printNextMailItem do exercício anterior (3.26), volte a invocar este método. Avance com o debugger sobre o método tal como anteriormente. O que é que observa? Explique a razão de ter sucedido.
3.28 - Passo-a-passo para dentro de método (step into): Volte a enviar uma mensagem de Ana para Paulo. Invoque o método printNextMailItem no cliente "paulo". Desta vez, assim que atingir a linha
item.print() utilize o botão Step Into em vez do botão Step. Assegure-se que consegue ver a janela de terminal (onde as mensagens são apresentadas) enquanto avança na execução. O que é que observa? Explique o que vê.

Exercício 3.29

Coloque um ponto de paragem (breakpoint) na primeira linha efectiva do método sendMessage da classe MailClient. Invoque agora esse método para enviar uma mensagem e utilize o botão Step Into da janela do debugger para entrar dentro do construtor de itens de correio electrónico (MailItem). Observe agora na janela do debugger as variáveis locais bem como as variáveis de instância a serem inicializadas à medida que avança na execução passo-a-passo no construtor. Avance até ao final do método sendMessage podendo optar por entrar dentro do método post do servidor durante a execução.

Exercício 3.30

Por observação do código fonte, execução integral de métodos, definição de pontos de paragem e execução de métodos com o debugger, procure entender as classes MailItem e MailClient. Procure igualmente entender a classe MailServer, tendo em conta que utiliza conceitos apresentados em capítulos posteriores ao Capítulo 3, mas já apresentados nas aulas teóricas.
Desenhe diagramas de objectos para explicitar o funcionamento dessas classes.


Semana 24 Outubro

Sumário

Colecções de objectos (ArrayList). Iterações em colecções.

Projecto auction (chapter 4)

Este projecto implementa um sistema de leilão. A classe Lot representa cada lote de artigos a serem leiloados. A classe Auction representa um leilão, tendo informação sobre os lotes a serem leiloados. A classe Person representa as pessoas que fazem uma licitação (oferta) para comprar um lote. A classe Bid representa as licitações (ofertas) feitas para um determinado lote.

Exercício 4.12 (alterado) [Resolução]

Procure exemplos de casting nos métodos da classe Auction.

Exercício 4.13 [Resolução]

O que acontece se tentar compilar a classe Auction sem um dos casting? Por exemplo, altere o método showLots de forma a que a primeira instrução do bloco do ciclo while passe a ser:

    Lot lot = it.next();

e teste o resultado da alteração.

Exercício 4.14 [Resolução]

Acrescente um novo método à classe Auction chamado close.  Este método deverá percorrer a colecção de lotes (lots) e imprimir os seus detalhes. Os detalhes referentes aos lotes que já tenham sido vendidos devem incluir o nome da pessoa que o comprou, bem como o valor pelo qual foi comprado. Sempre que um lote não tenha sido vendido, deve imprimir-se uma mensagem que indique esse facto.

Exercício 4.16 [Resolução]

Suponha que a classe Auction contém um método que permite a remoção de lotes. Assumindo que o número de cada  um dos restantes lotes (ver campo number na classe Lot) não é alterado sempre que ocorra uma remoção, qual será o impacto que esta nova operação teria no método getLot?

Exercício 4.17 [Resolução]

Reescreva o método getLot de forma a que este não associe o número de lote ao índice (número-de-lote -1) na colecção. Poderá assumir que os lotes são sempre por ordem crescente do seu número de lote.

Exercício 4.18 [Resolução]

Acrescente um novo método à classe Auction chamado removeLot, o qual deverá ter a seguinte assinatura:

    /**
     *    Remove o lote identificado pelo número de lote.
     *    @param    number    O número do lote a ser removido.
     *    @return    O lote com o número indicado, ou null no caso de não existir.
    */
    public Lot removeLot(int number)

Este método não deverá assumir que um lote com um determinado número está armazenado numa posição em particular dentro da colecção.


Semana 31 Outubro

Sumário

Classes da biblioteca Java. Exemplos de utilização de Maps (mapas): a classe java.util.HashMap. Documentação das classes em Java.

Nota: os exercícios desta semana são para ser feitos num novo projecto e não num projecto já existente, tal com tem vindo a acontecer nas aulas anteriores.

Exercício 5.21

O que é um HashMap? Qual é a sua função e como utilizá-lo? A resposta a estas questões deve ser feita tendo por base a consulta da documentação da biblioteca Java (caso tenha a documentação localmente no seu computador, poderá consultá-la aqui).

Exercício 5.22 [Resolução]

Crie um  novo projecto com uma classe chamada MapTester que utiliza um HashMap para implementar uma lista telefónica na qual apenas são armazenados os nomes e os números de telefone de diversas pessoas. Na classe criada implemente os seguintes métodos:

    public void enterNumber(String name, String number) - que permite inserir na lista telefónica uma nova pessoa e respectivo número de telefone.

    public String lookupNumber(String name) - que permite obter o número de telefone de uma determinada pessoa.

Estes dois métodos devem utilizar os métodos "put" e "get" da classe HashMap de forma a implementar a sua funcionalidade.

Exercício 5.23 [Resolução]

O que acontece quando se adiciona uma nova entrada (par chave/valor) num mapa (por exemplo, o HashMap) com uma chave já existente?

Exercício 5.24 [Resolução]

O que acontece quando se adiciona uma nova entrada (par chave/valor) num mapa (por exemplo, o HashMap) com um valor já existente?

Exercício 5.25 [Resolução]

Como é que se verifica que uma chave já existe no mapa? Apresente exemplos do código Java que constem do projecto desta aula.

Exercício 5.26 [Resolução]

O que acontece quando se tenta obter um valor cuja chave não existe no mapa?

Exercício 5.27 [Resolução]

Como se obtém o número de entradas (pares chave/valor) de um mapa?

Exercício Documentação (baseado na secção 5.10 do livro)

Acrescente comentários de  documentação (/** ... */) na classe MapTester, utilizando os diversos símbolos especiais para formatação (por exemplo, @param). Utilize a vista "interface" do editor de código fonte do BlueJ (no botão mais à direita do editor, com opções "implementation" e "interface",  escolher "interface") e veja a documentação resultante. Utilize ainda a funcionalidade "Project Documentation" do BlueJ (menu Tools) para gerar a documentação do projecto em html.
Mais informação sobre documentação de código Java aqui


Semana 7 Novembro

Sumário

Hierarquia de classes em Java. Superclasses e subclasses. Tipos e subtipos.

Projecto dome-v2 (chapter 8)

Exercício 8.1 (adaptado para o projecto dome-v2)

Abra o projecto dome-v2 (versão de DoME com hierarquia de classes). Observe o diagrama de classes, nomeadamente a hierarquia de classes dos itens (cd's e vídeos) a inserir na base de dados multimédia. Crie alguns cd's e alguns vídeos. Crie igualmente um objecto de base de dados (classe Database). Insira os cd's e os vídeos na base de dados e depois liste o conteúdo da mesma.

Exercício 8.6 [Resolução]

Ainda no projecto dome-v2, coloque um ponto de paragem (breakpoint) na primeira linha do construtor da classe CD. Depois crie um novo objecto da classe CD. Assim que aparecer a janela do debugger, use o botão Step Into para avançar ao longo do código fonte. Observe as variáveis de instância (campos) e sua inicialização. Descreva o que observa.

Exercício 8.7 [Resolução]

Adicione uma nova classe para jogos de vídeo ao projecto dome-v2. Para além dos campos que todos os itens têm, essa classe ainda tem os campos numberOfPlayers e platform, respectivamente para guardar o número de jogadores e a plataforma de execução dos jogos de vídeo. Crie alguns objectos dessa nova classe e teste se todos os seus métodos (incluindo os que são herdados) funcionam tal como esperado.
Nota: aproveite este exercício para repensar a resposta dada ao exercício 8.10 apresentado na aula teórico-prática da semana de 31 de Outubro.

Os próximos dois exercícios não são sobre nenhum projecto já existente.

Exercício 8.8 [Resolução]

Considere as seguintes classes: Pessoa, Professor, Estudante, Doutorando. Professor e Estudante são ambas subclasses de Pessoa. Doutorando é subclasse de Estudante.
Quais das seguintes atribuições estão correctas e porquê?

    Pessoa p1 = new Estudante();
    Pessoa p2 = new Doutorando();
    Doutorando d1 = new Estudante();
    Professor prof1 = new Pessoa();
    Estudante e1 = new Doutorando();

    e1 = p1;
    e1 = p2;
    p1 = e1;
    prof1 = e1;
    e1 = d1;
    d1 = e1;

Teste as suas respostas ao exercício anterior criando as classes referidas no mesmo e experimentando-as no BlueJ.


Semana 14 Novembro

Sumário

Hierarquia de classes em Java (continuação). Tipos estáticos e tipos dinâmicos. Redefinição de métodos (overriding). Procura dinâmica de métodos. Polimorfismo de métodos.
Trabalho Prático: ponto de situação dos vários grupos de trabalho após entrega do relatório intermédio.

Projecto dome-v2 (chapter 8)

Exercício 9.1 [Resolução]

Abra a sua última versão do projecto DoME. (Pode utilizar a versão dome-v2 caso não tenha ainda a sua própria versão). Remova o método print da classe Item e coloque-o na classe Video e na classe CD. Proceda à compilação das várias classes. O que observa?

Exercício 9.2 [Resolução]

No seu projecto DoME, acrescente novamente o método print na classe Item. Rescreva o corpo do método de forma imprimir apenas o title. Depois altere os métodos print da classe CD e da classe Video, de modo a imprimir apenas a informação relativa ao artista, no caso do CD; e a imprimir apenas informação relativa ao director, no caso do Video. Desta forma irá solucionar os erros que surgiram no exercício anterior.
Antes de executar, preveja qual dos métodos print é que irá ser executado após invocação do método list da classe Database.
Experimente agora, inserindo um objecto da classe CD e um objecto da classe Video na base de dados Database e depois invoque o método list dessa mesma classe. Qual foi o método print invocado? A sua previsão estava correcta? Tente explicar o que observou.

Exercício 9.3 [Resolução]

Altere a última versão do projecto DoME de forma a incluir uma chamada super no método print de cada subclasse da classe Item, invocando assim o método print dessa classe. Efectue alguns testes. O resultado é o esperado? Detecta algum problema com esta solução?

Exercício 9.8 [Resolução]

A invocação do método print da superclasse torna a apresentação da informação sobre os itens algo restritiva, na medida em que esta fica dependente na forma como o valor da variáveis de instância são apresentados. Efectue as alterações necessárias à classe Item e ao método print da classe CD de modo a apresentar a informação da seguinte forma:

CD: Frank Sinatra: A Swinging Affair *
    16 tracks, 64 minutes
    my favorite Sinatra album

Note que o texto nas áreas a sombreado representam detalhes de informação da superclasse.
Tenha em atenção que as alterações feitas à classe Item devem continuar a preservar o encapsulamento, sendo apenas aceitável que o mesmo seja quebrado quando se trate de uma subclasse. Assim , sempre que se justifique, sugere-se a utilização do qualificador protected nas variáveis de instância da classe Item.


Semana 21 Novembro

Sumário

Classes abstractas e interfaces em Java.
Trabalho prático: Esclarecimento de dúvidas referentes à implementação.

Projecto foxes-and-rabbits-v2 (chapter 10)

Este projecto simula o comportamento de uma população de animais numa determinada região (classe Field) modelada por uma matriz com várias posições (classe Location). Os animais considerados na simulação são as raposas (classe Fox) e os coelhos (classe Rabbit). A simulação propriamente dita é feita pela classe Simulator, que povoa o espaço com animais (raposas e coelhos) e os faz actuar (movimentar, caçar, etc) nesse espaço. Existem outras classes no projecto, nomeadamente as classes SimulatorView, FieldStats e Counter, responsáveis pela visualização gráfica da simulação e de alguns dados estatísticos sobre a  mesma.

Exercício 10.30 [Resolução]

Abra o projecto foxes-and-rabbits-v2. Mova o método canBreed das classes Fox e Rabbit para a classe Animal e reescreva-o da seguinte forma:

    /**
     * An animal can breed if it has reached the breeding age.
     */
    public boolean canBreed()
    {
        return getAge() >= getBreedingAge();
    }

Observe a invocação do método getBreedindAge. Acrescente agora o método getBreedindAge nas classes Fox e Rabbit de forma a comportar-se como o método acessional da constante BREEDING_AGE. Será que as alterações introduzidas são suficientes para se poder compilar o projecto? Se não forem, o que faltará na classe Animal?

Exercício 10.36 (adaptado) [Resolução]

Suponha agora que se pretende melhorar a simulação de forma a permitir outro tipo de intervenientes para além dos animais, tais como plantas, tempo, etc. Para tal necessitamos de generalizar a classe Animal, a qual passa agora a ser uma especialização da classe do topo da hierarquia dos intervenientes, designada Actor (ver figura10.3 da pág. 278 do livro). Considere ainda que a única característica comum a todos os intervenientes é o facto de todos realizarem algum tipo de acção, isto é, todos têm o método act (ver assinatura na página 278 do livro), ainda que com implementações diferentes.
Codifique agora a classe abstracta Actor e reescreva o método simulateOneStep da classe Simulator de forma a utilizar o tipo Actor em vez de Animal.

Exercício 10.37 [Resolução]

Reescreva a classe abstracta Actor do exercício anterior de forma a que esta passe a ser um interface (como é óbvio, altere também a ou as subclasses da classe Actor de forma a implementarem o interface em vez de estenderem a classe abstracta). Continuará a ser possível compilar e executar o projecto?


Semana 28 Novembro

Sumário

Tratamento de erros e excepções.
Trabalho prático: Esclarecimento de dúvidas referentes à implementação.

Projecto address-book-v3t (chapter 11)

Este projecto representa uma aplicação de gestão de contactos pessoais. As classes principais deste projecto são a classes AddressBook e ContactDetails. A classe AddressBookDemo permite testar a aplicação, criando para alguns contactos pessoais a serem introduzidos. Este projecto faz parte de um conjunto de projectos que, para além das versões texto, incluem ainda algumas versões gráficas.

Exercício 11.24 [Resolução]

No projecto address-book-v3t é feito o  lançamento de algumas "unchecked exceptions",  caso dos valores passados aos parâmetros dos vários métodos sejam null. O projecto inclui ainda uma "checked exception", representada na classe NoMatchingDetailsException, que actualmente não está a ser utilizada. Modifique o método removeDetails da classe AddressBook de forma a que este lance a referida excepção caso o parâmetro key não seja uma chave em utilização (chave não existente). Adicione agora o código necessário para apanhar e tratar a excepção (apresentando a respectiva ocorrência da mesma) no método remove da classe AddressBookTextInterface.

Exercício 11.27 [Resolução]

Ainda no projecto address-book.v3t, defina uma nova classe para a "checked exception" designada DuplicateKeyException. Esta excepção deverá ser lançada pelo método addDetails da classe AddressBook caso algum dos campos não null (campos name e phone) do seu parâmetro já esteja a ser utilizado. A classe de excepção a criar deverá armazenar os detalhes das chaves em situação de erro. Faça as alterações que julgue necessárias na classe de interface com o utilizador de modo a apanhar e reportar as situações de excepção.


Semana 5 Dezembro

Sumário

Streams em Java.
Trabalho prático: Esclarecimento de dúvidas referentes à implementação.

Projecto address-book-v3t (chapter 11)

Exercício Streams [Resolução]

Acrescente ao projecto address-book-v3t a funcionalidade de gravar e ler a lista de contactos e outra informação que julgue necessária em  ficheiro. Teste convenientemente, acrescentando os dois novos comandos ao interface com o utilizador.
Tenha em atenção que o exercício poderá ser resolvido com recurso a streams de texto ou streams de bytes. Pondere sobre a utilização dos dois tipos de streams e opte por uma na implementação


Semana 12 Dezembro

Sumário

Apresentação e defesa do trabalho prático.

 

bsp;        }