2. Noções básicas da linguagem Java
2.1. Introdução
Abordaremos o Java, inicialmente, como uma linguagem de programação clássica. Trataremos dos objetos posteriormente.
Em um programa, encontramos dois tipos de elementos
- dados
- as instruções que os manipulam
Geralmente, procuramos separar os dados das instruções:

2.2. Os dados em Java
O Java utiliza os seguintes tipos de dados:
- números inteiros
- números reais
- caracteres e cadeias de caracteres
- booleanos
- objetos
2.2.1. Tipos de dados predefinidos
Tipo | Codificação | Domínio |
char | 2 bytes | caractere Unicode |
int | 4 bytes | [-231, 231-1] |
long | 8 bytes | [-263, 263 -1] |
byte | 1 byte | [-27 , 27 -1] |
short | 2 bytes | [-215, 215-1] |
float | 4 bytes | [3.4 10-38, 3.4 10+38] em valor absoluto |
double | 8 bytes | [1.7 10-308 , 1.7 10+308] em valor absoluto |
boolean | 1 bit | verdadeiro, falso |
String | referência do objeto | cadeia de caracteres |
Date | referência de objeto | data |
Character | referência do objeto | caractere |
Integer | referência do objeto | int |
Long | referência do objeto | long |
Byte | referência do objeto | byte |
Float | referência do objeto | float |
Double | referência de objeto | double |
Boolean | referência de objeto | booleano |
2.2.2. Notação de dados literais
entier | 145, -7, 0xFF (hexadecimal) |
real duplo | 134,789, -45E-18 (-45 × 10⁻¹⁸) |
real float | 134.789F, -45E-18F (-45 × 10⁻¹⁸) |
caractère | 'A', 'b' |
cadeia de caracteres | "hoje" |
booléen | verdadeiro, falso |
date | new Date(13,10,1954) (dia, mês, ano) |
2.2.3. Declaração de dados
2.2.3.1. Função das declarações
Um programa manipula dados caracterizados por um nome e um tipo. Esses dados são armazenados na memória. No momento da compilação do programa, o compilador atribui a cada dado um espaço na memória caracterizado por um endereço e um tamanho. Ele faz isso com base nas declarações feitas pelo programador.
Além disso, essas declarações permitem que o compilador detecte erros de programação. Assim, a operação
x = x * 2;
será declarada como errada se x for uma sequência de caracteres, por exemplo.
2.2.3.2. Declaração de constantes
A sintaxe para declarar uma constante é a seguinte:
final tipo nome=valor; //define a constante nome=valor
ex.: final float PI=3.141592F;
Observação
Por que declarar constantes?
- A leitura do programa será mais fácil se dermos à constante um nome significativo:
ex.: final float taux_tva = 0.186F;
- A modificação do programa será mais fácil caso a “constante” venha a mudar. Assim, no caso anterior, se a alíquota do IVA passar para 33%, a única alteração a ser feita será modificar a instrução que define seu valor:
final float taux_tva=0.33F;
Se tivéssemos usado 0,186 explicitamente no programa, seria necessário alterar várias instruções.
2.2.3.3. Declaração de variáveis
Uma variável é identificada por um nome e está associada a um tipo de dados. O nome de uma variável Java tem n caracteres, sendo o primeiro alfabético e os demais alfabéticos ou numéricos. O Java diferencia maiúsculas de minúsculas. Assim, as variáveis FIN e fin são diferentes.
As variáveis podem ser inicializadas no momento de sua declaração. A sintaxe para declarar uma ou mais variáveis é:
onde identificateur_de_type é um tipo predefinido ou um tipo de objeto definido pelo programador.
2.2.4. As conversões entre números e cadeias de caracteres
número -> string | "" + número |
cadeia -> int | Integer.parseInt(cadeia) |
cadeia de caracteres -> long | Long.parseLong(string) |
string -> double | Double.valueOf(string).doubleValue() |
string -> float | Float.valueOf(string).floatValue() |
Aqui está um programa que apresenta as principais técnicas de conversão entre números e cadeias de caracteres. A conversão de uma cadeia de caracteres em um número pode falhar se a cadeia não representar um número válido. Nesse caso, ocorre um erro fatal, chamado de exceção em Java. Esse erro pode ser tratado pela cláusula try/catch a seguir:
try{
appel de la fonction susceptible de générer l'exception
} catch (Exception e){
traiter l'exception e
}
instruction suivante
Se a função não gerar uma exceção, passa-se para a instrução seguinte; caso contrário, passa-se para o corpo da cláusula catch e, em seguida, para a instrução seguinte. Voltaremos mais tarde ao gerenciamento de exceções.
import java.io.*;
public class conv1{
public static void main(String arg[]){
String S;
final int i=10;
final long l=100000;
final float f=(float)45.78;
double d=-14.98;
// número --> string
S=""+i;
affiche(S);
S=""+l;
affiche(S);
S=""+f;
affiche(S);
S=""+d;
affiche(S);
//booleano --> string
final boolean b=false;
S=""+new Boolean(b);
affiche(S);
// cadeia de caracteres --> int
int i1;
i1=Integer.parseInt("10");
affiche(""+i1);
try{
i1=Integer.parseInt("10.67");
affiche(""+i1);
} catch (Exception e){
affiche("Erreur "+e);
}
// string --> long
long l1;
l1=Long.parseLong("100");
affiche(""+l1);
try{
l1=Long.parseLong("10.675");
affiche(""+l1);
} catch (Exception e){
affiche("Erreur "+e);
}
// cadeia de caracteres --> double
double d1;
d1=Double.valueOf("100.87").doubleValue();
affiche(""+d1);
try{
d1=Double.valueOf("abcd").doubleValue();
affiche(""+d1);
} catch (Exception e){
affiche("Erreur "+e);
}
// cadeia de caracteres --> float
float f1;
f1=Float.valueOf("100.87").floatValue();
affiche(""+f1);
try{
d1=Float.valueOf("abcd").floatValue();
affiche(""+f1);
} catch (Exception e){
affiche("Erreur "+e);
}
}// fim main
public static void affiche(String S){
System.out.println("S="+S);
}
}// fim da classe
Os resultados obtidos são os seguintes:
S=10
S=100000
S=45.78
S=-14.98
S=false
S=10
S=Erreur java.lang.NumberFormatException: 10.67
S=100
S=Erreur java.lang.NumberFormatException: 10.675
S=100.87
S=Erreur java.lang.NumberFormatException: abcd
S=100.87
S=Erreur java.lang.NumberFormatException: abcd
2.2.5. As tabelas de dados
Uma matriz em Java é um objeto que permite agrupar, sob um mesmo identificador, dados do mesmo tipo. Sua declaração é a seguinte:
Tipo Tabela[] = new Tipo[n] ou Tipo[] Tabela = new Tipo[n]
Ambas as sintaxes são válidas. n é o número de dados que a matriz pode conter. A sintaxe Matriz[i] designa o dado nº i, onde i pertence ao intervalo [0,n-1]. Qualquer referência ao dado Tableau[i] em que i não pertença ao intervalo [0,n-1] provocará uma exceção.
Uma matriz bidimensional pode ser declarada da seguinte forma:
Tipo Tabela[][] = new Tipo[n][p] ou Tipo[][] Tabela = new Tipo[n][p]
A sintaxe Tableau[i] designa o dado nº i de Tableau, onde i pertence ao intervalo [0,n-1]. Tableau[i] é, por sua vez, uma tabela: Tableau[i][j] designa o dado nº j da Tabela[i], onde j pertence ao intervalo [0,p-1]. Qualquer referência a um dado de Tableau com índices incorretos gera um erro fatal.
Veja um exemplo:
public class test1{
public static void main(String arg[]){
float[][] taux=new float[2][2];
taux[1][0]=0.24F;
taux[1][1]=0.33F;
System.out.println(taux[1].length);
System.out.println(taux[1][1]);
}
}
e os resultados da execução:
Um array é um objeto que possui o atributo length: trata-se do tamanho do array.
2.3. As instruções básicas do Java
Distinguem-se
- as instruções elementares executadas pelo computador
- as instruções de controle do andamento do programa.
As instruções elementares ficam claras quando se considera a estrutura de um microcomputador e de seus periféricos.

