Revisões de programação imperativa Transição para o Java

Propaganda
Revisões de programação imperativa
Transição para o Java
PCO / PPO
Departamento de Informática
Faculdade de Ciências da Universidade de Lisboa
Resumo
➡ Revisões de programação imperativa e transição para o
Java
➡
aspectos básicos de sintaxe
➡
pacotes e classes
➡
o método main
➡
métodos: assinatura e corpo
➡
variáveis: declaração, atribuição e uso
➡
tipos primitivos e operadores
➡
instruções condicionais: if-then-else, switch-case
➡
iteração: while, do-while, for
➡
recursão
2
“Hello world!” em Java
package pco;
/*
* This program simply prints "Hello world!"
*/
public class HelloWorld {
public static void main(String[] args) {
// Print "Hello world!"
System.out.println("Hello World!");
}
}
➡ Ao nível mais básico há bastantes semelhanças com a sintaxe de
C / C++ / C#, por exemplo na forma de comentários, uso de ‘;’ e
chavetas, palavras-chave, operadores, etc
➡ Comecemos por examinar esses aspectos …
3
Comentários
package pco;
/*
* This program simply prints "Hello world!"
*/
public class HelloWorld {
public static void main(String[] args) {
// Print "Hello world!"
System.out.println("Hello World!");
}
}
➡ Comentários em código fonte.
➡
➡
multi-linha: entre /* e */
até ao fim da linha: iniciados com //
4
Classes e pacotes
package pco;
/*
* This program simply prints "Hello world!"
*/
public class HelloWorld {
public static void main(String[] args) {
// Print "Hello world!"
System.out.println("Hello World!");
}
}
➡
Código organizado em pacotes (“packages”), do qual podem fazer
parte várias classes.
➡
➡
A classe HelloWorld faz parte do pacote pco.
Em associação à classe, definimos um programa cujo ponto de
entrada é o método main.
5
Instruções
package pco;
/**
* This program simply prints "Hello world!"
*/
public class HelloWorld {
public static void main(String[] args) {
// Print "Hello world!"
System.out.println("Hello World!");
}
}
➡ Instruções
➡
➡
uma instrução simples (comando) é terminada com ‘;’
um bloco de instruções é agrupado com chavetas (entre { e })
6
Em mais detalhe …
public static void main(String[] args) {
// Print "Hello world!"
System.out.println("Hello World!");
}
➡
➡
➡
➡
➡
➡
➡
➡
➡
Alguns conceitos que iremos desenvolver a seguir …
Assinatura de um método
o nome é main
o tipo de retorno é void, significando que o método não retorna nenhum
valor;
o método tem apenas um parâmetro: args com tipo String[], um vector
de strings (passados externamente ao programa e ignorados neste caso)
dois modificadores, de que não falaremos por agora: public e static
Corpo de um método
bloco de instruções agrupadas em bloco (entre chavetas) a seguir à assinatura
main contém apenas uma instrução, que trata de chamar o método println
sobre o objecto System.out passando como argumento a string “Hello
World!”
7
Exemplo 2 (max)
package pco;
public class MaxExample {
public static int max(int a, int b) {
int r;
if (a > b) {
r = a;
} else {
r = b;
}
return r;
}
public static void main(String[] args) {
System.out.println( max(100, 200) );
}
}
➡ Exemplo simples que ilustra:
➡
➡
➡
uso de tipos primitivos (int) e operadores ( < , = )
declaração e uso de parâmetros e variáveis locais (a, b, r)
fluxo de controlo: bloco condicional if-else, retorno de
valores com return, chamada a max a partir de main
8
Declaração de variavéis
public static int max(int a, int b) {
int r;
if (a > b) {
r = a;
} else {
r = b;
}
return r;
}
➡ A declaração de uma variável compreende o seu tipo e o seu nome. O
compilador de Java valida que:
➡
a declaração antecede sempre qualquer uso da variável;
➡
em cada âmbito de declarações, não há 2 variáveis com o mesmo nome;
➡
uma variável tem sempre um valor definido antes de ser lida;
➡
➡
No exemplo o tipo da variável é int e o nome é r.
Podemos remover a declaração de r? Declará-la apenas após o if-else ou
várias vezes ? Mudar o nome de r para a? Remover uma das atribuições a r ?
NÃO!
9
Tipos primitivos
Tipo
Descrição
boolean
valor booleano
char
caracter Unicode de 16-bits
byte
inteiro de 8 bits
short
inteiro de 16 bits
int
inteiro de 32 bits
long
inteiro de 64 bits
float
número de vírgula flutuante de 32 bits
double
número de vírgula flutuante de 64 bits
➡ A um tipo primitivo associam-se valores elementares com determinado
âmbito (ex. -2^31 a 2^31-1 para int) .
➡ Veja:
https://docs.oracle.com/javase/tutorial/java/nutsandbolts/
datatypes.html para uma descrição dos tipos primitivos em Java.
10
Operadores
➡ Consulte https://docs.oracle.com/javase/tutorial/java/nutsandbolts/operators.html
11
Sobrecarga de métodos
public static int max(int a, int b) {
. . . // código anterior
}
public static double max(double a, double b) {
double r;
if (a > b) {
r = a;
} else {
r = b;
}
return r;
}
public static void main(String[] args) {
System.out.println( max(1, 3) );
System.out.println( max(1.5, 3.4) );
}
}
➡ Sobrecarga de métodos
➡
➡
podemos definir métodos diferentes com o mesmo nome desde que
não haja ambiguidade entre as respectivas assinaturas
no exemplo main invoca a variante de max para valores de tipo int e
depois a variante para valores de tipo double
12
Fluxo de controlo
➡ Condicionais
➡
if - else
➡
uso de operadores && e ||
➡
switch - case
➡ Iteração (ciclo)
➡
for
➡
while
➡
do-while
➡ Retorno de método
➡
return
13
If, else if
public static boolean isHexDigit(char c) {
boolean r;
if (c >= '0' && c <= '9') {
r = true;
} else if (c >= 'a' && c <= 'f') {
r = true;
} else if (c >= 'A' && c <= 'F') {
r = true;
} else {
r = false;
}
return r;
}
➡ Exemplo testa se um caracter corresponde a um dígito hexadecimal.
➡ Consulte valores numéricos para os caracteres em https://en.wikipedia.org/wiki/
List_of_Unicode_characters#Basic_Latin
14
Codificação alternativa
do exemplo anterior
public static
boolean r;
if (c >= '0'
r = true;
} else if (c
r = true;
} else if (c
r = true;
} else {
r = false;
}
return r;
boolean isHexDigit(char c) {
&& c <= '9') {
>= 'a' && c <= 'f') {
>= 'A' && c <= 'F') {
}
public static
return
(c
|| (c
|| (c
}
boolean isHexDigit(char c) {
>= '0' && c <= '9')
>= 'a' && c <= 'f')
>= 'A' && c <= 'F');
➡ Fluxo condicional implícito no uso de && e ||.
➡ Em a && b a expressão b só é avaliada se a avaliação (prévia) de a der
true
➡ Em a
false
||
b a expressão b só é avaliada se a avaliação (prévia) de a der
15
Switch-case
public static String monthString(int month) {
String str;
switch (month) {
case 1: str = "January"; break;
case 2: str = "February"; break;
case 3: str = "March";
break;
case 4: str = "April";
break;
case 5: str = "May";
break;
case 6: str = "June";
break;
case 7: str = "July";
break;
case 8: str = "August";
break;
case 9: str = "September";break;
case 10: str = "October"; break;
case 11: str = "November"; break;
case 12: str = "December"; break;
default: str = "Invalid"; break;
}
return str;
}
➡ Bloco switch-case
16
Switch-case
public static int someFunc(int n) {
int r = 0;
switch (n) {
case 0:
r = 1;
case 1:
r = r + n + 1;
break;
case 2:
case 3:
r = n+1;
break;
default:
r = n;
}
return r;
}
➡ Note-se a ausência de break em case 0 e o tratamento conjunto dos
casos em que n é 2 ou 3.
➡ Qual será o resultado do método para n entre 0 e 5 ?
17
Exemplo - factorial
package pco;
public class FactorialExample {
public static int factorial(int n) {
int r = 1;
int i = 1;
while (i <= n) {
r = r * i;
i = i + 1;
}
return r;
}
public static void main(String[] args) {
int f4_plus_1 = factorial(4) + 1;
System.out.println( f4_plus_1 );
}
}
➡4!=4x3x2x1
➡ Qual o valor impresso pelo programa?
➡ Como se desenrola a execução do ciclo while
?
18
Factorial - codificações alternativas
public static int factorial(int n) {
int r = 1;
for (int i = 1; i <= n; i++) {
r = r * i;
}
return r;
}
➡ Implementação usando ciclo for.
➡ Equivalente em termos de execução à anterior.
19
Factorial - codificações alternativas
public static int factorial(int n) {
int r = 1;
int i = 1;
do {
r = r * i;
i = i + 1;
} while (i <= n);
return r;
}
➡
➡
Iteração usando ciclo do-while.
Embora o resultado seja o mesmo, qual é a diferença na execução em
relação às alternativas anteriores?
20
Factorial - codificações alternativas
public static int factorial(int n) {
if (n == 1)
return 1;
else
return n * factorial(n - 1);
}
➡
➡
Iteração usando recursão.
Qual é a diferença na execução em relação às alternativas anteriores?
21
Vectores (“arrays”)
package pco;
public class PrintProgramArguments {
public static void main(String[] args) {
for (int i=0; i < args.length; i++) {
System.out.println(args[i]);
}
}
}
➡ Um vector (“array”) é um objecto especial que contém um numero
fixo de elementos de determinado tipo.
➡ No exemplo: o programa imprime todos os argumentos que lhe são
fornecidos em args, um vector de strings.
➡
➡
o tamanho é dado por args.length e não pode ser alterado
o acesso a cada posição é definido por args[i]
22
Vectores (“arrays”)
package pco;
public class PrintProgramArguments {
public static void main(String[] args) {
for (int i=0; i < args.length; i++) {
System.out.println(args[i]);
}
}
}
args •
Ana
Berto
Carlos
“Ana”
“Beto”
“Carlos”
0
1
2
args.length = 3
No Eclipse configure os argumentos no
menu “Run As > Run Configurations”.
23
Validação de acessos
vs.
i < args.length
i <= args.length
for (int i=0; i <= args.length; i++) {
System.out.println(args[i]);
}
args •
“Ana”
“Beto”
“Carlos”
0
1
2
3?
Ana
Beto
Carlos
Exception in thread "main"
java.lang.ArrayIndexOutOfBoundsException: 3
at pco.PrintProgramArguments.main(PrintProgramArguments.java:6)
➡ Com i <= args.length o programa irá aceder à posição 3, que é inválida.
➡ Erro de execução (excepção): ArrayIndexOutOfBoundsException
24
Vectores (“arrays”)
- validação de acessos ➡ O acesso a uma posição de um vector é sempre validado
pela máquina virtual Java.
➡ No
caso de acesso inválido, a excepção
ArrayIndexOutOfBoundsException
é lançada
automaticamente, causando no exemplo anterior a
terminação abrupta do programa.
➡ De forma geral, excepções assinalam eventos anómalos de
vária ordem, eventualmente tratáveis pelo programa. Iremos
ver depois como funciona o mecanismo em detalhe.
25
Vectores e ciclos “for-each”
public class PrintProgramArgumentsUsingForeachLoop {
public static void main(String[] args) {
for (String s : args) {
System.out.println(s);
}
}
}
➡ Programa equivalente ao original.
➡ É usado um ciclo “for-each” (“para-cada”)
➡
➡
➡
Forma geral: for (tipo nomeVar : vector) { ... }
Permite código menos verboso / mais simples.
Conveniente em muitos casos: quando o índice do vector é
irrelevante na iteração e não queremos modificar o vector.
26
Ciclos “for-each”
- segundo exemplo public static int sumElements1(int[] array) {
int sum = 0;
for (int i = 0; i < array.length; i++) {
sum += array[i];
}
return sum;
}
ciclo
for
public static int sumElements2(int[] array) {
int sum = 0;
for (int value : array) {
sum += value;
}
return sum;
}
ciclo
for-each
27
Criação de vectores (1)
public static int[] reverse(int[] v) {
int[] result = new int[v.length];
for (int i=0; i < v.length; i++) {
result [i] = v[v.length - i - 1];
}
return result;
}
public static void main(String[] args) {
int[] a = { 0, 1, 2, 3, 4};
int[] b = reverse(a);
for (int i = 0; i < b.length; i++) {
System.out.println(b[i]);
}
}
•
0
1
2
3
4
➡ Este
programa cria um novo vector, que resulta da
inversão de { 0, 1, 2, 3, 4 }, i.e., { 4, 3, 2, 1, 0 }.
➡ Em
main o vector é construído com os valores
constantes em causa.
28
Criação de vectores (2)
public static int[] reverse(int[] v) {
int[] result = new int[v.length];
for (int i=0; i < v.length; i++) {
result [i] = v[v.length - i - 1];
}
return result;
}
public static void main(String[] args) {
int[] a = { 0, 1, 2, 3, 4};
int[] b = reverse(a);
for (int i = 0; i < b.length; i++) {
System.out.println(b[i]);
}
}
➡ Operador new
•
0
0
0
0
0
•
4
3
2
1
0
•
0
1
2
3
4
define a criação de um vector com um
tamanho dado.
➡ As posições do vector são inicialmente preenchidas com
um valor por defeito (0 no caso de vectores int).
29
Vectores e referências
int[] a = { 1 , 1, 1};
int[] b = a;
b[1] = 2;
System.out.println(a[1]);
System.out.println(b[1]);
if (a == b) {
System.out.println(“a == b”);
}
a
b
•
•
1
1
1
a
b[1] = 2;
b
•
•
1
2
a == b
impressão
1
2
1
➡
➡
O valor de a é atribuido a b … o que isso significa?
➡
➡
➡
Assim, b vai passar a referenciar o mesmo vector que a.
O valor das variáveis em causa não “são” vectores em si, mas antes
referências a vectores …
b[1] = 2 modificará o mesmo vector.
a == b avalia para true
30
Clonagem de vectores
int[] a = { 1 , 1, 1};
int[] b = a.clone();
b[1] = 2;
System.out.println(a[1]);
System.out.println(b[1]);
if (a != b) {
System.out.println(“a != b”);
}
a
b
➡
➡
➡
•
•
1
1
1
a
1
1
1
b
b[1] = 2;
•
•
1
2
a != b
impressão
1
1
1
1
2
1
a.clone() cria uma cópia de a
… e então b contém referência para um vector distinto
Operadores == e != apenas testam se referências são idênticas. Para
testar equivalência de conteúdo podemos usar o método
Arrays.equals().
31
Referência nula (null)
package pco;
public class NullExample {
public static void main(String[] args) {
int[] v = null;
// This will cause NullPointerException to be thrown
int a = v[0];
// The following will not be executed
System.out.println(a);
}
}
Exception in thread "main"
java.lang.NullPointerException
at pco.NullExample.main(NullReferenceExample.java:6)
➡ A referência nula é identificada pela palavra-chave null.
➡ Acesso à referência nula leva à excepção NullPointerException
32
Vectores multi-dimensionais
char[][] v = {
{ 'a', 'b', 'c', 'd'},
{ 'e', 'f', 'g' },
{ 'h', 'i' },
{ 'j' }
};
for (int i = 0; i < v.length; i++) {
for (int j = 0; j < v[i].length; j++) {
System.out.print(v[i][j]);
}
System.out.print('\n');
}
abcd
efg
hi
j
v
•
impressão
• • • •
a
e
h
b
f
i
c
g
j
d
➡ v é um vector com 4 posições
➡ Cada posição de v contém por sua vez uma referência a um vector de
tipo char
33
Vectores multi-dimensionais (2)
int[][] a = new int[3][2]; // equivalent to { {0,0}, {0,0},
{0,0} }
int[][] b = new int[3][]; // equivalent to { null, null, null }
int[][] c = { {0}, { 1, 2 }, {3, 4, 5}};
int[][][] v = { a, b, c };
System.out.println(v[2][1][0]); // What value is printed?
•
v
a
•
• • •
0
0
0
0
0
0
• • •
b
•
/ / /
c
•
• • •
0
1
3
2
4
5
34
Download