0% acharam este documento útil (0 voto)
25 visualizações35 páginas

Sebenta de Java-Caps1a4

Sebenta de Java autoria de António Cruz
Direitos autorais
© © All Rights Reserved
Levamos muito a sério os direitos de conteúdo. Se você suspeita que este conteúdo é seu, reivindique-o aqui.
Formatos disponíveis
Baixe no formato PDF, TXT ou leia on-line no Scribd
0% acharam este documento útil (0 voto)
25 visualizações35 páginas

Sebenta de Java-Caps1a4

Sebenta de Java autoria de António Cruz
Direitos autorais
© © All Rights Reserved
Levamos muito a sério os direitos de conteúdo. Se você suspeita que este conteúdo é seu, reivindique-o aqui.
Formatos disponíveis
Baixe no formato PDF, TXT ou leia on-line no Scribd
Você está na página 1/ 35

Programação Orientada por Objetos com UML e

Java

Sebenta para a UC de Programação II

Engenharia Informática

António Miguel Rosado da Cruz


Instituto Politécnico de Viana do Castelo
v0.5 (work in progress)

5 de outubro de 2023
Conteúdo

1 Introdução 5
1.1 Organização do Documento . . . . . . . . . . . . . . . . . . . 6

2 Modelação e Programação Orientadas por Objetos 7


2.1 A Linguagem UML . . . . . . . . . . . . . . . . . . . . . . . . 7
2.2 A Linguagem Java . . . . . . . . . . . . . . . . . . . . . . . . 8

3 Introdução à linguagem Java 10


3.1 Programa principal . . . . . . . . . . . . . . . . . . . . . . . . 10
3.2 Tipos de dados . . . . . . . . . . . . . . . . . . . . . . . . . . 11
3.2.1 Tipos de dados primitivos . . . . . . . . . . . . . . . . 11
3.2.2 Array . . . . . . . . . . . . . . . . . . . . . . . . . . . 13
3.2.3 O tipo de dados String . . . . . . . . . . . . . . . . . . 14
3.3 Operadores Aritméticos . . . . . . . . . . . . . . . . . . . . . 15
3.4 Operadores Relacionais . . . . . . . . . . . . . . . . . . . . . 16
3.5 Operadores lógicos . . . . . . . . . . . . . . . . . . . . . . . . 16
3.6 instruções Condicionais . . . . . . . . . . . . . . . . . . . . . 18
3.6.1 if . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 18
3.6.2 switch . . . . . . . . . . . . . . . . . . . . . . . . . . . 19
3.7 Ciclos . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 20
3.7.1 while . . . . . . . . . . . . . . . . . . . . . . . . . . . . 20
3.7.2 do. . . while . . . . . . . . . . . . . . . . . . . . . . . . 21
3.7.3 for. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 22
3.8 I/O na Consola . . . . . . . . . . . . . . . . . . . . . . . . . . 22
3.9 Sumário . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 22
3.10 Exercı́cios . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 22
3.10.1 Exercı́cio 1 . . . . . . . . . . . . . . . . . . . . . . . . 22

4 Classes e Objetos 24
4.1 Classe e suas instâncias . . . . . . . . . . . . . . . . . . . . . 24
4.2 Atributos e métodos de instância . . . . . . . . . . . . . . . . 26
4.2.1 Acessibilidade de atributos e métodos . . . . . . . . . 26
4.2.2 A referência this . . . . . . . . . . . . . . . . . . . . . 27

2
CONTEÚDO

4.3 Sobrecarga de Operadores/métodos . . . . . . . . . . . . . . . 27


4.4 Atributos e métodos de Classe . . . . . . . . . . . . . . . . . 29
4.5 Tipos enumerados de dados . . . . . . . . . . . . . . . . . . . 31
4.6 Arrays de Objetos . . . . . . . . . . . . . . . . . . . . . . . . 32
4.7 De UML para Java . . . . . . . . . . . . . . . . . . . . . . . . 33
4.8 Exercı́cios . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 33
4.8.1 Exercı́cio 1 . . . . . . . . . . . . . . . . . . . . . . . . 33
4.8.2 Exercı́cio 2 . . . . . . . . . . . . . . . . . . . . . . . . 34
4.8.3 Exercı́cio 3 . . . . . . . . . . . . . . . . . . . . . . . . 34
4.8.4 Exercı́cio 4 . . . . . . . . . . . . . . . . . . . . . . . . 34
4.8.5 Exercı́cio 5 . . . . . . . . . . . . . . . . . . . . . . . . 35
4.8.6 Exercı́cio 6 . . . . . . . . . . . . . . . . . . . . . . . . 35

5 Herança 36
5.1 Herança . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 36
5.2 Sobreposição de Operadores/métodos . . . . . . . . . . . . . 40
5.3 A referência super . . . . . . . . . . . . . . . . . . . . . . . . 40
5.4 Polimorfismo . . . . . . . . . . . . . . . . . . . . . . . . . . . 41
5.5 Sumário . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 42
5.6 Exercı́cios . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 43
5.6.1 Exercı́cio 1 . . . . . . . . . . . . . . . . . . . . . . . . 43

6 Classes Abstratas e Interfaces 44


6.1 Introdução . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 44
6.2 Classes abstratas . . . . . . . . . . . . . . . . . . . . . . . . . 44
6.3 Interfaces . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 48
6.4 Conclusão . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 49

7 Coleções de Objetos 51
7.1 Introdução . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 51
7.2 Tipos de coleção . . . . . . . . . . . . . . . . . . . . . . . . . 51
7.3 Tipos Genéricos . . . . . . . . . . . . . . . . . . . . . . . . . . 52
7.4 Conjuntos . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 53
7.5 Listas . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 54
7.6 Conjuntos Ordenados . . . . . . . . . . . . . . . . . . . . . . 55
7.7 Outras Coleções em Java . . . . . . . . . . . . . . . . . . . . . 56
7.8 Iterator . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 56
7.9 Sumário . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 57
7.10 Exercı́cios . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 57
7.10.1 Exercı́cio 1 . . . . . . . . . . . . . . . . . . . . . . . . 57

3 Prog. Orientada por Objetos com UML e Java - A. Miguel R. da Cruz


CONTEÚDO

8 Associações de Objetos 58
8.1 Introdução . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 58
8.2 Map . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 58
8.2.1 HashMap . . . . . . . . . . . . . . . . . . . . . . . . . 59
8.3 Exercı́cios . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 60
8.3.1 Exercı́cio 1 . . . . . . . . . . . . . . . . . . . . . . . . 60

9 Tratamento de Erros e Excepções 61


9.1 Introdução . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 61

10 Anotações 65

11 Constructs Funcionais 66
11.1 Sumário . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 66
11.2 Exercı́cios . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 66
11.2.1 Exercı́cio 1 . . . . . . . . . . . . . . . . . . . . . . . . 66

12 Programação Concorrente 67
12.1 Exercı́cios . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 67
12.1.1 Exercı́cio 1 . . . . . . . . . . . . . . . . . . . . . . . . 67

13 Boas Práticas 68
13.1 Exercı́cios . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 68
13.1.1 Exercı́cio 1 . . . . . . . . . . . . . . . . . . . . . . . . 68