-
leitura de informações provenientes do teclado
-
processamento de informações
-
exibição de informações na tela
-
leitura de informações de um arquivo em disco
-
gravação de informações em um arquivo no disco
2.3.1. Gravação na tela
A sintaxe da instrução de gravação na tela é a seguinte:
System.out.println(expressão) ou System.err.println(expressão)
onde expression é qualquer tipo de dado que possa ser convertido em sequência de caracteres para ser exibido na tela. No exemplo anterior, vimos duas instruções de gravação:
System.out grava em um arquivo de texto que, por padrão, é a tela. O mesmo se aplica a System.err. Esses arquivos possuem um número (ou descripteur) correspondente a 1 e 2, respectivamente. O fluxo de entrada do teclado (System.in) também é considerado um arquivo de texto, com o descritor 0. Tanto o DOS quanto o Unix suportam o uso de tubos (pipe) entre comandos:
Tudo o que o commande1 escreve com o System.out é redirecionado para a entrada do System.in do commande2. Em outras palavras, o commande2 lê, por meio do System.in, os dados produzidos pelo commande2 com o System.out, que, portanto, não são mais exibidos na tela. Esse sistema é amplamente utilizado no Unix. Nessa encadeamento de comandos, o fluxo System.err não é redirecionado: ele escreve na tela. É por isso que é usado para exibir mensagens de erro (daí seu nome err): assim, temos a garantia de que, durante um redirecionamento de comandos, as mensagens de erro continuarão sendo exibidas na tela. Portanto, é recomendável adquirir o hábito de exibir as mensagens de erro na tela usando o fluxo System.err, em vez do fluxo System.out.
2.3.2. Leitura de dados digitados no teclado
O fluxo de dados proveniente do teclado é designado pelo objeto System.in, do tipo InputStream. Esse tipo de objeto permite ler dados caractere por caractere. Cabe ao programador, então, identificar nesse fluxo de caracteres as informações de seu interesse. O tipo InputStream não permite ler uma linha de texto de uma só vez. O tipo BufferedReader permite isso com o método readLine.
Para poder ler linhas de texto digitadas no teclado, cria-se, a partir do fluxo de entrada System.in do tipo InputStream, outro fluxo de entrada, desta vez do tipo BufferedReader:
Não explicaremos aqui os detalhes dessa instrução, que envolve o conceito de construção de objetos. Vamos utilizá-la tal como está.
A construção de um fluxo pode falhar: nesse caso, é gerado um erro fatal, chamado de exceção em Java. Sempre que um método pode gerar uma exceção, o compilador Java exige que ela seja tratada pelo programador. Portanto, para criar o fluxo de entrada anterior, será necessário, na verdade, escrever:
BufferedReader IN=null;
try{
IN=new BufferedReader(new InputStreamReader(System.in));
} catch (Exception e){
System.err.println("Erreur " +e);
System.exit(1);
}
Mais uma vez, não vamos nos aprofundar aqui na gestão de exceções. Depois de criar o fluxo IN mencionado anteriormente, é possível ler uma linha de texto por meio da instrução:
A linha digitada no teclado é armazenada na variável ligne e pode, em seguida, ser utilizada pelo programa.
2.3.3. Exemplo de entradas e saídas
Aqui está um programa que ilustra as operações de entrada e saída do teclado e da tela:
import java.io.*; // necessário para o uso de fluxos de E/S
public class io1{
public static void main (String[] arg){
// gravação no fluxo System.out
Object obj=new Object();
System.out.println(""+obj);
System.out.println(obj.getClass().getName());
// gravação no fluxo System.err
int i=10;
System.err.println("i="+i);
// leitura de uma linha digitada no teclado
String ligne;
BufferedReader IN=null;
try{
IN=new BufferedReader(new InputStreamReader(System.in));
} catch (Exception e){
affiche(e);
System.exit(1);
}
System.out.print("Tapez une ligne : ");
try{
ligne=IN.readLine();
System.out.println("ligne="+ligne);
} catch (Exception e){
affiche(e);
System.exit(2);
}
}//fim da entrada manual
public static void affiche(Exception e){
System.err.println("Erreur : "+e);
}
}//fim de classe
e os resultados da execução:
C:\Serge\java\bases\iostream>java io1
java.lang.Object@1ee78b
java.lang.Object
i=10
Tapez une ligne : je suis là
ligne=je suis là
As instruções
têm como objetivo mostrar que qualquer objeto pode ser exibido. Não vamos explicar aqui o significado do que está sendo exibido. Também temos a exibição do valor de um objeto no bloco:
try{
IN=new BufferedReader(new InputStreamReader(System.in));
} catch (Exception e){
affiche(e);
System.exit(1);
}
A variável e é um objeto do tipo Exception, que é exibido aqui com a chamada affiche(e). Já havíamos encontrado, sem mencionar, essa exibição do valor de uma exceção no programa de conversão visto anteriormente.
2.3.4. Atribuição do valor de uma expressão a uma variável
Vamos nos concentrar aqui na operação variable=expression;
A expressão pode ser do tipo: aritmética, relacional, booleana, de caracteres
2.3.4.1. Interpretação da operação de atribuição
A operação variable=expression; é, por si só, uma expressão cuja avaliação ocorre da seguinte maneira:
- A parte direita da atribuição é avaliada: o resultado é um valor V.
- o valor V é atribuído à variável
- o valor V é também o valor da atribuição, agora considerada como uma expressão.
É assim que a operação V1=V2=expressão é válida. Devido à prioridade, é o operador = mais à direita que será avaliado. Portanto, temos V1=(V2=expressão). A expressão V2=expressão é avaliada e tem como valor V. A avaliação dessa expressão provocou a atribuição de V a V2. O operador = seguinte é então avaliado na forma V1=V. O valor dessa expressão continua sendo V. Sua avaliação resulta na atribuição de V a V1. Assim, a operação V1=V2=expressão é uma expressão cuja avaliação
1: resulta na atribuição do valor de expression às variáveis V1 e V2
2: retorna como resultado o valor de expression.
É possível generalizar para uma expressão do tipo: V1=V2=....=Vn=expressão
2.3.4.2. Expressão aritmética
Os operadores das expressões aritméticas são os seguintes:
+: adição
- : subtração
*: multiplicação
/: divisão: o resultado é o quociente exato se pelo menos um dos operandos for real. Se ambos os operandos forem inteiros, o resultado é o quociente inteiro. Assim, 5/2 → 2 e 5,0/2 → 2,5.
%: divisão: o resultado é o resto, independentemente da natureza dos operandos, sendo o quociente inteiro. Trata-se, portanto, da operação módulo.
Existem diversas funções matemáticas:
double sqrt(double x) | raiz quadrada |
double cos(double x) | Cosseno |
double sin(double x) | seno |
double tan(double x) | Tangente |
double pow(double x, double y) | x elevado a y (x > 0) |
double exp(double x) | Exponencial |
double log(double x) | Logaritmo natural |
double abs(double x) | valor absoluto |
etc...
Todas essas funções estão definidas em uma classe Java chamada Math. Ao utilizá-las, é necessário antepor o nome da classe em que estão definidas. Assim, escreveremos:
A definição da classe Math é a seguinte:
public final class java.lang.Math
extends java.lang.Object (I-§1.12)
{
// Campos
public final static double E; §1.10.1
public final static double PI; §1.10.2
// Métodos
public static double abs(double a); §1.10.3
public static float abs(float a); §1.10.4
public static int abs(int a); §1.10.5
public static long abs(long a); §1.10.6
public static double acos(double a); §1.10.7
public static double asin(double a); §1.10.8
public static double atan(double a); §1.10.9
public static double atan2(double a, double b); §1.10.10
public static double ceil(double a); §1.10.11
public static double cos(double a); §1.10.12
public static double exp(double a); §1.10.13
public static double floor(double a); §1.10.14
public static double §1.10.15
IEEEremainder(double f1, double f2);
public static double log(double a); §1.10.16
public static double max(double a, double b); §1.10.17
public static float max(float a, float b); §1.10.18
public static int max(int a, int b); §1.10.19
public static long max(long a, long b); §1.10.20
public static double min(double a, double b); §1.10.21
public static float min(float a, float b); §1.10.22
public static int min(int a, int b); §1.10.23
public static long min(long a, long b); §1.10.24
public static double pow(double a, double b); §1.10.25
public static double random(); §1.10.26
public static double rint(double a); §1.10.27
public static long round(double a); §1.10.28
public static int round(float a); §1.10.29
public static double sin(double a); §1.10.30
public static double sqrt(double a); §1.10.31
public static double tan(double a); §1.10.32
}
2.3.4.3. Prioridades na avaliação de expressões aritméticas
A prioridade dos operadores na avaliação de uma expressão aritmética é a seguinte (da mais alta à mais baixa):
[fonctions], [ ( )], [ *, /, %], [+, -]
Os operadores de um mesmo bloco [ ] têm a mesma prioridade.
2.3.4.4. Expressões relacionais
Os operadores são os seguintes: <, <=, ==, !=, >, >=
ordem de prioridade
>, >=, <, <=
==, !=
O resultado de uma expressão relacional é o valor booleano false se a expressão for falsa; true caso contrário.
Exemplo:
Comparação de dois caracteres
Sejam dois caracteres C1 e C2. É possível compará-los com os operadores
<, <=, ==, !=, >, >=
Nesse caso, são comparados seus códigos ASCII, que são números. Vale lembrar que, de acordo com a ordem ASCII, temos as seguintes relações:
espaço < .. < '0' < '1' < .. < '9' < .. < 'A' < 'B' < .. < 'Z' < .. < 'a' < 'b' < .. < 'z'
Comparação de duas cadeias de caracteres
Elas são comparadas caractere por caractere. A primeira desigualdade encontrada entre dois caracteres determina uma desigualdade no mesmo sentido nas cadeias.
Exemplos:
Suponhamos que se queira comparar as cadeias “Gato” e “Cão”
Essa última desigualdade permite afirmar que “Gato” < “Cão”.

Suponha que se queira comparar as cadeias “Gato” e “Gatinho”. Há igualdade o tempo todo até que a cadeia “Gato” se esgote. Nesse caso, a cadeia esgotada é declarada como a mais “pequena”. Portanto, temos a relação
“Gato” < “Gatinho”.
Funções de comparação entre duas cadeias
Não é possível utilizar aqui os operadores relacionais <, <=, ==, !=, >, >=. É necessário utilizar métodos da classe String:
String chaine1, chaine2;
chaine1=…;
chaine2=…;
int i=chaine1.compareTo(chaine2);
boolean egal=chaine1.equals(chaine2)
No exemplo acima, a variável i terá o valor:
0: se as duas cadeias forem iguais
1: se a sequência n.º 1 for maior que a sequência n.º 2
-1: se a sequência nº 1 for menor que a sequência nº 2
A variável egal terá o valor true se as duas cadeias forem iguais.
2.3.4.5. Expressões booleanas
Os operadores são & (and) ||(or) e ! (not). O resultado de uma expressão booleana é um valor booleano.
ordem de prioridade ! , &&, ||
exemplo:
Os operadores relacionais têm prioridade sobre os operadores && e ||.
2.3.4.6. Operações em bits
Os operadores
Sejam i e j dois números inteiros.
i<<n | desloca i n bits para a esquerda. Os bits de preenchimento são zeros. |
i>>n | desloca i n bits para a direita. Se i for um inteiro com sinal (signed char, int, long), o bit de sinal é preservado. |
i & j | realiza a operação lógica ET entre i e j, bit a bit. |
i | j | realiza a operação lógica OU entre i e j, bit a bit. |
~i | completa i com 1 |
i^j | gera OU a partir de EXCLUSIF de i e j |
Ou seja
operação | valor |
i<<4 | 0x23F0 |
i>>4 | 0x0123 o bit de sinal é preservado. |
k>>4 | 0xFF12 o bit de sinal é preservado. |
i&j | 0x1023 |
i|j | 0xF33F |
~i | 0xEDC0 |
2.3.4.7. Combinação de operadores
a=a+b pode ser escrito como a+=b
a=a-b pode ser escrito como a-=b
O mesmo se aplica aos operadores /, %, *, <<, >>, &, |, ^
Assim, a=a+2; pode ser escrito como a+=2;
2.3.4.8. Operadores de incremento e decremento
A notação variable++ significa variable=variable+1 ou ainda variable+=1
A notação variable-- significa variable=variable-1 ou ainda variable-=1.
2.3.4.9. O operador?
A expressão expr_cond ? expr1:expr2 é avaliada da seguinte maneira:
1: a expressão expr_cond é avaliada. Trata-se de uma expressão condicional com valor verdadeiro ou falso
2: Se for verdadeira, o valor da expressão é o de expr1. expr2 não é avaliada.
3: Se for falsa, ocorre o contrário: o valor da expressão é o de expr2. expr1 não é avaliada.
Exemplo
i = (j > 4 ? j + 1 : j - 1);
atribuirá à variável i:
j+1 se j>4, j-1 caso contrário
É o mesmo que escrever if(j>4) i=j+1; else i=j-1; mas é mais conciso.
2.3.4.10. Prioridade geral dos operadores
() [] função | gd |
! ~ ++ -- | dg |
new (tipo) operadores de conversão | dg |
* / % | gd |
+ - | gd |
<< >> | gd |
< <= > >= instanceof | gd |
== != | gd |
& | gd |
^ | gd |
| | gd |
&& | gd |
|| | gd |
? : | dg |
= += -= etc. . | dg |
gd: indica que, em caso de igualdade de prioridade, é observada a regra de prioridade da esquerda para a direita. Isso significa que, quando em uma expressão há operadores com a mesma prioridade, o operador mais à esquerda na expressão é avaliado primeiro. dg indica uma prioridade da direita para a esquerda.
2.3.4.11. Mudanças de tipo
É possível, em uma expressão, alterar temporariamente a codificação de um valor. Isso é chamado de alteração do tipo de um dado ou, em inglês, type casting. A sintaxe para alterar o tipo de um valor em uma expressão é (tipo) valor. O valor passa então a ter o tipo indicado. Isso resulta em uma alteração na codificação do valor.
Exemplo:
Aqui é necessário alterar o tipo de i ou j para real; caso contrário, a divisão resultará em um quociente inteiro e não real.
i é um valor codificado com precisão em 2 bytes
(float) i é o mesmo valor codificado de forma aproximada como número real em 4 bytes
Portanto, ocorre uma transcodificação do valor de i. Essa transcodificação ocorre apenas durante o cálculo, já que a variável i mantém sempre seu tipo int.
2.4. As instruções de controle do andamento do programa
2.4.1. Parada
O método exit, definido na classe System, permite interromper a execução de um programa.
ação: interrompe o processo em andamento e retorna o valor status ao processo pai
O método exit encerra o processo em andamento e devolve o controle ao processo chamador. O valor de *status pode ser utilizado por este. No DOS, essa variável status é retornada ao DOS na variável de sistema ERRORLEVEL, cujo valor pode ser verificado em um arquivo batch. No Unix, é a variável $? que recupera o valor de status* se o interpretador de comandos for o Bourne Shell (/bin/sh).
Exemplo:
para encerrar o programa com um valor de status igual a 0.
2.4.2. Estrutura de escolha simples
syntaxe : if (condition) {actions_condition_vraie;} else {actions_condition_fausse;}
observações:
- a condição está entre parênteses.
- cada ação é terminada por ponto-e-vírgula.
- As chaves não são encerradas por ponto-e-vírgula.
- As chaves só são necessárias se houver mais de uma ação.
- A cláusula else pode estar ausente.
- Não há “then”.
O equivalente algorítmico dessa estrutura é a estrutura “se... então... senão”:
exemplo
if (x>0) { nx=nx+1;sx=sx+x;} else dx=dx-x;
É possível aninhar as estruturas de escolha:
Às vezes surge o seguinte problema:
public static void main(void){
int n=5;
if(n>1)
if(n>6)
System.out.println(">6");
else System.out.println("<=6");
}
No exemplo anterior, a referência else se refere a qual if? A regra é que um else sempre se refere ao if mais próximo: if(n>6), no exemplo. Consideremos outro exemplo:
public static void main(void)
{ int n=0;
if(n>1)
if(n>6) System.out.println(">6");
else; // else do if(n>6): nada a fazer
else System.out.println("<=1"); // else do if(n>1)
}
Aqui, queríamos colocar um else no if(n>1) e não um else no if(n>6). Devido à observação anterior, somos obrigados a incluir um else para o if(n>6), no qual não há nenhuma instrução.
2.4.3. Estrutura de casos
A sintaxe é a seguinte:
switch(expression) {
case v1:
actions1;
break;
case v2:
actions2;
break;
. .. .. .. .. ..
default: actions_sinon;
}
notas
- O valor da expressão de controle só pode ser um número inteiro ou um caractere.
- A expressão de controle deve estar entre parênteses.
- A cláusula default pode estar ausente.
- Os valores vi são valores possíveis da expressão. Se a expressão tiver o valor vi, as ações associadas à cláusula case vi serão executadas.
- A instrução break faz com que se saia da estrutura de caso. Se ela estiver ausente no final do bloco de instruções do valor vi, a execução prossegue com as instruções do valor vi+1.
Exemplo
Em algoritmos
selon la valeur de choix
cas 0
arrêt
cas 1
exécuter module M1
cas 2
exécuter module M2
sinon
erreur<--vrai
findescas
Em Java
int choix, erreur;
switch(choix){
case 0: System.exit(0);
case 1: M1();break;
case 2: M2();break;
default: erreur=1;
}
2.4.4. Estrutura de repetição
2.4.4.1. Número de repetições conhecido
Sintaxe
for (i=id;i<=if;i=i+ip){
actions;
}
Notas
- Os três argumentos do for estão entre parênteses.
- Os três argumentos do for são separados por ponto-e-vírgula.
- Cada ação do for é terminada por um ponto-e-vírgula.
- A chave só é necessária se houver mais de uma ação.
- A chave não é seguida de ponto-e-vírgula.
O equivalente algorítmico é a estrutura pour:
que pode ser traduzida por uma estrutura tantque:
2.4.4.2. Número de repetições desconhecido
Existem diversas estruturas em Java para esse caso.
Estrutura “while”
while(condition){
actions;
}
O loop continua enquanto a condição for verdadeira. O loop pode nunca ser executado.
Notas:
- a condição está entre parênteses.
- cada ação é terminada por ponto-e-vírgula.
- A chave só é necessária se houver mais de uma ação.
- A chave não é seguida de ponto-e-vírgula.
A estrutura algorítmica correspondente é a estrutura “enquanto”:
Estrutura “repetir até” (do while)
A sintaxe é a seguinte:
do{
instructions;
}while(condition);
O loop é executado até que a condição se torne falsa ou enquanto a condição for verdadeira. Aqui, o loop é executado pelo menos uma vez.
notas
- a condição está entre parênteses.
- Cada ação é terminada por ponto-e-vírgula.
- A chave só é necessária se houver mais de uma ação.
- A chave não é seguida de ponto-e-vírgula.
A estrutura algorítmica correspondente é a estrutura “repetir … até”:
Estrutura para “for”
A sintaxe é a seguinte:
for(instructions_départ;condition;instructions_fin_boucle){
instructions;
}
O loop é executado enquanto a condição for verdadeira (avaliada antes de cada iteração do loop). Instructions_départ são executadas antes de entrar no loop pela primeira vez. Instructions_fin_boucle são executadas após cada iteração do loop.
notas
- Os três argumentos do for estão entre parênteses.
- Os três argumentos do for são separados por ponto-e-vírgula.
- Cada ação do for é terminada por um ponto-e-vírgula.
- A chave só é necessária se houver mais de uma ação.
- A chave não é seguida de ponto-e-vírgula.
- As diferentes instruções em instructions_depart e instructions_fin_boucle são separadas por vírgulas.
A estrutura algorítmica correspondente é a seguinte:
Exemplos
Todos os programas a seguir calculam a soma dos primeiros n números inteiros.
1 for(i=1, somme=0;i<=n;i=i+1)
somme=somme+a[i];
2 for (i=1, somme=0;i<=n;somme=somme+a[i], i=i+1);
3 i=1;somme=0;
while(i<=n)
{ somme+=i; i++; }
4 i=1; somme=0;
do somme+=i++;
while (i<=n);
Instruções para gerenciamento de loop
break | sai do loop for, while, do ... while. |
continue | avança para a próxima iteração dos loops for, while, do ... while |
2.5. A estrutura de um programa Java
Um programa Java que não utilize classes definidas pelo usuário nem funções além da função principal main poderá ter a seguinte estrutura:
public class test1{
public static void main(String arg[]){
… code du programme
}// main
}// class
A função main, também chamada de método, é executada em primeiro lugar durante a execução de um programa Java. Ela deve obrigatoriamente ter a assinatura a seguir:
public static void main(String arg[]){
ou
public static void main(String[] arg){
O nome do argumento arg pode ser qualquer um. Trata-se de uma matriz de cadeias de caracteres que representam os argumentos da linha de comando. Voltaremos a esse assunto mais adiante.
Se forem utilizadas funções suscetíveis de gerar exceções que não se deseja tratar detalhadamente, é possível envolver o código do programa em uma cláusula try/catch:
public class test1{
public static void main(String arg[]){
try{
… code du programme
} catch (Exception e){
// gestão de erros
}// try
}// main
}// classe
No início do código-fonte e antes da definição da classe, é comum encontrar instruções de importação de classes. Por exemplo:
import java.io.*;
public class test1{
public static void main(String arg[]){
… code du programme
}// main
}// classe
Vamos dar um exemplo. Considere a seguinte instrução de gravação:
que exibe java na tela. Nessa instrução simples, há muitos elementos:
- System é uma classe cujo nome completo é java.lang.System
- out é uma propriedade dessa classe do tipo java.io.PrintStream, outra classe
- println é um método da classe java.io.PrintStream.
Não vamos complicar desnecessariamente essa explicação, que surge muito cedo, já que requer a compreensão do conceito de classe, que ainda não foi abordado. Podemos comparar uma classe a um recurso. Neste caso, o compilador precisará ter acesso às duas classes java.lang.System e java.io.PrintStream. As centenas de classes do Java estão distribuídas em arquivos também chamados de pacotes (package). As instruções import colocadas no início do programa servem para indicar ao compilador de quais classes externas o programa precisa (aquelas utilizadas, mas não definidas no arquivo-fonte que será compilado). Assim, em nosso exemplo, nosso programa precisa das classes java.lang.System e java.io.PrintStream. Isso é indicado com a instrução import. Poderíamos escrever no início do programa:
Como um programa Java costuma utilizar dezenas de classes externas, seria trabalhoso escrever todas as funções import necessárias. As classes foram agrupadas em pacotes, e assim é possível importar o pacote inteiro. Assim, para importar os pacotes java.lang e java.io, escrever-se-á:
O pacote java.lang contém todas as classes básicas do Java e é importado automaticamente pelo compilador. Portanto, no final, basta escrever:
2.6. Gerenciamento de exceções
Muitas funções do Java podem gerar exceções, ou seja, erros. Já encontramos uma função desse tipo, a função readLine:
String ligne=null;
try{
ligne=IN.readLine();
System.out.println("ligne="+ligne);
} catch (Exception e){
affiche(e);
System.exit(2);
}// try
Quando uma função pode gerar uma exceção, o compilador Java obriga o programador a tratá-la, com o objetivo de obter programas mais resistentes a erros: é preciso sempre evitar que um aplicativo “trave” de forma inesperada. Aqui, a função readLine gera uma exceção se não houver nada para ler, por exemplo, porque o fluxo de entrada foi fechado. O tratamento de uma exceção é feito de acordo com o esquema a seguir:
try{
appel de la fonction susceptible de générer l'exception
} catch (Exception e){
traiter l'exception e
}
instruction suivante
Se a função não gerar uma exceção, passa-se para a instrução seguinte; caso contrário, passa-se para o corpo da cláusula catch e, em seguida, para a instrução seguinte. Observe os seguintes pontos:
- e é um objeto derivado do tipo Exception. É possível ser mais preciso utilizando tipos como IOException, SecurityException, ArithmeticException, etc.: existem cerca de vinte tipos de exceções. Ao escrever catch (Exception e), indica-se que se deseja tratar todos os tipos de exceções. Se o código da cláusula try for suscetível de gerar vários tipos de exceções, pode-se querer ser mais preciso, tratando a exceção com várias cláusulas catch:
try{
appel de la fonction susceptible de générer l'exception
} catch (IOException e){
traiter l'exception e
}
} catch (ArrayIndexOutOfBoundsException e){
traiter l'exception e
}
} catch (RunTimeException e){
traiter l'exception e
}
instruction suivante
- É possível adicionar uma cláusula `finally` às cláusulas try/catch:
try{
appel de la fonction susceptible de générer l'exception
} catch (Exception e){
traiter l'exception e
}
finally{
code exécuté après try ou catch
}
instruction suivante
Aqui, haja ou não uma exceção, o código da cláusula finally será sempre executado.
- A classe Exception possui um método getMessage() que retorna uma mensagem detalhando o erro ocorrido. Portanto, se quisermos exibir essa mensagem, escreveremos:
catch (Exception ex){
System.err.println("L'erreur suivante s'est produite : "+ex.getMessage());
...
}//catch
- A classe Exception possui um método toString() que retorna uma sequência de caracteres indicando o tipo da exceção, bem como o valor da propriedade Message. Assim, poderemos escrever:
catch (Exception ex){
System.err.println ("L'erreur suivante s'est produite : "+ex.toString());
...
}//catch
Também é possível escrever:
Temos aqui uma operação string + Exception que será automaticamente transformada em string + Exception.toString() pelo compilador, a fim de realizar a concatenação de duas cadeias de caracteres.
O exemplo a seguir mostra uma exceção gerada pelo uso de um elemento de tabela inexistente:
// quadros
// importações
import java.io.*;
public class tab1{
public static void main(String[] args){
// declaração e inicialização de um array
int[] tab=new int[] {0,1,2,3};
int i;
// exibição de tabela com um for
for (i=0; i<tab.length; i++)
System.out.println("tab[" + i + "]=" + tab[i]);
// geração de uma exceção
try{
tab[100]=6;
}catch (Exception e){
System.err.println("L'erreur suivante s'est produite : " + e);
}//try-catch
}//main
}//classe
A execução do programa produz os seguintes resultados:
tab[0]=0
tab[1]=1
tab[2]=2
tab[3]=3
L'erreur suivante s'est produite : java.lang.ArrayIndexOutOfBoundsException
Aqui está outro exemplo em que se lida com a exceção causada pela atribuição de uma sequência de caracteres a um número, quando a sequência não representa um número:
// importações
import java.io.*;
public class console1{
public static void main(String[] args){
// criação de um fluxo de entrada
BufferedReader IN=null;
try{
IN=new BufferedReader(new InputStreamReader(System.in));
}catch(Exception ex){}
// Solicitação do nome
System.out.print("Nom : ");
// leitura da resposta
String nom=null;
try{
nom=IN.readLine();
}catch(Exception ex){}
// solicitação da idade
int age=0;
boolean ageOK=false;
while ( ! ageOK){
// pergunta
System.out.print("âge : ");
// Leitura e verificação da resposta
try{
age=Integer.parseInt(IN.readLine());
ageOK=true;
}catch(Exception ex) {
System.err.println("Age incorrect, recommencez...");
}//try-catch
}//while
// exibição final
System.out.println("Vous vous appelez " + nom + " et vous avez " + age + " ans");
}//Main
}//classe
Alguns resultados da execução:
E:\data\serge\MSNET\c#\bases\1>console1
Nom : dupont
âge : xx
Age incorrect, recommencez...
âge : 12
Vous vous appelez dupont et vous avez 12 ans
2.7. Compilação e execução de um programa Java
Compile e, em seguida, execute o seguinte programa:
// importação de classes
import java.io.*;
// classe de teste
public class coucou{
// função main
public static void main(String args[]){
// exibição na tela
System.out.println("coucou");
}//main
}//classe
O arquivo de origem que contém a classe coucou anterior deve, obrigatoriamente, ser chamado de coucou.java:
A compilação e a execução de um programa Java são realizadas em uma janela DOS. Os executáveis javac.exe (compilador) e java.exe (interpretador) estão localizados no diretório bin do diretório de instalação do JDK:
E:\data\serge\JAVA\classes\paquetages\personne>dir "e:\program files\jdk14\bin\java?.exe"
07/02/2002 12:52 24 649 java.exe
07/02/2002 12:52 28 766 javac.exe
O compilador javac.exe analisará o arquivo-fonte .java e produzirá um arquivo compilado .class. Este não é imediatamente executável pelo processador. Ele requer um interpretador Java (java.exe), conhecido como máquina virtual ou JVM (Java Virtual Machine). A partir do código intermediário presente no arquivo .class, a máquina virtual irá gerar instruções específicas para o processador da máquina na qual ela está sendo executada. Existem máquinas virtuais Java para diferentes tipos de sistemas operacionais (Windows, Unix, Mac OS, etc.). Um arquivo .class pode ser executado por qualquer uma dessas máquinas virtuais e, portanto, em qualquer sistema operacional. Essa portabilidade entre sistemas é uma das principais vantagens do Java.
Vamos compilar o programa anterior:
E:\data\serge\JAVA\ESSAIS\intro1>"e:\program files\jdk14\bin\javac" coucou.java
E:\data\serge\JAVA\ESSAIS\intro1>dir
10/06/2002 08:42 228 coucou.java
10/06/2002 08:48 403 coucou.class
Vamos executar o arquivo .class gerado:
Observe-se que, na solicitação de execução acima, não foi especificado o sufixo .class do arquivo coucou.class a ser executado. Ele está implícito. Se o diretório bin do JDK estiver no PATH da máquina DOS, não será necessário especificar o caminho completo dos executáveis javac.exe e java.exe. Basta, então, escrever
2.8. Argumentos do programa principal
A função principal main aceita como parâmetros uma matriz de strings: String[]. Essa matriz contém os argumentos da linha de comando usada para iniciar o aplicativo. Assim, se iniciarmos o programa P com o comando:
e se a função main estiver declarada da seguinte forma:
teremos arg[0]="arg0", arg[1]="arg1" … Veja um exemplo:
import java.io.*;
public class param1{
public static void main(String[] arg){
int i;
System.out.println("Nombre d'arguments="+arg.length);
for (i=0;i<arg.length;i++)
System.out.println("arg["+i+"]="+arg[i]);
}
}
Os resultados obtidos são os seguintes:
2.9. Passagem de parâmetros para uma função
Os exemplos anteriores mostraram apenas programas Java com uma única função, a função principal main. O exemplo a seguir mostra como utilizar funções e como ocorre a troca de informações entre elas. Os parâmetros de uma função são sempre passados por valor: ou seja, o valor do parâmetro efetivo é copiado para o parâmetro formal correspondente.
import java.io.*;
public class param2{
public static void main(String[] arg){
String S="papa";
changeString(S);
System.out.println("Paramètre effectif S="+S);
int age=20;
changeInt(age);
System.out.println("Paramètre effectif age="+age);
}
private static void changeString(String S){
S="maman";
System.out.println("Paramètre formel S="+S);
}
private static void changeInt(int a){
a=30;
System.out.println("Paramètre formel a="+a);
}
}
Os resultados obtidos são os seguintes:
Os valores dos parâmetros efetivos “papa” e 20 foram copiados para os parâmetros formais S e a. Estes foram, em seguida, modificados. Os parâmetros efetivos, por sua vez, permaneceram inalterados. É importante observar aqui o tipo dos parâmetros efetivos:
- S é uma referência ao objeto c.a.d. O endereço de um objeto na memória
- age é um valor inteiro
2.10. O exemplo dos impostos
Concluiremos este capítulo com um exemplo que será retomado várias vezes ao longo deste documento. Propomos escrever um programa que permita calcular o imposto de um contribuinte. Consideraremos o caso simplificado de um contribuinte que tenha apenas seu salário para declarar:
- calcula-se o número de cotas do empregado nbParts = nbEnfants/2 + 1 se ele for solteiro, nbEnfants/2 + 2 se for casado, onde nbEnfants é o número de filhos.
- se tiver pelo menos três filhos, ele tem mais meia parcela
- calcula-se sua renda tributável R = 0,72 * S, onde S é seu salário anual
- calcula-se seu coeficiente familiar QF = R / nbParts
- calcula-se seu imposto I. Consideremos a tabela a seguir:
12620,0 | 0 | 0 |
13.190 | 0,05 | 631 |
15.640 | 0,1 | 1.290,5 |
24.740 | 0,15 | 2.072,5 |
31.810 | 0,2 | 3.309,5 |
39.970 | 0,25 | 4.900 |
48.360 | 0,3 | 6.898,5 |
55.790 | 0,35 | 9.316,5 |
92.970 | 0,4 | 12.106 |
127.860 | 0,45 | 16.754,5 |
151.250 | 0,50 | 23.147,5 |
172.040 | 0,55 | 30.710 |
195.000 | 0,60 | 39.312 |
0 | 0,65 | 49.062 |
Cada linha possui 3 campos. Para calcular o imposto I, procura-se a primeira linha em que QF ≤ campo1. Por exemplo, se QF = 23000, será encontrada a linha
O imposto I é, então, igual a 0,15*R - 2072,5*nbParts. Se QF for tal que a relação QF <= campo1 nunca for verificada, então serão utilizados os coeficientes da última linha. Aqui:
o que resulta no imposto I = 0,65 * R - 49.062 * nbParts.
O programa Java correspondente é o seguinte:
import java.io.*;
public class impots{
// ------------ main
public static void main(String arg[]){
// dados
// limites das faixas de imposto
double Limites[]={12620, 13190, 15640, 24740, 31810, 39970, 48360,55790, 92970, 127860, 151250, 172040, 195000, 0};
// coeficiente aplicado ao número de cotas
double Coeffn[]={0, 631, 1290.5, 2072.5, 3309.5, 4900, 6898.5, 9316.5,12106, 16754.5, 23147.5, 30710, 39312, 49062};
// o programa
// criação do fluxo de entrada do teclado
BufferedReader IN=null;
try{
IN=new BufferedReader(new InputStreamReader(System.in));
}
catch(Exception e){
erreur("Création du flux d'entrée", e, 1);
}
// recuperação do estado civil
boolean OK=false;
String reponse=null;
while(! OK){
try{
System.out.print("Etes-vous marié(e) (O/N) ? ");
reponse=IN.readLine();
reponse=reponse.trim().toLowerCase();
if (! reponse.equals("o") && !reponse.equals("n"))
System.out.println("Réponse incorrecte. Recommencez");
else OK=true;
} catch(Exception e){
erreur("Lecture état marital",e,2);
}
}
boolean Marie = reponse.equals("o");
// número de filhos
OK=false;
int NbEnfants=0;
while(! OK){
try{
System.out.print("Nombre d'enfants : ");
reponse=IN.readLine();
try{
NbEnfants=Integer.parseInt(reponse);
if(NbEnfants>=0) OK=true;
else System.err.println("Réponse incorrecte. Recommencez");
} catch(Exception e){
System.err.println("Réponse incorrecte. Recommencez");
}// try
} catch(Exception e){
erreur("Lecture état marital",e,2);
}// try
}// while
// salário
OK=false;
long Salaire=0;
while(! OK){
try{
System.out.print("Salaire annuel : ");
reponse=IN.readLine();
try{
Salaire=Long.parseLong(reponse);
if(Salaire>=0) OK=true;
else System.err.println("Réponse incorrecte. Recommencez");
} catch(Exception e){
System.err.println("Réponse incorrecte. Recommencez");
}// try
} catch(Exception e){
erreur("Lecture Salaire",e,4);
}// try
}// enquanto
// cálculo do número de cotas
double NbParts;
if(Marie) NbParts=(double)NbEnfants/2+2;
else NbParts=(double)NbEnfants/2+1;
if (NbEnfants>=3) NbParts+=0.5;
// renda tributável
double Revenu;
Revenu=0.72*Salaire;
// quociente familiar
double QF;
QF=Revenu/NbParts;
// busca da faixa de imposto correspondente a QF
int i;
int NbTranches=Limites.length;
Limites[NbTranches-1]=QF;
i=0;
while(QF>Limites[i]) i++;
// o imposto
long impots=(long)(i*0.05*Revenu-Coeffn[i]*NbParts);
// exibe-se o resultado
System.out.println("Impôt à payer : " + impots);
}// página inicial
// ------------ erro
private static void erreur(String msg, Exception e, int exitCode){
System.err.println(msg+"("+e+")");
System.exit(exitCode);
}// erro
}// classe
Os resultados obtidos são os seguintes:
C:\Serge\java\impots\1>java impots
Etes-vous marié(e) (O/N) ? o
Nombre d'enfants : 3
Salaire annuel : 200000
Impôt à payer : 16400
C:\Serge\java\impots\1>java impots
Etes-vous marié(e) (O/N) ? n
Nombre d'enfants : 2
Salaire annuel : 200000
Impôt à payer : 33388
C:\Serge\java\impots\1>java impots
Etes-vous marié(e) (O/N) ? w
Réponse incorrecte. Recommencez
Etes-vous marié(e) (O/N) ? q
Réponse incorrecte. Recommencez
Etes-vous marié(e) (O/N) ? o
Nombre d'enfants : q
Réponse incorrecte. Recommencez
Nombre d'enfants : 2
Salaire annuel : q
Réponse incorrecte. Recommencez
Salaire annuel : 1
Impôt à payer : 0