14 Interfaces gráficas em ambiente Desktop 69


14.1 Introdução . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 69
14.2 Java Swing . . . . . . . . . . . . . . . . . . . . . . . . . . . . 69
14.3 Java FX(?) . . . . . . . . . . . . . . . . . . . . . . . . . . . . 69
14.4 Sumário . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 69
14.5 Exercı́cios . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 69
14.5.1 Exercı́cio 1 . . . . . . . . . . . . . . . . . . . . . . . . 69

15 Conclusão 70

Prog. Orientada por Objetos com UML e Java - A. Miguel R. da Cruz 4


Capı́tulo 1

Introdução

O paradigma de programação orientada por objetos (POO) é hoje larga-


mente adotado pelas equipas de desenvolvimento de software de todo o
mundo. São várias as linguagens de programação que suportam este pa-
radigma (ex.: Java, C++, Python, Ruby, Swift). A aproximação ao desen-
volvimento de software orientado por objetos é feita pela identificação de
classes ou categorias de “objetos”do mundo real, relevantes para a resolução
do problema entre mãos. Esses “objetos”do mundo real podem ser mais
ou menos tangı́veis. Exemplos de tais objetos são automóveis, bicicletas,
livros, mas também clientes, inscrições, encomendas, faturas ou recibos de
pagamento.
A identificação de classes representativas destes objetos ou conceitos do
mundo real conduz tipicamente ao desenvolvimento de um modelo de clas-
ses. A linguagem UML (Unified Modeling Language) é hoje a linguagem de
modelação mais usada em contextos de desenvolvimento de software. Trata-
se de uma linguagem diagramática (baseada em diagramas) que oferece a
notação e semântica de diversos diagramas [1]. Estes diagramas permitem
a modelação de diferentes perspectivas, ou visões, através de diferentes dia-
gramas, formando um modelo do sistema de software a desenvolver, o qual
integras as diferentes visões. Um desses diagramas é o diagrama de classes, o
qual permite a criação de um modelo de classes. Este modelo consiste numa
visão estrutural do sistema, composta pelas diferentes classes identificadas,
seus atributos ou propriedades, seu comportamento, e relações estruturais
entre elas.
Por outro lado, a linguagem Java permite-nos codificar essas classes e o
seu comportamento, numa forma passı́vel de ser executada.
Contrariamente a outras linguagens, como o C ou C++, que são compi-
ladas para a linguagem máquina duma arquitetura fı́sica especı́fica, os pro-
gramas na linguagem Java são compilados para uma linguagem intermédia
(bytecode), de uma máquina virtual (a JVM - Java Virtual Machine). Cada
arquitetura especı́fica terá a sua máquina virtual própria, mas todas elas for-

5
CAPÍTULO 1. INTRODUÇÃO

necem a mesma abstração para execução de programas. Desta forma, um


programa compilado para bytecodes pode ser executado em qualquer JVM,
em diferentes sistemas operativos ou diferentes arquiteturas fı́sicas [3].
A máquina virtual de Java (JVM) serve ainda, e cada vez mais, de am-
biente de execução para programas em outras linguagens, como a linguagem
Scala, Kotlin, Clojure, etc.[4].
Outras linguagens oferecem arquiteturas semelhantes, como por exem-
plo as linguagens para o ambiente .Net, como o C#, Visual Basic.Net ou
J#, entre outras, as quais são compiladas para uma linguagem intermédia
(Intermediate Language - IL), de uma máquina virtual (Common Language
Runtime - CLR) [2].
A existência de uma máquina virtual tem ainda outras vantagens, como
a de garantir a inicialização de variáveis, e gerir a memória utilizada, li-
bertando espaço da memória do programa que já não é utilizado por este
(espaços de memória que deixaram de estar referenciados no programa).

1.1 Organização do Documento


Os capı́tulos seguintes estão organizados da seguinte forma:

• O capı́tulo 2 introduz a linguagem UML, para modelação de sistemas,


e a linguagem Java para programação orientada por objetos.

• O capı́tulo 3 apresenta-nos os principais constructs da linguagem Java.

• O capı́tulo 4 introduz os conceitos de Classe e Objeto, assim como


outras noções básicas relativas ao paradigma de orientação por objetos.

• O capı́tulo 5 aprofunda e apresenta outros conceitos de orientação por


objetos, como os conceitos de heranâa e polimorfismo, entre outros.

• No capı́tulo 7 são apresentadas coleções de objetos em Java.

• No capı́tulo 9 é abordado o mecanismo de Excepções do Java.

• O capı́tulo 8 apresenta alguns dos contructs funcionais suportados pelo


Java.

Prog. Orientada por Objetos com UML e Java - A. Miguel R. da Cruz 6


Capı́tulo 2

Modelação e Programação
Orientadas por Objetos

O inı́cio de qualquer projeto de programação, consiste na compreensão e


análise dos requisitos, e o desenho de uma solução para o problema. Usando
o paradigma de orientação a objetos, tanto a análise como o desenho da
solução consistem na identificação de classes de objetos relevantes, e quais
os seus atributos e comportamento.
Assim, da lista de requisitos, pretende-se identificar os conceitos ou obje-
tos relevantes, para que possam ser modelados como classes, estudada a sua
estrutura interna, o seu comportamento, e estudadas as suas inter-relações.
A linguagem UML (Unified Modeling Language) oferece-nos diversos dia-
gramas para modelar diferentes aspetos de um sistema de software. Na
secção seguinte iremos analisar três desses tipos de diagramas. A linguagem
Java permite-nos implementar/codificar os modelos especificados como uma
solução para o problema entre mãos.

2.1 A Linguagem UML


A linguagem UML fornece diferentes tipos de diagramas para criar um mo-
delo do sistema a desenvolver. De acordo com a especificação oficial, esses
diagramas podem ser categorizados em três grupos[1]:

Diagramas estruturais São diagramas que modelam a estrutura do sis-


tema, ou seja as suas classes, os seus pacotes, os seus módulos ou
componentes, e a forma como são distribuı́dos;

Diagramas comportamentais Modelam o comportamento do sistema.


Estão nesta categoria os diagramas de atividades e de máquina de
estados. Pode-se também considerar nesta categoria os diagramas de
casos de uso (ou de casos de utilização), os quais não modelam com-
portamento por si só, mas servem para estruturar a modelação do

7
CAPÍTULO 2. MODELAÇÃO E PROGRAMAÇÃO ORIENTADAS
POR OBJETOS

comportamento em pacotes de funcionalidade. O comportamento de


cada pacote (caso de uso) será depois especificado através de diagra-
mas de atividades e máquina de estados, ou diagramas de sequência,
ou ainda através de templates de casos de utilização (não definidos no
UML).

Diagramas de interação Servem para modelar interação entre objetos do


sistema ou entre utilizadores e o sistema. De certa forma, acabam por
também permitir modelar comportamento. Inclui os diagramas de
sequência, comunicação, tempo, e visão geral de interação.

Ao longo dos capı́tulos seguintes, iremos falar apenas dos diagramas de


classes, casos de uso, sequência e colaboração.
Através da notação de diagrama de classes, a linguagem UML permite-
nos modelar a estrutura de um sistema de software de uma forma orientada
por objetos. Uma classe, é uma entidade que permite criar estruturas que
encapsulam dados e operações sobre os dados. No capı́tulo 4 introduziremos
a notação de classe e este tipo de diagrama.
Usando o diagrama de casos de uso, é possı́vel modelar perfis de uti-
lização do sistema (utilizadores humanos e sistemas externos) e funcionali-
dade do sistema acessı́vel a cada perfil de utilização. No capı́tulo 14 intro-
duziremos este tipo de diagrama.
Através dos diagrama de sequência e de colaboração, podemos modelar a
sequência de invocação de métodos de diferentes objetos, dentro de um dado
método ou função do sistema. No capı́tulo 4 introduziremos estes diagramas
para modelar a invocação de métodos, no contexto de um dado método.
Depois, no capı́tulo 14 usaremos este tipo de diagramas para modelar a
interação do utilizador com o sistema no contexto de uma função do sistema.

2.2 A Linguagem Java


Java é uma linguagem de programação de âmbito geral, orientada por ob-
jetos. A linguagem Java conta já com mais de vinte anos de idade, ao
longo dos quais sofreu diversas melhorias e atualizações. Java foi criada por
James Gosling, na Sun Microsystems, em 1995, tendo sido posteriormente
adquirida pela Oracle Corporation.
Os programas desenvolvidos em Java são compilados para bytecode, a
linguagem máquina da Java Virtual Machine (JVM), a máquina virtual de
Java. A JVM está disponı́vel para diferentes sistemas operativos e diferentes
arquiteturas de hardware. Isto torna possı́vel compilar um programa Java
apenas uma vez, e executá-lo diversas vezes em diferentes plataformas.
Outras linguagens têm, recentemente, visado a JVM como alvo dos seus
compiladores. Exemplos notáveis são Scala e Kotlin. O facto de serem

Prog. Orientada por Objetos com UML e Java - A. Miguel R. da Cruz 8


CAPÍTULO 2. MODELAÇÃO E PROGRAMAÇÃO ORIENTADAS
POR OBJETOS

compiladas para a JVM faz com que possam interoperar com programas em
Java.
Sendo uma máquina virtual, a JVM corre os seus próprios processos de
gestão e otimização de memória, sendo o garbage collector o mais conhe-
cido. Este processo liberta zonas de memória não referidas por nenhuma
variável num programa. Isto liberta o programador de preocupações como a
gestão de apontadores para posições de memória e a necessidade de libertar
memória que já não usa.
O capı́tulo seguinte apresenta os principais constructs da linguagem Java.
Os capı́tulos posteriores apresentam modelação e programação orientadas
por objetos, usando UML e Java.

9 Prog. Orientada por Objetos com UML e Java - A. Miguel R. da Cruz


Capı́tulo 3

Introdução à linguagem Java

Um programa em linguagem Java consiste num conjunto de classes que são


usadas para instanciar estruturas dinâmicas em memória (os objetos), as
quais agrupam dados e operações sobre esses dados.
Podemos criar as várias classes Java num qualquer editor de texto (ex.:
vi, notepad, notepad++) ou usando um IDE (Integrated Development En-
vironment) para Java. Para compilar e executar o programa Java, podemos
usar a linha de comandos do sistema operativo e executar o compilador
(javac) e depois o ambiente de execução com o JDK (java).
Nesta sebenta, usamos o IDE NetBeans (https://netbeans.org/) para
editar programas em Java e, associado ao JDK, para compilar e executar es-
ses programas. Para os assuntos tratados nesta sebenta, é suficiente descar-
regar a última versão do JDK (https://www.oracle.com/java/technologies/downloads/).
Antes de instalar o NetBeans, deve ser instalado o JDK necessário para
executar o NetBeans, e compilar e executar os programas Java a desenvolver,
conforme as indicações na página de download do NetBeans.
Pode, alternativamente, ser descarregado o JDK with NetBeans IDE
Java SE bundle a partir de https://netbeans.apache.org/download/, ou o IDE
IntelliJ IDEA (https://www.jetbrains.com/idea/).

3.1 Programa principal


Um programa em Java consiste numa coleção de classes, agrupando dados
e operações sobre os mesmos, a um “programa principal”, a partir do qual
tudo é coordenado.
O programa Java mais simples terá sempre uma classe com o “programa
principal”. Este, que é de facto um método de classe, é o primeiro método a
ser executado no programa. O excerto de código seguinte ilustra um tı́pico
programa Olá Mundo o qual escreve pura e simplemente no ecrã a frase “Ola
Mundo!”:
package exemplo;

10
CAPÍTULO 3. INTRODUÇÃO À LINGUAGEM JAVA

public class OlaMundo {

public static void main(String[] args) {


System.out.println("Ola Mundo!");
}
}

3.2 Tipos de dados


A linguagem Java é “tipada”, no sentido em que as suas variáveis têm que
ser declaradas, e ao fazê-lo é necessário declarar o tipo de cada variável. O
tipo de uma variável define os valores que lhe podem ser atribuı́dos. Por
exemplo, uma variável de tipo inteiro (int em Java) pode tomar valores intei-
ros, enquanto uma variável de tipo caracter (char em Java) pode armazenar
um caracter. O excerto de código seguinte, representa um programa Java
onde são declaradas variáveis x, y, c e d, sendo x e y de tipo inteiro (int), c
de tipo caracter (char) e d de tipo decimal (double):
int x, y=0;
char c = ’a’;
double d = 2.35;
O código acima, ilustra ainda a atribuição de valores a variáveis usando
o operador =, que atribui o valor do lado direito é variável do seu lado
esquerdo. No exemplo, é atribuı́do o valor 0 à variável y, o caracter ’a’ à
variável c, e o valor 2,35 à variável d.
Em Java podemos declarar variáveis de tipos de dados primitivos (ou de
valor), como os da tabela 3.1, ou de tipos de dados de referência, como o
tipo String e todos os que representem classes (iremos ver isto em detalhe
no capı́tulo 4).

3.2.1 Tipos de dados primitivos


Os tipos de dados primitivos do Java são os existentes na maior parte das
linguagens de programação. A tabela 3.1 lista os tipos de dados primitivos
do Java, o seu tamanho em bits e o intervalo de valores admitido por cada
tipo. No caso de atributos de classes (ver capı́tulo 4), estes são inicializados
com os valores por defeito indicados na última coluna da tabela. Apenas
os atributos de classes são automaticamente inicializados. O mesmo não
acontece com variáveis declaradas localmente numa função/método.
O excerto de código seguinte ilustra a declaração e utilização de algumas
variáveis locais de tipos primitivos:

int n, i=0;

11 Prog. Orientada por Objetos com UML e Java - A. Miguel R. da Cruz


CAPÍTULO 3. INTRODUÇÃO À LINGUAGEM JAVA

Tipo de Tamanho/ Intervalo Valor por


dados formato defeito (para
atributos)
int 32 bits 0
short 16 bits De -32 768 a 32 767 0
long 64 bits em com- De 263 a 263 1. long 0L
plemento para 2 pode ainda ser usado
como unsigned (inteiro
sem sinal de 64 bits) no
intervalo 0 a 264 1
byte 8 bits De -128 a 127 0
char 16 bits Unicode De ‘\u0000’ (0) a ‘\u0000’
character ‘\uf f f f ’ (65 535)

float Vı́rgula flutuante de Precisão simples 0.0f


32 bits IEEE 754
double Vı́rgula flutuante de Precisão dupla 0.0d
64 bits IEEE 754
boolean true, false false

Tabela 3.1: Tipos de dados primitivos.

Prog. Orientada por Objetos com UML e Java - A. Miguel R. da Cruz 12


CAPÍTULO 3. INTRODUÇÃO À LINGUAGEM JAVA

float x, y, z;
char c = ’a’;

x = 5; y = 9; z = 13;
i = 2;
x = y/2;
System.out.println("x = " + x);

i = (int)(z/y);
System.out.println("i = " + i);
System.out.println("z/y = " + (z/y));

n = c; //n fica com o c\’odigo ASCII do caracter ’a’


System.out.println("c = " + c);
System.out.println("n = " + n);

O excerto de código acima começa por declarar variáveis de tipo inteiro,


float e caracter. Depois, atribui valores a algumas variáveis, diretamente
ou como resultado de operações aritmáticas, e imprime no ecrã os novos
conteúdos de algumas variáveis. De notar que i é uma variável inteira, pelo
que o resultado da divisão de duas variáveis float, que lhe é atribuido, tem
que ser convertido para int (é feito o cast para int) e vê truncada a sua parte
decimal. No caso da atribuição da variável c, de tipo caracter, a n, de tipo
inteiro, o valor visı́vel passa a ser o código ASCII do caracter ’a’. Os valores
impressos no ecrã seriam:

x = 4.5
i = 1
z/y = 1.4444444
c = a
n = 97

3.2.2 Array
Um Array é uma coleção indexada (sequência) de dados de um determinado
tipo. Por exemplo, as linhas de código seguintes, de um método main,
declaram um array arrInt para armazenar dez números inteiros e um array
arrCar para quinze caracteres:

int arrInt[] = new int[10];


char arrCar[] = new char[15];

A estes arrays podem ver atribuı́dos valores em posições especı́ficas, como


no excerto seguinte:

13 Prog. Orientada por Objetos com UML e Java - A. Miguel R. da Cruz


CAPÍTULO 3. INTRODUÇÃO À LINGUAGEM JAVA

arrInt[0] = 5;
arrInt[1] = 3;
arrCar[0] = ’o’;
arrCar[1] = ’l’;
arrCar[2] = ’a’;

System.out.println(arrayInt[0] + arrayInt[1]);
System.out.println(arrayCar[0] + arrayCar[1] + arrayCar[2]);
A execução do excerto anterior provocaria o seguinte output para o ecrã:
8
ola
é possı́vel, também, declarar e inicializar um array de uma só vez. A linha
seguinte cria um array de inteiros e inicializa-o com dez inteiros, estando no
ı́ndice zero o valor 1, no ı́ndice um o valor 5, e assim por diante:
int inteiros[] = {1, 5, 8, 12, 9, 34, 7, 10, 2, 8};
Um array de N posições tem ı́ndices entre 0 e N 1.
Um array é, em Java, uma classe, pelo que um objeto do tipo Array de
dados de um outro determinado tipo, encapsula o array de dados juntamente
com operações sobre esses dados. Por exemplo, inteiros.length dá-nos o
tamanho do array inteiros declarado acima.

3.2.3 O tipo de dados String


O tipo de dados String, em Java, é também uma classe. Significa isto que
um objeto do tipo String tem encapsulado o valor da String e um conjunto
de métodos sobre esse valor. O excerto de código seguinte, declara e inicia-
liza uma String nome, e depois imprime no ecrã informação consultada ou
aoperada através de métodos disponibilizados pela classe String:
String nome = "Ana Maria Silva";

System.out.println(nome.length());
System.out.println(nome.charAt(4));
System.out.println(nome.substring(4, 9));
System.out.println(nome.isEmpty());
System.out.println(nome.concat(" ol\’a, ol\’a!"));
O exemplo anterior, imprime o tamanho da string (número de caracteres
em nome); depois, imprime o caracter no ı́ndice 4 da String (vista como
um array de caracteres); imprime a substring de nome entre os ı́ndices 4,
inclusivé, e 9, excluindo este; imprime true ou f alse, conforme a string
nome estiver vazia ou não; e, por fim, imprime o resultado da concatenação
de nome com a string “ olá, olá!”. O resultado impresso, seria então:

Prog. Orientada por Objetos com UML e Java - A. Miguel R. da Cruz 14


CAPÍTULO 3. INTRODUÇÃO À LINGUAGEM JAVA

Operador Significado
⇤ Multiplicação
/ Divisão
+ Adição (também usado para concatenação de Strings)
Subtração
% Resto da divisão inteira
++ Incrementar (posfix ou prefix)
Decrementar (posfix ou prefix)
”Subtração”unária (troca de sinal)

Tabela 3.2: Operadores Aritméticos

15
M
Maria
false
Ana Maria Silva ol\’a, ol\’a!

3.3 Operadores Aritméticos


A tabela 3.2 mostra os principais operadores aritméticos disponı́veis em
Java. Os primeiros quatro (multiplicação, divisão, adição e subtração) são
já conhecidos de outros contextos e o seu comportamento é o esperado. Os
valores operados têm que ser, obviamente, relativos a grandezas numéricas
(inteiras ou decimais). Já o operador % (resto da divisão inteira) serve para
operar dois números inteiros e obter o resto da divisão inteira de um pelo
outro.
Os operadores ++ e são, respetivamente, operadores unários para in-
crementar ou decrementar uma variável. Estes operadores podem ser usados
antes (prefix) ou depois (posfix) da variável a ser operada, com significado
ligeiramente diferente. No exemplo seguinte, a variável x é incrementada,
na linha 2, ficando com o valor 1. Na linha 3, o y é calculado como sendo o
valor dele próprio mais o valor de x, ficando a variável y com o valor 1. Só
depois, o valor de x é incrementado, passando para 2. Na linha 4, a variável
x é incrementada, antes de ser usada no cálculo de z. A variável x fica, neste
ponto, com o valor 3, e depois z é calculado como sendo o valor dele próprio
mais x, ficando z com o valor 3. Na linha 8, a variável y é incrementada em
3 unidades, usando a combinação do operador de atribuição (’=’) com o de
adição (’+’). y+ = 3 é equivalente e abrevia a expressão y = y + 3.

1: int x=0; int y=0; int z=0;


2: x++;

15 Prog. Orientada por Objetos com UML e Java - A. Miguel R. da Cruz


CAPÍTULO 3. INTRODUÇÃO À LINGUAGEM JAVA

3: y = y + (x++);
4: z = z + (++x);
5: System.out.println("x = " + x);
6: System.out.println("y = " + y);
7: System.out.println("z = " + z);
8: y += 3;
9: System.out.println("y = " + y);
O output do excerto de código acima seria:
x = 3
y = 1
z = 3
y = 4

3.4 Operadores Relacionais


Operadores relacionais relacionam dois valores, comparando-os, e dando
como resultado um valor booleano. A tabela 3.3 lista os operadores relaci-
onais disponı́veis em Java. No excerto de código seguinte são definidas três
variáveis inteiras e seis booleanas. Depois, são feitas diversas comparações
entre os valores das variáveis inteiras, sendo o resultado das comparações
atribuido às variáveis booleanas.
int x=3, y=5, z=7;
boolean a, b, c, d, e, f;
a = (x == y);
b = (x != y);
c = (x < z);
d = (x <= y);
e = (y > z);
f = (z >= y);
Assim, a ficará com o valor f alse, pois não existe relação de igualdade
entre x e y; b ficará com valor true; c ficará true; d ficará true; e ficará
f alse; e, f ficará true.
Os operadores relacionais são muito usados com instruções condicionais
e ciclos, e podem ser combinados com operadores lógicos.

3.5 Operadores lógicos


A tabela 3.4 apresenta os principais operadores lógicos disponı́veis em Java.
Estes operadores permitem a conjunção, disjunção ou negação de condições
lógicas. Uma condição lógica é uma expressão que avalia sempre para Ver-
dadeiro (true) ou Falso (f alse), como por exemplo:

Prog. Orientada por Objetos com UML e Java - A. Miguel R. da Cruz 16


CAPÍTULO 3. INTRODUÇÃO À LINGUAGEM JAVA

Operador Significado
== Igualdade
!= Desigualdade
< Menor que
<= Menor ou igual a
> Maior que
>= Maior ou igual a

Tabela 3.3: Operadores Relacionais

Operador Significado
&& E lógico
|| OU lógico
! Negação lógica

Tabela 3.4: Operadores lógicos

x == 3

ou
y>4

Uma conjunção lógica (E, AN D ou ^), representada em Java por &&,


das duas condições anteriores seria representada por:

(x == 3)&&(y > 4)

Similarmente, a disjunção lógica (OU , OR ou _), representada em Java


por ||, dessas condições, seria:

(x == 3)||(y > 4)

A negação (¬) de (x == 3), seria representada por !(x == 3) ou (x! = 3).


O resultado da conjunção, disjunção, negação de condições lógicas, ou
da combinação de diversos destes operadores entre condições lógicas, é ele
próprio uma condição lógica.
Java tem ainda operadores lógicos bit a bit, assim como operações de
manipulação de bits, as quais não são abordadas neste documento.

17 Prog. Orientada por Objetos com UML e Java - A. Miguel R. da Cruz


CAPÍTULO 3. INTRODUÇÃO À LINGUAGEM JAVA

3.6 instruções Condicionais


Uma instrução condicional, ou de controlo de fluxo de execução, faz de-
pender a lógica a executar da verificação ou não de uma condição lógica.
Nesta secção iremos abordar as instruções if e switch, as quais permitem
testar uma ou mais condições e dependendo do resultado (true ou f alse)
encaminhar a execução do código para um ou outro bloco de instruções.

3.6.1 if
A instrução if permite a execução condicional de uma outra instrução ou
bloco de instruções. Ou seja, se uma dada condição é verdadeira, a instrução
ou bloco de i©s seguintes serão executados. No exemplo seguinte, a linha
4 será executada apenas se a condição (x > y), da linha 3, for verdadeira:

1: int x=0, y=0;


2: x++;
3: if (x > y) {
4: System.out.println("x \’e maior que y");
5: }

A instrução if permite ainda uma clausula else, a qual permite que uma
outra instrução ou bloco de instruções sejam executados no caso da condição
inicial ser falsa. Ou seja, na instrução seguinte, o bloco de instruções 1 será
executado se a condição cond for verdadeira, senão (i.e., se a condição for
falsa) será executado o bloco 2:

if (cond) {
// bloco 1
...
}
else {
// bloco 2
...
}

No exemplo seguinte, a linha 4 será executada se a condição (x > y), da


linha 3, for verdadeira. Se esta for falsa, então serão executadas as linhas 7
e 8:

1: int x=0, y=0;


2: x++;
3: if (x > y) {
4: System.out.println("x \’e maior que y");
5: }

Prog. Orientada por Objetos com UML e Java - A. Miguel R. da Cruz 18


CAPÍTULO 3. INTRODUÇÃO À LINGUAGEM JAVA

6: else {
7: System.out.println("x \’e menor que y");
8: System.out.println("x tem valor " + x);
9: }

Quando, no ”if”ou no ”else”, temos um bloco com apenas uma instrução,


então as chavetas são opcionais. Assim, o exemplo anterior pode ser reescrito
como:

1: int x=0, y=0;


2: x++;
3: if (x > y) System.out.println("x \’e maior que y");
4: else {
5: System.out.println("x \’e menor que y");
6: System.out.println("x tem valor " + x);
7: }

3.6.2 switch
Por vezes precisamos de testar várias condições em sequência, sendo execu-
tado o bloco de instruções da primeira condição que for avaliada para true.
Isto pode ser feito encadeando várias instruções if...else:

1: int x=0;
2: x++;
3: if (x == 1) System.out.println("Amarelo");
4: else if (x == 2) System.out.println("Verde");
5: else if (x == 3) System.out.println("Azul");
6: else if (x == 4) System.out.println("Vermelho");
7: else if (x == 5) System.out.println("Preto");
8: else if (x == 6) System.out.println("Branco");
9: else System.out.println("Cinzento");

Mas, neste caso, é melhor usar a instrução switch:

1: int x=0;
2: x++;
3: switch(x){
4: case 1:
5: System.out.println("Amarelo");
6: break;
7: case 2:
8: System.out.println("Verde");
9: break;
10: case 3:

19 Prog. Orientada por Objetos com UML e Java - A. Miguel R. da Cruz


CAPÍTULO 3. INTRODUÇÃO À LINGUAGEM JAVA

11: System.out.println("Azul");
12: break;
13: case 4:
14: System.out.println("Vermelho");
15: break;
16: case 5:
17: System.out.println("Preto");
18: break;
19: case 6:
20: System.out.println("Branco");
21: break;
22: default:
23: System.out.println("Cinzento");
24: }

O valor da variável no switch é testado em cada case e, se for igual


ao valor do case, é executado tudo até ao final do switch, excepto se for
encontrada uma instrução break, altura em que a execução do switch é in-
terrompida, sendo executada a instrução a seguir à chaveta que encerra o
bloco do switch.

3.7 Ciclos
Frequentemente queremos executar um bloco de código repetidamente en-
quanto uma condição se mantém verdadeira. As instruções seguintes permitem-
nos fazer isso.

3.7.1 while
A instrução while testa uma condição inicial, e se a mesma for verdadeira,
executa o bloco de código seguinte, senão ignora esse bloco.
No exemplo seguinte,

1: int x=0;
2: while (x < 10){
3: System.out.println("Linha " + (x+1));
4: $x = x + 1;$;
5: }

a condição (x < 10) é testada e, sendo verdadeira, é executado o bloco de


instruções do while. Neste caso seriam impressas no ecrã as linhas:

Linha 1
Linha 2
Linha 3

Prog. Orientada por Objetos com UML e Java - A. Miguel R. da Cruz 20


CAPÍTULO 3. INTRODUÇÃO À LINGUAGEM JAVA

Linha 4
Linha 5
Linha 6
Linha 7
Linha 8
Linha 9
Linha 10

Note-se que a instrução x = x + 1; é equivalente a usar o operador ++,


apresentado na secção 3.3. No entanto, se usarmos x + +;, é devolvido o
valor de x antes de fazer o incremento da variável, enquanto que se for usado
+ + x, é primeiro incrementado o valor de x, e só depois devolvido o novo
valor. Assim, poderı́amos reescrever o exemplo anterior da seguinte forma,
obtendo o mesmo resultado:

1: int x=0;
2: while (x < 10){
3: System.out.println("Linha " + (++x));
5: }

Mas, se o exemplo for alterado para:

1: int x=0;
2: while (x < 10){
3: System.out.println("Linha " + (x++));
5: }

o resultado em output começará com ’Linha 0’, sendo a última linha a ’Linha
9’.

3.7.2 do. . . while


A instrução do . . . while é muito parecida com a instrução while mas começa
por executar o bloco de instruções e só depois testa a condição. Assim, o
exemplo seguinte

1: int x=0;
2: do{
3: System.out.println("Linha " + (++x));
5: } while (x < 10);

imprime sempre a primeira ’Linha’, mesmo que o valor de x seja 10.


Assim, neste exemplo a linha ’Linha 10’ ainda será impressa, apesar de x já
ter valor 10, porque a condição só é testada depois.

21 Prog. Orientada por Objetos com UML e Java - A. Miguel R. da Cruz


CAPÍTULO 3. INTRODUÇÃO À LINGUAGEM JAVA

3.7.3 for. . .
A instrução for permite duas abordagens:

• Uma abordagem clássica, que permite iterar sobre um intervalo de


valores;

• Uma abordagem para percorrer arrays ou coleções, por vezes chamada


for each.

A primeira abordagem tem 3 componentes, para além do bloco de ins-


truções:

• Definição e inicialização de variáveis

• Definição da condição de manutenção

• Incremento a efetuar às variáveis

Como exemplo, podemos escrever o exemplo acima usando a instrução


for:

1: for(int x=0; x < 10; x++)


2: System.out.println("Linha " + (x+1));

A segunda abordagem permite percorrer arrays ou coleções, definindo


uma variável à qual vai sendo atribuindo um valor da coleção. Exemplo:

1: int array[] = {1, 3, 5, 4, 6, 12, 9, 10, 5, 3, 2};


2: for(int x : array)
3: System.out.println("--> " + x);

3.8 I/O na Consola


Como instruções de I/O na consola, temos visto nos exemplos anteriores a
utilização de ’System.out.println’, a qual permite imprimir no ecrã strings e
valores de variáveis.
A tabela 3.5 apresenta as principais instruções de I/O, que serão úteis
para os nossos exemplos.

3.9 Sumário

3.10 Exercı́cios
3.10.1 Exercı́cio 1

Prog. Orientada por Objetos com UML e Java - A. Miguel R. da Cruz 22


CAPÍTULO 3. INTRODUÇÃO À LINGUAGEM JAVA

Instrução Exemplo Descrição

System.out.println System.out.println(”Olá Escreve no ecrã, termi-


Mundo!”); nando com uma quebra
de linha
System.out.printf System.out.printf(”%.2f”, Escreve texto forma-
x); tado no ecrã. Neste caso
escreve o valor com duas
casas decimais.
System.out.print System.out.print(”Insira Escreve no ecrã, termi-
o valor: ”); nando sem quebra de li-
nha
System.in.read ... ...

Tabela 3.5: Instruções de I/O na consola.

23 Prog. Orientada por Objetos com UML e Java - A. Miguel R. da Cruz


Capı́tulo 4

Classes e Objetos

4.1 Classe e suas instâncias

No paradigma de desenvolvimento orientado a objetos, um objeto repre-


senta um conceito ou objeto, mais ou menos tangı́vel, do mundo real. Uma
classe agrupa objetos com caracterı́sticas comuns. Por exemplo, a repre-
sentação de automóveis no paradigma orientado a objetos pode ser defi-
nida através de uma classe Automóvel, a partir da qual podem ser criadas
instâncias (objetos), com as caracterı́sticas definidas nessa classe. A figura
4.1 ilustra uma possı́vel definição da classe Automóvel, representada usando
a linguagem UML, enquanto a figura 4.2 representa a mesma classe usando a
linguagem Java. De notar que, relativamente aos métodos, na representação
UML foi apenas definida a sua interface (ou assinatura), enquanto na repre-
sentação Java foi também definida uma implementação desses métodos.
A classe Automóvel pode, então, ser vista como um template para criar
representações de automóveis especı́ficos, os objetos instância da classe Au-
tomóvel.
Uma classe define também um tipo de dados. Todas as suas instâncias
(objetos criados à imagem da classe) são desse tipo. A criação de instâncias
de uma classe é feita através de construtores definidos na classe. Na figura
4.2 está codificado um construtor da classe Automóvel. Apesar de não ter
conteúdo, este construtor serve para criar automóveis, ou seja objetos de
Automóvel, que é o mesmo que instâncias da classe Automóvel. A figura
4.3 ilustra uma possı́vel definição de outro construtor para a mesma classe.
O excerto de código Java, na figura 4.4 ilustra a criação de instâncias da
classe Automóvel, fazendo uso dos respetivos construtores. São declaradas
duas variáveis, a1 e a2, de tipo Automovel, sendo depois criadas e atribuı́das
duas instâncias de Automóvel, uma a cada variável, usando, para cada uma,
um dos dois diferentes construtores da classe.

24
CAPÍTULO 4. CLASSES E OBJETOS

Figura 4.1: Classe Automóvel representada em UML.

Figura 4.2: Classe Automóvel codificada em Java.

Figura 4.3: Outro construtor da classe Automóvel.

25 Prog. Orientada por Objetos com UML e Java - A. Miguel R. da Cruz


CAPÍTULO 4. CLASSES E OBJETOS

Figura 4.4: Objetos ou instâncias de Automóvel.

4.2 Atributos e métodos de instância


Na classe Automóvel, do exemplo acima, foram definidos quatro atributos
(marca, modelo, potência e matrı́cula) os quais constituem propriedades
próprias dos automóveis, i.e. propriedades que os distinguem. Ou seja, dife-
rentes automóveis podem ter diferentes marca, modelo, potência e matrı́cula.
Estas propriedades ou atributos são chamados atributos de instância. O seu
valor pertence à instância. Por vezes são também chamadas de variáveis
de instância. Da mesma forma, os métodos que foram definidos na classe
Automóvel (getInfo(), setPotencia(. . . ) e getPotencia()), são métodos que
consultam ou alteram o estado de uma instância especı́fica (i.e., os atributos
da instância).

4.2.1 Acessibilidade de atributos e métodos


A abordagem da comunicação por invocação de métodos pode ser usada:

• para interação com outros objetos (métodos).

• para invocação de métodos locais.

Enquanto os métodos locais (métodos definidos na própria classe) são


sempre visı́veis, a interação com outros objetos é feita através da invocação
de métodos de outros objetos, os quais têm que ser visı́veis a partir do objeto
que os invoca. O Java permite a declaração da acessibilidade aos métodos
(e aos atributos e construtores), logo na definição dos mesmos. Assim,

Prog. Orientada por Objetos com UML e Java - A. Miguel R. da Cruz 26


CAPÍTULO 4. CLASSES E OBJETOS

public: O atributo, construtor ou método é visı́vel do exterior da classe,


por outros objetos.

private: O atributo, construtor ou método apenas é visı́vel do interior da


própria classe.

protected: O atributo, construtor ou método apenas é visı́vel do interior da


própria classe, sendo passado por herança às suas subclasses (veremos
este caso num capı́tulo mais adiante).

No exemplo da classe Automóvel apresentado na Figura 4.2, as variáveis


de instância marca, modelo e matricula são de acesso público, sendo visı́veis
por outros objetos instância de qualquer classe, enquanto a variável de
instância potencia é de acesso privado, sendo apenas visı́vel pela própria
instância de Automovel. O construtor e os métodos apresentados na mesma
classe são de acesso público.

4.2.2 A referência this


No desenvolvimento do código dos métodos em uma dada classe há, por
vezes, a necessidade de referenciarmos uma variável de instância própria,
ou invocar métodos internos ao objeto instância da classe. No entanto,
internamente, o objeto não tem identificador para ser referenciado por nome.
Em java, sempre que dentro do código de uma dada classe pretendemos ter
acesso a uma variável, ou método, da mesma classe, podemos fazê-lo usando
a palavra this, que é uma referência especial. Para que um objeto possa
referenciar-se a si próprio para a utilização direta de um atributo ou para
invocação de um método, existe uma forma de auto-referência: this.
No exemplo da classe Automóvel apresentado na Figura 4.2, a referência
this é usada nos métodos setPotencia(. . . ) e getPotencia(. . . ). Enquanto no
primeiro esta utilização era obrigatória, pois existe outra variável (parâmetro
do método) com o mesmo nome que a variável de instância que se pretendia
utilizar, no segundo método a referencia this era opcional, pois não havia
aqui conflito de nomes entre variáveis.

4.3 Sobrecarga de Operadores/métodos


A sobrecarga de operadores (métodos) surge quando usamos o mesmo nome
para vários operadores, mas com assinaturas diferentes. Ou seja, é possı́vel
dar o mesmo nome a diferentes métodos, numa mesma classe, desde que
a assinatura desses métodos seja diferente. O que é a assinatura de um
método? O nome do mesmo e o tipo e ordem dos seus parâmetros.
No exemplo seguinte, a classe Carro tem uma sobrecarga do método
pintar de com um, dois e três parâmetros.

27 Prog. Orientada por Objetos com UML e Java - A. Miguel R. da Cruz


CAPÍTULO 4. CLASSES E OBJETOS

public class Carro {


private String corGeral;
private String corTejadilho;
private String corPortas;
private String marca;
private int potencia;

public Carro(){}

public Carro(String newCor){


corGeral = corTejadilho = corPortas = newCor;
}

public String getCorGeral() {


return corGeral;
}

public String getCorTejadilho() {


return corTejadilho;
}

public String getCorPortas() {


return corPortas;
}

public String getMarca() {


return marca;
}

public void setMarca(String marca) {


this.marca = marca;
}

public int getPotencia() {


return potencia;
}

public void setPotencia(int potencia) {


this.potencia = potencia;
}

public void pintar_de(String newCor){


corGeral = corTejadilho = corPortas = newCor;
}

Prog. Orientada por Objetos com UML e Java - A. Miguel R. da Cruz 28


CAPÍTULO 4. CLASSES E OBJETOS

public void pintar_de(String newCorGeral, String newCorPortas){


corGeral = corTejadilho = newCorGeral;
corPortas = newCorPortas;
}

public void pintar_de(String newCorGeral,


String newCorPortas,
String newCorTejadilho){
corGeral = newCorGeral;
corPortas = newCorPortas;
corTejadilho = newCorTejadilho;
}
}

4.4 Atributos e métodos de Classe


Atributos e métodos definidos numa classe pertencem, em geral, às suas
instâncias, não à classe, e têm valores individuais por instância. Por exem-
plo, cada cliente tem o seu próprio nome e a sua própria morada.
No entanto, por vezes precisamos de atributos cujos valores possam ser
partilhados por todos os objetos de uma classe. Nestes casos podemos definir
atributos ao nı́vel da classe, não das suas instâncias.
No exemplo abaixo, da classe Cliente, temos vários atributos ou variáveis
de instância (nome, morada, id) e temos um atributo ou variável de classe
(nClientes) o qual contém o número de objetos Cliente criados até ao
momento. O atributo nClientes pertence à classe Cliente, não às suas
instâncias, mas pode ser acedido e alterado por estas, sendo o seu valor
visı́vel por todas elas.

public class Cliente {


private String nome;
private String morada;
private int id;
private static int nClientes=0;

public Cliente(String nome){


this.nome = nome;
this.id = ++nClientes;
}

public String getNome() {


return nome;
}

29 Prog. Orientada por Objetos com UML e Java - A. Miguel R. da Cruz


CAPÍTULO 4. CLASSES E OBJETOS

public void setNome(String nome) {


this.nome = nome;
}

public String getMorada() {


return morada;
}

public void setMorada(String morada) {


this.morada = morada;
}

public int getId() {


return id;
}

public static int getnClientes() {


return nClientes;
}

Um atributo de classe inclui a palavra reservada static na sua declaração


e, tal como com os atributos de instância, estes também devem ser private,
sendo o seu acesso controlado através da criação ou não de getters e setters
públicos. Estes métodos devem, neste caso, pertencer também à classe, e
não às suas instâncias, pelo que devem também ser declarados static.
No exemplo da classe Cliente, acima, foi declarado um método de classe
getnClientes() para aceder ao valor do atributo de classe nClientes. Não
temos no entanto um setter para esse atributo, pois o seu valor é calculado
através do incremento do valor anterior sempre que é instanciado um novo
objeto Cliente (ver o código do construtor). A variável de instância id é
também calculada no momento da criação do objeto, não tendo também um
método setter.
O código da figura 4.5 ilustra a utilização dos métodos de instância getId
e de classe getnClientes(). O output da sua execução encontra-se na figura
4.6.
Note-se que, um método de classe pode e deve ser chamado diretamente
no contaxto da classe (Cliente.getnClientes()), embora também possa ser
chamado nas suas instâncias. Como o método pertence e é executado no
contexto da classe, não pode ser usada a palavra reservada this, pois não
existe uma instância. Mesmo que o método seja chamado numa instância da

Prog. Orientada por Objetos com UML e Java - A. Miguel R. da Cruz 30


CAPÍTULO 4. CLASSES E OBJETOS

Figura 4.5: código Java utilizando a classe Cliente.

classe, ele será sempre executado no contexto da classe, e o resultado será o


mesmo.

Figura 4.6: Output da execução do código Java anterior.

4.5 Tipos enumerados de dados


Já vimos que uma classe define um tipo de dados por referência. há por vezes
a necessidade de criar tipos de dados cujos valores possı́veis conhecemos e
queremos declarar e enumerar. Nestes casos, podemos criar um tipo de
dados enumerado (ver exemplo na figura 4.7).

Figura 4.7: Tipo de Dados Enumerado em Java.

As variáveis de um tipo de dados enumerado contêm um valor desse tipo,


e não uma referência. No exemplo da figura 4.8 podemos ver um exemplo de

31 Prog. Orientada por Objetos com UML e Java - A. Miguel R. da Cruz


CAPÍTULO 4. CLASSES E OBJETOS

utilização do tipo de dados enumerado V elocidade definido anteriormente.

Figura 4.8: Exemplo de utilização de tipo de dados enumerado.

4.6 Arrays de Objetos


Antes de resumirmos este capı́tulo, é importante ainda falar sobre arrays de
objetos. Em Java, a utilização de arrays de objetos não tem tanto interesse
como em linguagens como o C, pois o Java oferece um conjunto de classes
que nos permite criar coleções com muito maior liberdade do que através
da criação de arrays. No entanto, a utilização de arrays pode ter interesse e
tem seguramente o seu lugar na linguagem Java.
Como vimos anteriormente na secção 3.2.2, um array em Java de tipo
T ipo é declarado como:

Tipo[] varArray;

ou

Tipo varArray[];

ou

Tipo varArray[20];

sendo que nos dois primeiros casos, não é reservado espaço em memória para
os dados do array, enquanto no terceiro caso é reservado espaço para 20 itens
de tipo T ipo.
Assim como na secção 3.2.2 foram declarados arrays de tipos primiti-
vos, podemos declarar arrays de tipos de referência, nomeadamente Classes.
Observemos, assim, o seguinte exemplo:

Cliente[] clientes;
clientes = new Cliente[10];

clientes[0] = new Cliente("Maria");

Prog. Orientada por Objetos com UML e Java - A. Miguel R. da Cruz 32


CAPÍTULO 4. CLASSES E OBJETOS

clientes[1] = new Cliente("Jo\~ao");

System.out.println(clientes[0].getNome());
System.out.println(clientes[1].getNome());
Neste exemplo é declarado o array clientes de objetos de tipo Cliente.
Depois é reservado espaço em memória, para o array, para 10 clientes (i.e. 10
objetos de tipo Cliente). De seguida, é criado um cliente de nome ”Maria”,
o qual é atribuı́do à primeira posição do array clientes, e outro objeto de
tipo Cliente, com nome ”João”, o qual é atribuı́do à segunda posição do
array clientes. Por fim é impresso no ecrã o nome de cada um dos dois
primeiros clientes do array clientes.

4.7 De UML para Java


Para finalizar o capı́tulo, vamos abordar a relação entre as linguagens UML
e Java, através de um exemplo mais completo.

Figura 4.9: Modelo de classes em UML.

Considere-se o problema modelado na Figura 4.9, onde Um cliente está


associado a várias faturas . . .

4.8 Exercı́cios
4.8.1 Exercı́cio 1
Implemente a classe Retângulo, a qual tem dois atributos públicos de tipo
float, largura e altura. No método main() instancie um Retângulo, e altere

33 Prog. Orientada por Objetos com UML e Java - A. Miguel R. da Cruz


CAPÍTULO 4. CLASSES E OBJETOS

a sua largura e altura.

4.8.2 Exercı́cio 2
Altere a classe Retângulo anterior, de forma a que os seus atributos, largura
e altura, sejam privados. Crie também os getters e setters de largura e altura.
No método main() instancie um Retângulo, e altere a sua largura e altura.

4.8.3 Exercı́cio 3
Codifique a classe ContaBancária com os seguintes atributos e métodos:
(a) Uma variável de instância de acesso privado, titular, com tipo String.

(b) Uma variável de instância de acesso privado, saldo, com tipo double,
e com valor 0.0 por defeito.

(c) Uma variável de instância de acesso privado, dataAbertura, com tipo


Date, e com valor por defeito a data de hoje.

(d) Um construtor de instâncias da classe que recebe por parâmetro o


nome do titular e cria uma conta bancária para esse titular, na data
de hoje, e com saldo zero.

(e) Os métodos getters e setters para o saldo. E, apenas o método getter


para a data de abertura e para o titular.

(f) Um método getInformaçãoConta() que retorna uma String com o titu-


lar, o saldo da conta com duas casas decimais e a data de abertura da
conta no formato DD/MM/YYYY. Ex.: Titular: José Fonseca Saldo:
e321.50 Data Abertura: 21/2/2017.

(g) Um método depositar(. . . ) que recebe o valor a depositar na conta


(double) e atualiza o respetivo saldo.

(h) Um método levantar(. . . ) que recebe o valor a levantar da conta (dou-


ble) e atualiza o respetivo saldo. Não devem ser permitidos levanta-
mentos que coloquem o saldo negativo.
Escreva a função main() para testar a classe ContaBancária. Crie uma
conta, efetue depósitos e levantamentos e imprima no ecrã a informação da
conta sempre que atualiza o saldo.

4.8.4 Exercı́cio 4
Codifique a classe Banco com os seguintes atributos e métodos:
(a) Um array, contas, de objetos do tipo ContaBancária (ver exercı́cio
anterior).

Prog. Orientada por Objetos com UML e Java - A. Miguel R. da Cruz 34


CAPÍTULO 4. CLASSES E OBJETOS

(b) Um construtor de instâncias da classe, sem parâmetros, que inicializa


o array para cem itens.

(c) Os métodos getters e setters para o array contas.

(d) O método criaConta(. . . ) que recebe uma contaBancária por parâmetro


e acrescenta ao array.

(e) O método getConta(. . . ) que recebe o titular por parâmetro e devolve


a conta desse titular.

Escreva a função main() para testar a classe Banco. Crie uma conta, efetue
depósitos e levantamentos e imprima no ecrã a informação da conta sempre
que atualiza o saldo.

4.8.5 Exercı́cio 5
Escreva em Java a classe Ventoinha que representa uma ventoı́nha do mundo
real. Esta classe tem os seguintes atributos e métodos:

(a) Uma variável de instância de acesso privado, ligado, com tipo boolean,
que indica se a ventoı́nha está ligada (true) ou não (f alse). O valor
por defeito é f alse.

(b) Uma variável de instância de acesso privado, velocidade, com tipo


Velocidade (ver tipo de dados enumerado na figura 4.7). O valor por
defeito é BAIXA.

(c) Um construtor sem parâmetros.

(d) Os métodos getter e setter para a velocidade.

(e) Um método isLigado(), que funciona como getter do atributo ’ligado’.

(f) Um método ligar() que liga a ventoı́nha.

(g) Um método desligar() que desliga a ventoı́nha.

(h) Um método toString() que devolve uma String com o estado atual da
ventoı́nha.

Escreva a função main() para testar a classe Ventoinha. Crie uma Ventoinha,
ligue-a, altere a velocidade, desligue-a e imprima no ecrã a informação do
estado da ventoı́nha, sempre que o mesmo é alterado.

4.8.6 Exercı́cio 6
Implemente a classe Singleton, a qual apenas deve permitir a existência de
uma única instância de si própria.

35 Prog. Orientada por Objetos com UML e Java - A. Miguel R. da Cruz

Você também pode gostar