Apostila sobre Java - vqv.com.br ()

Propaganda
Capítulo 1 - Java - Linguagem e Plataforma
1.1. Breve histórico da Linguagem Java
A linguagem Java foi desenvolvida por um grupo de funcionários da Sun no início dos anos 90 para ser utilizado
em pequenos dispositivos eletrônicos inteligentes e não sofreu um grande avanço, de imediato, em virtude de
dificuldades de financiamento para esse setor à época. Já a partir de 1993, com a expansão da Internet, novas
oportunidades apareceram e a Sun investiu pesado nessa área.
A partir de 1995 a Sun anunciou o Java, não apenas como uma nova linguagem de programação, mas como
uma nova plataforma de desenvolvimento, possibilitando a criação de páginas da web com conteúdo interativo e
dinâmico, inicialmente com o uso de Applets com imagens em movimento.
Desde 1996, a linguagem não pára de crescer, produzindo soluções desde pequenos aplicativos corporativos a
controle de servidores www. Atualmente está sendo muito utilizada em celulares, pagers e PADs. Um fato interessante,
já que a linguagem foi inicialmente concebida para ser utilizada em pequenos equipamentos.
1.2. A Linguagem Java
Provavelmente o leitor já deve ter ouvido falar muito em Java, pois as revistas especializadas em informática
estão sempre publicando artigos versando sobre essa linguagem. Pelo sucesso que alcançou no mercado, muitas
empresas têm produzido ferramentas para manipular ou gerar códigos em Java, como foi o caso do Visual J++ da
Microsoft, o que resultou num imediato processo judicial impetrado pela Sun, a criadora e detentora dos direitos da
marca registrada Java.
A principal característica do Java é que os programas criados nessa linguagem podem ser executados
virtualmente em qualquer plataforma. Isso deixa os programadores muito à vontade, pois não precisam se preocupar
com o tipo de máquina em que o software produzido irá rodar. Os programas gerados em Java funcionam como
acessórios (applets) colocados no computador dos usuários da web quando eles acessam um site qualquer, ou seja, o
programa armazenado no servidor é transferido para o computador do usuário e executado localmente nessa máquina.
Outro aspecto interessante é que várias linguagens tiveram de ser aperfeiçoadas para apresentar versões
voltadas para orientação a objetos, o atual padrão de mercado, e Java já nasceu assim, e, exatamente por isso, tem se
destacado entre suas concorrentes.
1.3. As Características da Linguagem Java
•
Orientação a objetos: Java já foi concebida para programação orientada a objetos. Atual padrão de
programação adotado mundialmente.
•
Portabilidade: sendo uma linguagem multiplataforma, Java permite criar programas que sejam executados
em máquinas com diferentes sistemas operacionais sem necessidade de qualquer adaptação.
•
Multithreading: meio que possibilita a utilização simultânea de vários eventos em um mesmo programa, essa
característica permite a criação de servidores multiusuários, onde cada thread cuida da conexão de um
usuário ao servidor e todos os usuários podem estar acessando, ao mesmo tempos, pontos diferentes de
um mesmo programa.
•
Suporte à comunicação: Java fornece uma quantidade expressiva de classes com funcionalidades
específicas, e entre essas classes um conjunto desenvolvido para a implementação de sistemas
multiusuários. Tais classes suportam tecnologias avançadas de comunicação, como protocolos TCP/IP,
HTT/P, FTP e outros.
•
Acesso remoto a banco de dados: essa característica permite o acesso, via web, a bancos de dados em
qualquer ponto do planeta.
1.4. Criação de Programas em Java
Como as demais linguagens de programação, o código pode ser produzido em qualquer editor de texto, sendo
posteriormente, analisado pelo compilador Java, que traduz o código fonte para o Java ByteCodes, um código
independente de plataforma que será interpretado por um Interpretador Java instalado no computador ou pelo browser,
caso o programa esteja sendo utilizado na Internet.
1.5. A Plataforma Java
A maioria das plataformas é formada por um conjunto, o hardware e um sistema operacional que o controla. A
Java é composta apenas pelo hardware, que pode operar sobre outra plataforma qualquer. Por essa característica, a
Sun criou o seguinte slogan para sua plataforma: WORA “write once, run anywhere”, isto é, uma vez escrito, roda em
qualquer lugar.
1.6. Ambiente de Desenvolvimento
Os programas em Java podem ser escritos em qualquer editor de textos e depois deverão ser submetidos ao
Sun Development Kit (SDK), um kit composto por um compilador da linguagem (javac), um interpretador (Java), um
visualizador de applets (appletviewer), bibliotecas de desenvolvimento (packages), um depurador de programas (JDB) e
diversos documentos (javadoc).
1.7. Um Primeiro Contato com Java
Como primeiro contato com a linguagem, será apresentada uma classe Java que escreve uma mensagem
qualquer na tela. Trata-se de um exemplo simples, mas que contém os itens fundamentais para a criação de qualquer
aplicação em Java.
class Primeiro_programa {
public static void main (String args [ ] ) {
System.out.println("Este é meu primeiro contato com Java");
}
}
Todo programa Java começa com a palavra reservada class seguida pelo nome da classe, por convenção,
iniciado por uma letra maiúscula e contém um par de chaves envolvendo todo o código da classe.
As classes podem ser compostas por vários métodos (em outras linguagens chamados por sub-rotinas,
procedures ou funções), os quais pode conter outros métodos ou outras estruturas de programa.
Toda classe executável deve possuir o método main. No exemplo, o método main contém uma única instrução,
o comando System.out.println, que não é exatamente um comando, mas uma classe da linguagem que permite a
saída de dados na tela.
A linha do método principal possui o seguinte formato: public static void main (String args [ ] ), e praticamente
todas as aplicações deverão conter esta linha. A seguir são feitas considerações sobre cada palavra reservada dessa
linha.
public - é o qualificador do método, e indica que ele é acessível externamente por outras classes;
static - é um outro qualificador, que, por sua vez, indica que o método deve ser compartilhado por todos os objetos que são
criados a partir desta classe;
void - é o valor de retorno do método. Quando o método não retorna valor, ele é chamado void, uma espécie de valor vazio,
que deve ser especificado;
main - é o nome do método que indica ao compilador o início do programa, Este é o método principal, onde todas as
variáveis, argumentos e instruções são interpretados e processados para a execução do programa;
(String args [ ] ) - é o argumento do método principal e conseqüentemente do programa todo; ele é um vetor de strings
formado por todos os argumentos passados ao programa na linha de comando do sistema operacional quando o programa é
invocado; e
{ ......... } - estas chaves delimitam o bloco das instruções que integram o método, correspondem ao BEGIN e END da
linguagem Pascal.
Capítulo 2 - Aspectos Fundamentais sobre Java
Neste capítulo serão apresentadas as principais características da linguagem Java relacionadas com o tipo de
dados e operações.
2.1. Tipos de Dados
A linguagem Java oferece diversos tipos de dados com os quais podemos trabalhar. Esta seção abordará os
tipos de dados mais importantes, que podem ser divididos em duas categorias: tipos primitivos e tipos de referências.
Os tipos primitivos correspondem aos dados mais simples ou escalares e serão abordados em detalhe a seguir, os
tipos de referências consistem em arrays (vetores), classes e interfaces. Estes serão vistos mais adiante.
A tabela a seguir mostra um resumo dos tipos de dados primitivos em Java:
Tipo
boolean
Descrição
Pode assumir o valor true ou o valor false
char
Caractere em notação Unicode de 16 bits. Serve para a armazenagem de dados alfanuméricos.
Também pode ser usado como um dado inteiro com valores na faixa entre 0 e 65535.
byte
Inteiro de 8 bits em notação de complemento de dois. Assume valores entre -27 e 27-1 (-127 a 128).
short
Inteiro de 16 bits em notação de complemento de dois. Os valores possíveis cobrem a faixa de -2-15 a
215-1 ( -32.768 a 32.767 )
int
Inteiro de 32 bits em notação de complemento de dois. Pode assumir valores entre -231 e 231-1
(2.147.483.648 a 2.147.483.647).
long
Inteiro de 64 bits em notação de complemento de dois. Pode assumir valores entre -263 e 263-1.
float
double
Representa números em notação de ponto flutuante normalizada em precisão simples de 32 bits em
conformidade com a norma IEEE 754-1985. O menor valor positivo representável por esse tipo é
1.40239846e-46 e o maior é 3.40282347e+38.
Representa números em notação de ponto flutuante normalizada em precisão dupla de 64 bits em
conformidade com a norma IEEE 754-1985. O menor valor positivo representável é
4.94065645841246544e-324 e o maior é 1.7976931348623157e+308.
Ao contrário do que acontece com outras linguagens de programação, as características dos tipos de dados
listados acima independem da plataforma em que o programa deverá ser executado. Dessa forma, os tipos de dados
primitivos são realmente únicos e garantem que um programa seja multiplataforma (do ponto de vista de tipos de dados
primitivos).
2.1.1. Tipo Boolean
Uma variável booleana pode assumir apenas um entre dois valores: true ou false. Algumas operações
possíveis em Java como a <= b, x > y, entre outras têm como resultado um valor booleano, que pode ser
armazenado para uso futuro em variáveis booleanas. Estas operações são chamadas operações lógicas. As variáveis
booleanas são tipicamente empregadas para sinalizar alguma condição ou a ocorrência de algum evento em um
programa Java. Por exemplo:
boolean fim_do_arquivo = false;
é a declaração de uma variável do tipo boolean, cujo nome é fim_do_arquivo. O valor false à direita do
operador "=" indica que a variável recebe esse valor como valor inicial. Sem essa especificação, o valor de uma variável
fica indeterminado, podendo ser qualquer um dos valores possíveis para seu tipo (neste caso true ou false).
Na declaração acima, também podemos observar a forma de se declarar e inicializar variáveis em Java:
1.informar o tipo de dado que deseja declarar (boolean);
2.informar o nome que será usado para batizar a variável (fim_do_arquivo);
3.atribuir à variável um valor inicial (= false); e
4.terminar a declaração com um ponto-e-vírgula ";".
Na declaração acima foi usado o nome fim_do_arquivo para designar a variável. Um nome de variável, assim
como o nome de um método, classe, rótulo ou dezenas de outros itens lexicográficos, constitui o que é chamado de
identificador. Uma vez criado, um identificador representa sempre o mesmo objeto a ele associado, em qualquer
contexto em que seja empregado.
As seguintes regras regem a criação de identificadores:
•
o primeiro caractere de um identificador deve ser uma letra. Os demais caracteres podem ser quaisquer
seqüências de numerais e letras;
•
não apenas os numerais e letras latinas podem ser empregadas, como também letras de qualquer outro
alfabeto;
•
por razões históricas, o underscore "_" e o sinal de dólar "$" são considerados letras e podem ser usados
nos identificadores ;
•
assim como nas linguagens C e C++, os identificadores distinguem o tipo de caixa das letras, isto é, as
maiúsculas são consideradas distintas das minúsculas. Isso significa que fimDeArquivo é um identificador
diferente de FimDeArquivo ;
•
Os identificadores não podem ser palavras reservadas, tais como: class, for, while, public e outras.
2.1.2. Tipos de dados inteiros
Os tipos de dados primitivos byte, int, char, short e long constituem tipos de dados inteiros. Isso porque
variáveis desses tipos podem conter um valor numérico inteiro dentro da faixa estabelecida para cada tipo individual.
Por exemplo: um byte pode conter um inteiro entre -128 e 127, enquanto um short pode conter um valor entre -32.768
e 32.767. Você deve escolher o tipo inteiro mais adequado às suas necessidades.
Se alguma operação aritmética cria um resultado que excede um dos limites estabelecidos para o tipo inteiro
empregado, não há qualquer indicação de erro para avisar sobre essa ocorrência. Ao invés disso, um complemento de
dois do valor obtido será o resultado. Por exemplo: se a variável for do tipo byte, ocorrem os seguintes resultados:
127+1 = -128, 127+9=-120 e 127+127=-2. Entretanto, uma exceção do tipo ArithmeticException é apresentada caso
ocorra uma divisão por zero.
public class Arith {
public static void main(String args[])
{
byte a = 127;
short b = 32767;
int c = 2147483647;
long d = 9223372036854775807L;
int e = 0;
a += 1;
b += 1;
c += 1;
d += 1;
System.out.println("Valor de a = " + a);
System.out.println("Valor de b = " + b);
System.out.println("Valor de c = " + c);
System.out.println("Valor de d = " + d);
d /= e;
// Vai dar erro porque e = 0
}
}
com seu respectivo resultado de execução:
$java Arith
Valor de a = -128
Valor de b = -32768
Valor de c = -2147483648
Valor de d = -9223372036854775808
java.lang.ArithmeticException: / by zero at Arith.main(Arith.java:18)
Seguem abaixo alguns exemplos de declarações de variáveis de tipo inteiro:
byte Contador = 1;
int AnguloEmGraus = -45;
char indice = 6;
A diferença entre essas declarações e a declaração de dados booleanos no início da seção 2.1.1, está no tipo de
dado especificado e no valor atribuído a cada variável.
Operações com inteiros
Podemos realizar uma série de operações com os dados do tipo inteiro. A tabela seguinte mostra uma lista
completa dessas operações.
Operação
=, +=, -=, *=, /=, %=
==, !=
<, <=, >, >=
+, +, -, *, /, %
+=, -=, *=, /=, %=
++, -<<, >>, >>>
<<=, >>=, >>>=
~
&, |, ^
&=, |=, ^=
Descrição
Operadores de atribuição
Operadores de igualdade e diferença
Operadores de desigualdade
Operadores unários
Adição, subtração, multiplicação, divisão e módulo
Operadores de atribuição com adição, subtração, multiplicação, divisão e módulo
Incremento e decremento
Operadores de deslocamento de bits
Operadores de atribuição com deslocamento de bits
Operador lógico de negação
Operadores lógicos E, OU e OU-exclusivo
Operadores de atribuição com operação lógica E, OU e OU-exclusivo
Muitas das operações que aparecem na lista acima são familiares e praticamente não requerem explicação. Há
outras, porém, que podem ser um tanto quanto ambíguas. É o caso dos operadores de atribuição aritméticos. Por
exemplo: += adiciona um valor ao valor antigo de uma variável e a soma passa a ser o novo valor. Esse padrão
também é obedecido para as operações -=, *=, /= e %=. Temos assim as seguintes correspondências:
x
x
x
z
+=
-=
*=
/=
5
y
2
4
x
x
x
z
=
=
=
=
x
x
x
z
+
*
/
5
y
2
4
Os operadores de incremento e decremento referem-se a apenas uma variável (e por isso são chamados de
unários). Por exemplo, o operador de incremento soma um ao operando conforme o exemplo:
x++;
É uma maneira muito mais concisa de se escrever x = x + 1. Mas não só, esses operadores se comportam de
modo diferente quando seguem ou precedem o nome de uma variável. Se o operador precede o nome da variável,
então o incremento (ou decremento) ocorre antes que o valor da variável seja tomado para a expressão aritmética. No
seguinte exemplo, o valor das variáveis x e y será 6:
int x = 5;
int y = ++x;
Porém, no próximo exemplo o valor de x será 6 enquanto que o valor de y será 5:
int x = 5;
int y = x++;
Vejamos alguns exemplos de declarações e de utilizações de operações envolvendo tipos inteiros:
byte j = 60;
short k = 24;
int
l = 30;
long m = 12L;
long resultado = 0L;
resultado
resultado
resultado
resultado
resultado
resultado
+= j;
+= k;
/= m;
-= l;
= -resultado;
%= m;
//
//
//
//
//
//
resultado
resultado
resultado
resultado
resultado
resultado
=
=
=
=
=
=
60 (0 mais 60)
84 (60 mais 24)
7 (84 dividido por 12)
-23(7 menos 30)
23 ( -(-23) )
11 (resto de 23 div. 12)
2.1.3. Tipo caractere
Uma variável do tipo char armazena um caractere Unicode. Um caractere Unicode é um caractere de 16 bits,
sendo que de 0 a 225 correspondem aos caracteres do código ASCII (a tabela ASCII é uma tabela padronizada
internacionalmente de associações entre caractere e a sua representação numérica no computador). Uma constante do
tipo caractere é representada colocando-se entre apóstrofos, ou pelo valor numérico correspondente na tabela Unicode
(ou ASCII), ou, ainda, pela seqüência '\x' onde x especifica o caractere a ser referido. Esta especificação de seqüência
de escape obedece às mesmas convenções do C/C++. Por exemplo: 'a', 'f', '\n', etc, são constantes do tipo char.
2.1.4. Tipos de ponto flutuante
Em Java, existem duas categorias de variáveis de ponto flutuante: float, que armazena valores numéricos em
ponto flutuante de precisão simples, e double, de precisão dupla. Ambas seguem a norma: IEEE Standard for Binary
Floating Point Arithmetic, ANSI/IEEE Std. 754-1985 (IEEE, New York). O fato de obedecer a essa norma é que torna os
tipos de dados aceitos pela linguagem Java tão portáveis. Esses dados serão aceitos por qualquer plataforma,
independendo do tipo de sistema operacional e do fabricante do computador. A representação dos valores em ponto
flutuante pode ser feita usando a notação decimal (exemplo: -24.321) ou a notação científica (exemplo: 2.52E-31).
Além dos possíveis valores numéricos que uma variável de ponto flutuante pode assumir há também os
seguintes:
•
menos infinito
•
mais infinito
•
zero
•
NAN - not a number
Estes são requeridos pela norma. O mais infinito é usado, por exemplo, ao somarmos 1 ao maior valor
possivelmente representável por esse sistema. Observe que esse comportamento é diferente do comportamento para
números inteiros.
Muitas das operações realizáveis com inteiros (porém não todas) têm análogas para números de ponto flutuante.
Eis um resumo:
Operação
=, +=, -=, *=, /=
==, !=
Descrição
Operadores de atribuição
Operadores de igualdade e diferença
<, <=, >, >=
+, +, -, *, /
+=, -=, *=, /=
++, --
Operadores de desigualdade
Sinais unários
Adição, subtração, multiplicação e divisão
Operadores de atribuição com adição, subtração, multiplicação e divisão
Operadores unários de incremento e decremento
2.2. Vetores e Matrizes
Semelhante às linguagens C, C++ e Pascal, a linguagem Java também dá suporte a vetores e matrizes (arrays)
de diversas formas. Os vetores constituem uma forma muito conveniente de organizar informações em fileira. Por
exemplo, podemos formar um vetor com as notas de cinco alunos de uma sala de aula do seguinte modo:
float nota[] = { 7.8, 8.4, 4.2, 1.8, 6.4 };
Neste caso nota[0] é a nota do primeiro aluno, isto é, 7.8; nota[1] é a nota do segundo, ou seja, 8.4; nota[2] é a
nota do terceiro; e assim por diante.
A utilização de vetores e matrizes em Java envolve três passos:
1. Declarar o vetor ou matriz. Para isto, basta acrescentar um par de colchetes antes ou depois do nome da
variável. Por exemplo:
int ind[];
double A[][],T[][][];
int []nota;
2. Reservar espaço de memória e definir o tamanho. É preciso definir o tamanho do vetor, isto é, a
quantidade total de elementos que terá de armazenar. Em seguida é necessário reservar espaço de memória
para armazenar os elementos. Isto é feito de maneira simples pelo operador new:
ind = new int[10];
nota = new int[70];
A = new double[10][20];
3. Armazenar elementos no vetor ou matriz. Para armazenar uma informação em um dos elementos de um
vetor ou matriz, é necessário fornecer um índice que indique a posição desse elemento. Por exemplo, para
armazenar um valor na quarta posição do vetor nota, fazemos o seguinte:
nota[3] = 5.2;
Como podemos observar, os índices começam em zero e vão até o número de posições reservadas, menos um.
No vetor nota criado acima, os índices válidos vão de 0 até 69. Caso haja a tentativa de atribuir um valor a um
elemento cujo índice esteja fora desse intervalo, ocorrerá um erro que impedirá a execução do programa.
Existe, porém, um atalho para esses três passos quando desejamos criar um vetor com valores atribuídos de
modo estático. Foi o que fizemos no primeiro exemplo acima, declarando o vetor nota com as notas de cinco alunos.
float nota[] = { 7.8, 8.4, 4.2, 1.8, 6.4 };
Nesse caso, espaço suficiente para as notas de cinco alunos foi reservado e as notas foram guardadas em
respectivas posições do vetor. Eis mais alguns exemplos de vetores e matrizes:
// 12 primeiros termos da seqüência de Fibonacci:
long Fibonacci[] = {1,1,2,3,5,8,13,34,55,89,144};
// Tabela de sen(n * pi / 6), n = 0, 1, 2,...5
float seno[] = {0.0000,0.5000,0.8660,1.0000,0.8660,0.5000};
// Tabela de log(1+n), n = 0, 2...99:
double tlog[] = new double[100];
for(int n=0; n<100; n++) tlog[i] = Math.log(1+n);
// Matriz dos coeficientes
double A[][] = { {1,2,3}, {0,1,3}, {0,0,-1} };
2.3. Comentários
Os comentários em Java podem ser feitos de três formas:
•
comentário por linha: ao utilizar o “//”, toda a parte do código que estiver à direita será considerada como
comentário;
•
comentário por bloco: ao utilizar o “/* ..... */”, toda a parte do código que estiver entre o “/*” e o “*/” será
considerada como comentário; e
•
documentação (Javadoc): ao utilizar o “/** ..... */”, toda a parte do código que estiver entre o “/**” e o “*/” será
considerada como parte da documentação da classe.
2.4. Operadores
A linguagem Java oferece um amplo conjunto de operadores destinados à realização de operações aritméticas,
lógicas e relacionais, podendo formar expressões de qualquer tipo.
2.4.1. Operadores Aritméticos
A tabela a seguir mostra os operadores aritméticos da linguagem Java:
Função
Adição
Subtração
Multiplicação
Divisão
Resto da divisão inteira
Sinal negativo
Sinal positivo
Incremento unário
Decremento unário
Operador
+
*
/
%
+
++
--
Exemplo
X + Y
X – Y
X * Y
X / Y
X % Y
-X
+X
++X ou X++
--X ou X--
2.4.2. Operadores Relacionais
Os operadores relacionais possibilitam comparar valores ou expressões, retornando um resultado lógico
verdadeiro ou falso. A tabela a seguir apresenta os operadores relacionais usados em Java:
Função
Igual
Diferente
Maior que
Maior ou igual a
Menor que
Menor ou igual a
Operador
==
!=
>
>=
<
<=
Exemplo
X == Y
X != Y
X > Y
X >= Y
X < Y
X <= Y
2.4.3. Operadores Lógicos
São operadores que permitem avaliar o resultado lógico de diferentes operações aritméticas em uma expressão.
Os operadores lógicos utilizados em Java são os seguintes:
Função
E lógico ou AND
OU lógico ou OR
Negação ou NOT
2.5. Literais
Operador
&&
||
!
Exemplo
X && Y
X || Y
!X
O valor literal é um valor escrito no código fonte e identificado como sendo de um tipo primitivo.
int x
char u
boolean b
double d
=
=
=
=
1;
’a’;
true;
002.11d;
//
//
//
//
literal
literal
literal
literal
inteiro
char
boolean
double
Há três maneiras de representar literais numéricos inteiros em Java:
•
octal (base 8), representado com um 0 (zero) na frente do valor numérico. Exemplo:
int x = 01;
int x = 0931;
int x = 021;
•
decimal (base 10), representado normalmente. Exemplo:
int x = 1;
int x = 931;
int x = 21;
•
hexadecimal (base 16), representado com um 0x (zero e x) na frente do valor numérico. Exemplo:
int
int
int
int
int
quinze
vinte_e_nove
vinte_e_nove
valor
valor
=
=
=
=
=
0xF;
0x1D;
0x1d;
0xBAFAFA;
0xBaFAfa;
//
//
//
//
//
15 (decimal)
29 (decimal)
29 (decimal)
12253946 (decimal)
12253946 (decimal)
Caracteres também possuem uma representação especial. Todo caractere se encontra entre aspas simples,
porem pode-se atribuir um valor inteiro ao caractere sem precisar de uma conversão explicita. Eis alguns exemplos:
char
char
char
char
char
char
char
char
char
char
char
char
char
char
a
b
c
d
e
f
g
h
i
j
k
l
m
n
=
=
=
=
=
=
=
=
=
=
=
=
=
=
’A’;
’&’;
’\u004D’;
’\n’;
’\t’;
’\r’;
’\b’;
’\f’;
’\\’;
’\’’;
’\”’;
65;
(char) -1;
(char)100000;
//
//
//
//
//
//
//
//
//
//
//
//
//
// letra A
caractere &
letra M (unicode)
salto para próxima linha
Tabulação
Retorno de carro
backspace
avanço de formulário (form feed)
contra-barra
caractere ’ (apóstrofo ou aspas simples)
caractere “ (aspas duplas)
char recebe um valor de um int
fora do intervalo, conversão explícita
fora do intervalo, conversão explícita
2.6. Conversão entre tipos primitivos
Existem duas maneiras de fazer conversões de tipos primitivos:
•
conversão implícita quando o tamanho de uma variável é maior do que o tamanho da variável ou do valor
que lhe está sendo atribuído. Exemplo:
int y = 10;
long x = y;
•
conversão explícita quando o tamanho de uma variável é menor do que o tamanho da variável ou do valor
que lhe está sendo atribuído. Exemplo:
long y = 10L;
int x = (int) y;
O tamanho das variáveis do tipo long (64 bits) é maior do que o das variáveis do tipo int (32 bits), tornando-se,
portanto, necessário indicar uma conversão. Essa indicação é feita colocando-se entre parênteses, o tipo da variável
que irá receber o valor. Se essa informação for omitida, o compilador indicará que existe um erro de compilação (tipos
incompatíveis). Outra forma é usar as constantes de identificação de tipos e fazer uma conversão explícita, como em :
long y = 10L;
2.7. Uso do Teclado para a Entrada de Dados
A linguagem Java possui diversas formas de entrada de dados. No entanto, muitas delas exigem que se faça um
tratamento de exceções (erros). Alguns exemplos que utilizam a entrada de dados com tratamento de erros serão
apresentados nos próximos capítulos. Para este curso, será utilizado o mini aplicativo gráfico que retorna uma String
(seqüência de caracteres). A seguir, um exemplo de uma leitura de dados (não esquecer de acrescentar o import
nos programas).
Exemplo 1:
import javax.swing.JOptionPane;
public class Exercicio_1_1 {
public static void main (String[ ] args) {
int n1, n2, n3, n4, soma;
String s;
s = JOptionPane.showInputDialog(“Digite
n1 = Integer.parseInt(s);
s = JOptionPane.showInputDialog(“Digite
n2 = Integer.parseInt(s);
s = JOptionPane.showInputDialog(“Digite
n3 = Integer.parseInt(s);
s = JOptionPane.showInputDialog(“Digite
n4 = Integer.parseInt(s);
soma = n1 + n2 + n3 + n4;
System.out.println(“A soma é “ + soma);
}
}
o primeiro nr”);
o segundo nr”);
o terceiro nr”);
o quarto nr”);
Exemplo 2:
import javax.swing.JOptionPane;
public class Exercicio_2_1 {
public static void main (String[ ] args) {
double n1, n2, n3, media;
String s;
s = JOptionPane.showInputDialog(“Digite a primeira nota”);
n1 = Integer.parseDouble(s);
s = JOptionPane.showInputDialog(“Digite a segunda nota”);
n2 = Integer.parseDouble(s);
s = JOptionPane.showInputDialog(“Digite a terceira nota”);
n3 = Integer.parseDouble(s);
media = ( n1 + n2 + n3 ) / 3;
System.out.println(“A média é “ + media);
}
}
Capítulo 3 - Comandos Condicionais e Estruturas de Controle
Controle de fluxo é a habilidade de ajustar a maneira como um programa realiza suas tarefas. Por meio de
instruções especiais, chamadas comandos, essas tarefas podem ser executadas seletivamente, repetidamente ou
excepcionalmente.
Podemos classificar os comandos aceitos pela linguagem Java em basicamente quatro categorias:
Comando
Tomada de decisões
Laços ou repetições
Apontamento e tratamento de exceções
outros
Palavras-chave
if-else, switch-case
for, while, do-while
try-catch-finally, throw
break, continue, label:, return
3.1 Execução Condicional
A forma mais simples de controle de fluxo é o comando if-else. Ele é empregado para executar seletivamente ou
condicionalmente um outro comando, mediante um critério de seleção. Esse critério é dado por uma expressão, cujo
valor resultante deve ser um dado do tipo booleano, isto é, true ou false. Se esse valor for true, então o comando
seguinte é executado; se for false, a execução do programa salta esse comando e segue adiante. A sintaxe para esse
comando é :
if ([condição])
[comando]
// O comando é executado se a condição for true
Uma variação do comando if-else permite escolher, alternadamente, um entre dois comandos a executar.
Nesse caso, se o valor da expressão condicional que define o critério de seleção for true, então o primeiro dos dois
comandos é executado, senão, será executado o segundo comando.
if([condição])
[comando_1] // Executado se a condição for true
else
[comando_2] // Executado se a condição for false
Por exemplo:
import java.io.StreamTokenizer;
public class sqrt {
public static void main(String args[]) {
double x;
StreamTokenizer inp = new StreamTokenizer(System.in);
// Lê um dado double a partir do teclado
System.out.println("x = "); System.out.flush();
try {
inp.nextToken();
x = inp.nval;
}
catch(java.io.IOException e) {
x = 0;
}
// Decide se é possível calcular a raiz quadrada do
// número dado. Sendo possível, calcula-a. Do contrário
// emite uma mensagem de aviso
if (x >= 0)
System.out.println("raiz quadrada de x e " + sqrt(x));
else
System.out.println("x e negativo");
}
}
Quando mais de um comando deve ser executado, eles devem ser delimitados por chaves { }, e passam a
constituir que se convencionou chamar de blocos de comandos. Para efeitos de programação, um bloco de comandos é
interpretado como se fosse um único comando. Eis alguns exemplos de blocos de comandos:
Exemplo 1:
{
System.out.println("x=");
System.out.println(x);
// comandos em linhas separadas
}
Exemplo 2:
{ temp = y; y = x; x = temp; }
// comandos em uma mesma linha
Desse modo, pode-se fazer também a execução seletiva de blocos de comandos conforme ilustra o seguinte
programa para discutir sobre as raízes de uma equação do segundo grau ax2 + bx + c = 0:
import java.io.StreamTokenizer;
public class Baskhara {
public static void main(String args[]) {
double a, b, c, delta;
StreamTokenizer in = new StreamTokenizer(System.in);
// Requisitando do usuário os dados sobre a equação a ser analisada.
try {
System.out.println("Digite os coeficientes a, b e c, da equação");
System.out.print("a = "); System.out.flush(); in.nextToken();
a = in.nval;
System.out.print("b = "); System.out.flush(); in.nextToken();
b = in.nval;
System.out.print("c = "); System.out.flush(); in.nextToken();
c = in.nval;
}
catch(java.io.IOException e) {
System.out.println("Falha na entrada dos dados.");
a = 0;
}
// Calculando o discriminante da equação
//
delta = b*b - 4*a*c;
System.out.println( "Equação: ("+a+")x^2+("+b+")x+("+c+")" );
// Decidindo sobre o número de raízes da equação mediante o
// valor do discriminante calculado acima
if ( delta > 0 ) {
// A eq. tem duas raízes reais
double r, d, x1, x2;
r = Math.sqrt(delta);
d = 2*a;
x1 = ( -b - r ) / d;
x2 = ( -b + r ) / d;
System.out.println("A equação tem duas soluções reais: ");
System.out.println("
x1 = " + x1);
System.out.println("
x2 = " + x2);
}
else
if ( delta < 0 )
// A eq. não tem raízes reais
System.out.println("A equação não tem raízes reais.");
else {
// A eq. tem uma raiz real dupla
double x;
x = -b / (2*a);
System.out.println("A equação tem uma única raiz real:");
System.out.println("
x1 = x2 = " + x);
}
System.out.println("Fim da discussão.");
}
}
Exemplo 3:
import javax.swing.JOptionPane;
class Baskara {
public static void main (String[ ] args) {
int a, b, c, d;
double r, x, x1, x2;
String s;
System.out.println("Entre com os coeficientes da equação");
s = JOptionPane.showInputDialog("Digite A");
a = Integer.parseInt(s);
s = JOptionPane.showInputDialog("Digite B");
b = Integer.parseInt(s);
s = JOptionPane.showInputDialog("Digite C");
c = Integer.parseInt(s);
// Calculando o discriminante da equação
d = b*b - 4*a*c;
System.out.println( "Equação: "+a+"x2 + "+b+"x + "+c+" = 0" );
// Decidindo sobre o número de raízes da equação mediante o
// valor do discriminante calculado acima
if ( d > 0 ) {
// A eq. tem duas raízes reais
r = Math.sqrt(d);
x1 = ( -b - r ) / (2*a);
x2 = ( -b + r ) / (2*a);
System.out.println("Esta equação tem duas soluções reais: ");
System.out.println("
x1 = " + x1);
System.out.println("
x2 = " + x2);
}
else if ( d < 0 )
// A eq. não tem raízes reais
System.out.println("Esta equação não tem raízes reais.");
else {
// A eq. tem uma raiz real dupla
x = -b / (2*a);
System.out.println("Esta equação tem uma única raiz");
System.out.println("
x1 = x2 = " + x);
}
System.out.println("Fim da discussão.");
}
}
3.1.1 if-then-else compacto
O if-else compacto, também conhecido como operador ternário, não é propriamente um comando, mas um
operador que realiza avaliação seletiva de seus operandos, mediante o valor de uma expressão booleana semelhante à
do comando if-else. Se essa expressão for true, então um primeiro operando é avaliado; se for false então o segundo
operando é avaliado. A sua sintaxe é:
[expressão condicional] ? [expressão 1] : [expressão 2]
onde [expressão condicional] deve resultar em true ou false; e [expressão 1] e [expressão 2] são os operandos, que
podem ser expressões quaisquer. O valor resultante da aplicação do operador if-else compacto é, obviamente, igual ao
valor do operando que tiver sido avaliado. O tipo desse valor obedece às regras de conversão entre tipos de dados
discutida anteriormente.
Considere o seguinte exemplo:
y = x < 1 ? x*x : 2-x;
Esta linha de comando é logicamente equivalente à seguinte seqüência de comandos:
if (x<1) then
y = x*x;
else
y = 2-x;
É importante notar que o if-else compacto é um operador de baixa precedência, logo o uso de parênteses para
separar seus operandos não é necessário (a menos que mais de um desses operadores estejam presentes na mesma
expressão). Porém, há casos em que o uso de parênteses para definir claramente os operandos é essencial. Por
exemplo: y = |x|*sin(x) pode ser codificado como:
y = ( x < 0 ? -x : x ) * Math.sin(x); // aqui os parênteses são essenciais.
Sem os parênteses, x * Math.sin(x) seria visto pelo operador if-else compacto como se fosse um único operando,
devido à alta precedência do operador multiplicação.
3.2. Execução Seletiva de Múltiplos Comandos
Freqüentemente, desejamos que um único comando (ou único bloco de comandos) de uma lista seja executado
mediante um dado critério. Isso pode ser feito por intermédio do aninhamento ou acoplamento de vários comandos ifelse, do seguinte modo:
if ([condição 1])
[comando 1]
else if ([condição 2])
[comandos 2])
else if ([condição 3])
[comando 3]
....
else
[comando n]
A presença do último else, juntamente com seu comando, é opcional. Neste código, o [comando 1] será
executado (e os demais saltados) caso a primeira condição seja true, o [comando 2] será executado (e os demais
saltados) caso a primeira condição seja false e a segunda condição seja true, e assim sucessivamente. O [comando n]
(se houver) somente será executado (e os demais saltados) caso todas as condições sejam false.
Observe o exemplo:
import java.io.StreamTokenizer;
public class sqrt {
public static void main(String args[]) {
double x, y;
StreamTokenizer inp = new StreamTokenizer(System.in);
/* Deseja-se definir y tal que
| x + 2, se x < -1,
y = | 1,
se -1 <= x < 1,
| x * x, se 1 <= x.
*/
try {
System.out.print("x = ");
System.out.flush();
inp.nextToken();
x = inp.nval;
}
catch(java.io.IOException e){
x = 0;
}
if (x<-1)
y = x + 2;
else
if(x <= 0)
y = 1;
else
y = x*x;
System.out.println("y = " + y);
}
}
3.3.Execução Seletiva por Valores
Assim como no caso execução seletiva de múltiplos comandos, há situações em que se sabe de antemão que
as condições assumem o valor true de forma mutuamente exclusiva, isto é, apenas uma entre as condições sendo
testadas assume o valor true num mesmo momento. Nesses casos, a linguagem Java (como também as linguagem C,
C++ e Pascal) provê um comando de controle de fluxo bastante poderoso. Trata-se do comando swich, cuja sintaxe é a
seguinte:
switch([expressão]) {
case [constante 1]: [comando 1]; break;
case [constante 2]: [comando 2]; break;
......
case [constante n]: [comando n]; break;
default: comando];
}
onde [expressão] pode ser qualquer expressão válida com resultado do tipo int ou char. Ela é avaliada e o seu valor
resultante é comparado com as constantes distintas [constante 1], [constante 2], ..., [constante n]. Caso esse valor seja
igual a uma dessas constantes, o respectivo comando é executado (e todos os demais são saltados). O rótulo default: é
opcional, mas se estiver presente, os comandos que o seguem serão executados se nenhuma das constantes dos
rótulos anteriores se igualar ao valor da [expressão]. Por exemplo:
public class test {
public static void main(String args[]) {
int op;
op = 2;
System.out.print("valor de op eh: " + op)
switch(op) {
case 1: System.out.println("case 1: op="
case 2: System.out.println("case 2: op="
case 3: System.out.println("case 3: op="
default: System.out.println("default: op
}
}
}
+ op); break;
+ op); break;
+ op); break;
fora do limite 1..3");
3.4. Laço de iteração enquanto/faça
Em muitos programas, pode-se ter a necessidade de que alguma tarefa seja executada repetidamente enquanto
uma dada condição seja verdadeira. Isso pode ser implementado em Java pela utilização do comando while.
Este comando avalia uma expressão condicional, que deve resultar no valor true ou false. Se o valor for true,
então o comando é executado; se a expressão for false, então o comando é saltado e a execução prossegue adiante. A
diferença entre esta estrutura de controle de fluxo e o if-else, é que após executar o comando subjacente, a expressão
condicional é mais uma vez avaliada e seu resultado novamente considerado. Desse modo, a execução do comando
subjacente se repetirá até que o valor da expressão condicional seja false. Observe, porém, que, como a expressão é
avaliada antes de uma possível execução do comando, existe a possibilidade deste comando jamais ser executado. A
sintaxe do comando while é:
while([condição])
[comando]
Por exemplo:
// Achar a raiz quadrada de 2 pelo método de bissecção
public class sqrt2 {
public static void main(String args[]) {
double a, b, x=1.5, erro = 0.05;
a = 1; b = 2; // 1 < (raiz de 2) < 2
while( (b-a) > erro ) {
x = (a + b) / 2;
if (x*x < 2) // x < raiz de 2
a = x;
else // x >= raiz de 2
b = x;
}
System.out.println("Valor aproximado de raiz quadrada de 2: "+x);
}
}
3.5. Laço de iteração faça/enquanto
Outro tipo de laço de repetição, similar ao enquanto/faça, é o laço faça/enquanto. Este é introduzido pelo par de
comandos do - while, conjugados, que tem a seguinte sintaxe:
do
[comando]
while([condição]);
Diferente do laço enquanto/faça, este tipo de laço de repetição executa o comando e em seguida avalia a
expressão condicional. A repetição ocorre se o valor dessa expressão for true. Se esse valor for false, a execução
prossegue adiante do while. Observe o seguinte exemplo:
public class Menu {
public static void main(String args[]) {
char op;
int i = 0;
double x = 0;
do {
System.out.println("\nOpcoes:");
System.out.println("p - Atribuir: x = 0.5, i = 2");
System.out.println("n - Atribuir: x = -0.2, i = -1");
System.out.println("x - ver o valor de x");
System.out.println("i - ver o valor de i");
System.out.println("f - fim");
System.out.print("Sua escolha: "); System.out.flush();
try {
op =(char)System.in.read();
System.in.read(); // Para pegar o 'enter'
}
catch(java.io.IOException e) {
op = 'q';
}
switch(op) {
case 'p': x = 0.5; i = 2; break;
case 'n': x = -0.2; i = -1; break;
case 'x': System.out.println("\n--> x = " + x); break;
case 'i': System.out.println("\n--> i = " + i); break;
case 'f': break;
default : System.out.println("\n--> Opção invalida");
}
} while(op != 'f');
System.out.println("\nAté logo.");
}
}
3.6. Laço de iteração com contagem
Em certas situações, são necessários de laços de repetições nos quais alguma variável seja usada para contar o
número de iterações. Para essa finalidade, usa-se o laço for. Esse tipo de estrutura de controle de laço é o mais versátil
disponível na linguagem Java. Sua sintaxe é a seguinte:
for ([expressão 1]; [condição]; [expressão 2])
[comando]
onde : [expressão 1] é chamada expressão de inicialização,;
[condição] é uma expressão condicional; e
[expressão 2] é uma expressão qualquer a ser executado no final de cada iteração.
O laço for acima é equivalente a:
[expressão 1]
while ([condição]) {
[comando]
[expressão 2]
}
Isto que dizer que o laço for executa inicialmente a expressão de inicialização; em seguida, avalia a expressão
condicional; e, se o valor desta for true, então executa o comando e a segunda expressão, e, novamente, avalia a
expressão condicional. Do contrário, se o valor da expressão for false, a execução prossegue adiante do laço for. Este
arranjo é muito conveniente para controlar variáveis de contagem, conforme ilustra o seguinte exemplo:
for (i = 0; i <= n; i++)
System.out.println("V["+i+"]="+v[i]);
Este código imprime os valores de cada elemento v[i] de um vetor v, para i variando de 0 até n. O operador ++
foi utilizado na ultima expressão do laço for para somar um ao valor da variável de contagem. Caso fosse necessário
um incremento (ou decremento) maior do que um, poder-se-ia usar os operadores += ou -=. Por exemplo, para imprimir
todos os números pares entre de 0 até 10, o programa poderia ser codificado da seguinte maneira:
for(i = 0; i <= 10; i += 2)
System.out.println(" " + i);
Tanto a [expressão 1] quanto a [expressão 2] do laço for permitem acomodar múltiplas expressões, bastando
separá-las por vírgula. Por exemplo, a soma de {1/n} n = 1, 2, .., N pode ser obtida por:
for (soma = 0, n = 1; n <= N; n++)
soma += 1/n;
ou ainda por
for(soma = 0, n = 1; n <= N; soma += 1/n, n++);
3.7. break e continue
O comando break é usado para interromper a execução de um dos laços de iteração vistos acima ou de um
comando switch. Este comando é comumente utilizado para produzir a parada de um laço mediante a ocorrência de
alguma condição específica, antes da chegada do final natural do laço.
Exemplo:
// Achar i tal que v[i] é negativo
for(i = 0; i < n; i++)
if( v[i] <0) break;
if(i == n)
System.out.println("elemento negativo não encontrado.");
E se isto se der dentro de um laço duplo? Nesse caso, o comando break provocará a interrupção apenas do laço
em que o comando é imediatamente subjacente. Os outros laços continuam normalmente.
Exemplo:
// Notificando a existência de elemento nulo em cada linha do matriz A
for(i = 0; i <m; i++)
// Para cada linha i da matriz faça
for(j = 0; j <n; j++) // Para cada coluna j da matriz faça
if(A[i][j] == 0) {
System.out.println("A possui elemento nulo na linha "+i);
break;
}
O comando continue tem a função de ignorar os comandos restantes do laço, saltando direto para seu final, e
submetendo-o a uma nova avaliação de sua condição de repetição. O exemplo a seguir explora os dois comandos,
break e continue:
/* este programa calcula a média da nota dos alunos de uma sala de aula e
se encerra quando for digitada uma nota negativa */
/ Notificando a existência de elemento nulo em cada linha do matriz A
import javax.swing.JOptionPane;
class Media {
public static void main (String[ ] args) {
double nota, media = 0;
int aluno = 1;
System.out.println("Digite notas válidas ou nr < 0 para sair");
While ( 1 ) { // sempre verdadeiro
String s;
System.out.println("Aluno " + aluno);
s = JOptionPane.showInputDialog("Digite a nota ");
nota = Integer.parseDouble(s);
if (nota < 0 ) break; // sai do laço while
if (nota > 10) {
System.out.println("Nota inválida, digite novamente");
continue;
// desconsidera os próximos comandos
}
media += nota;
aluno++;
}
System.out.println( "A média da turma foi:"+ media / --aluno);
}
}
Capítulo 4 - Operações com strings e operações matemáticas
4.1. A classe String
Para muitas linguagens existe um tipo primitivo de dados para representar uma cadeia de caracteres. Em Java,
a cadeia de caracteres é representada por uma classe denominada String. Neste momento, ainda não será
apresentado um conceito formal da definição de classe, no entanto, alguns aspectos relevantes merecem ser
apontados para possibilitar a utilização da classe String nos programas.
4.1.1. Declaração e inicialização
Para se criar variáveis (objetos) do tipo String (da classe String) utiliza-se a mesma sintaxe para a criação de
variáveis dos tipos primitivos:
String s = "Linguagem Java";
String nome;
4.1.2. Referências
Variáveis do tipo String (o nome correto seria Objetos da classe String), como qualquer outro objeto em Java,
são acessadas por referência. Isso significa dizer que ela armazena o endereço físico de memória destinado a guardar
o valor da variável. Assim, quando houver dois objetos P1 e P2 da classe Pessoa e for executado o comando P1= P2,
desse ponto em diante, os dois identificadores passam a indicar o mesmo endereço de memória, e, nesse caso, P1 e
P2 serão considerados o mesmo objeto. Todas as modificações realizadas em P1 terão reflexos em P2 e vice-versa. A
classe String é a exceção dessa regra, pois os objetos String são inalteráveis. Para fixar esse entendimento, observe os
exemplos:
String s1 = "123";
String s2 = s1;
s1 = "abc";
A String s1 foi criada como "123" e modificada para "abc". Como esses objetos são acessados por referência, e
s2 = s1, era de se esperar que a alteração de s1 modificasse também o objeto s2, mas nada disso ocorre. s1 fica com o
valor "abc" e s2 com "123".
A explicação para isso é que, ao fazer s1 = "abc", o Java criou um NOVO objeto e, por isso, o valor de s2 não foi
alterado, pois s2 mantém a referência ao endereço inicialmente indicado por s1. A variável (objeto) s1 agora se
referencia a um novo objeto, cujo conteúdo é "abc".
Assim, se uma nova String for criada e não for atribuída a nenhuma variável de referência, ela ficará perdida mas
continuará ocupando espaço de memória. Veja mais um exemplo:
String s1 = "abc";
String s2 = "abcd" + "e";
O código anterior criará, no pool, quatro Strings ("abc", "abcd", "e" e "abcde"), das quais, duas serão perdidas (
"abcd" e "e"). Outro exemplo:
String s1 = "ricardo";
s1 = "santana";
O que este código acabou de fazer, foi: criar a String "'ricardo" no pool e referenciá-la por s1. Depois, criou uma
nova String ("santana") e a referenciou pela mesma variável s1. Assim, a string "ricardo" ficou perdida no pool (mas não
saiu da memória).
4.1.3. O método substring
O método substring recebe dois argumentos do tipo inteiro, onde define a posição inicial e a posição final da
string e retorna uma String (sem alterar a original). Observe os exemplos seguir:
Exemplo 1:
"abcdefghijklmnop".substring(0,3);
// resulta em: abc
Observe que a posição inicial (0) é a letra "a" e que a posição final (3) é a letra "d" e substring(0,3) retornou
"abc".
Exemplo 2:
public class TestaString {
public static main(String[ ] args) {
String s = "ricardo santana";
System.out.println(s.substring(8,13);
}
}
Saída na tela: "santa"
4.1.4. Métodos da String
A seguir são apresentados alguns métodos interessantes da classe String que poderão ser úteis no
desenvolvimento de programas futuros.
•
concat - Adiciona uma string a outra, porém não altera a string em que o método está sendo executado.
Exemplo:
public class TestaString {
public static main(String[ ] args) {
String s = "teste ";
System.out.println(s.concat("não mudou"));
System.out.println(s);
}
}
Saídas na tela:
teste não mudou
teste
Note que nenhuma alteração foi efetuada na string s. Se fosse o caso de alterá-la, o código poderia ser o
seguinte:
String s = "teste ";
s = s.concat("não mudou");
System.out.println(s); // resultado: teste não mudou
•
equalsIgnoreCase - Testa se uma string é igual a outra, ignorando a diferença entre maiúsculas e
minúsculas.
Exemplo:
String s1 = "teste";
String s2 = "TESTE";
System.out.println(s1.equals(s2)); // resultado: false
System.out.println(s1.equalsIgnoreCase(s2)); // resultado: true
•
length - Obtém o tamanho da string.
Exemplo:
String nome = "testa de ferro";
System.out.println(nome.length() );
•
// resultado: 15
replace - Substitui os caracteres de uma string.
Exemplo:
String texto = "Est4mos 4qui p4r4 test4r";
texto = texto.replace('4','a');
System.out.println(texto); // resultado: Estamos aqui para testar
•
substring - Extrai uma string de outra.
Exemplo:
String texto = "carambola";
System.out.println(texto.substring(2,7);
•
toLowerCase - Muda todas as letras que estiverem maiúsculas para letras minúsculas (mas não altera o
conteúdo da string original).
Exemplo:
String s = "AKJDJE";
System.out.println(s.toLowerCase() );
System.out.println(s);
•
// resultado: akjdje
// resultado: AKJDJE
toUpperCase - Transforma em maiúsculas todas as letras que estiverem minúsculas.
Exemplo:
String s = "teste de caixa alta";
s = s.toUpperCase();
System.out.println(s);
•
// resultado: rambo
trim - Retira os espaços das extremidades de uma string.
Exemplo:
String s = " tem um ";
s = s.trim();
// TESTE DE CAIXA ALTA
System.out.println("["+ s +"]");
•
// resultado: [tem um]
equals - Compara o valor de uma string com o de outra, informada como argumento. Para se comparar
duas strings de forma correta, assim como para comparar dois objetos, utiliza-se o método equals e não o
operador ==, pois, como os objetos são acessados por referência, o operador == compararia o valor do
endereço físico de memória dessas variáveis variável (objeto) e não o conteúdo delas. Somente quando
dois objetos se referem ao mesmo endereço de memória é que o == retorna true. Observe atentamente o
exemplo a seguir:
Exemplo:
String s1 = "texto";
String s2 = "texto";
System.out.println(s1 == s2);
System.out.println(s1.equals(s2));
s1 = new String ("texto");
s2 = new String ("texto");
System.out.println(s1 == s2);
System.out.println(s1.equals(s2));
// resultado 1: true
// resultado 2: true
// resultado 3: false
// resultado 4: true
4.2. A classe StrinBuffer
A classe StringBuffer é uma alternativa a ser utilizada nos casos em que o uso da classe String se torna inviável
(seja por consumir memória ou por outra razão). Essa classe difere da String por ser passível de sofrer alteração.
Exemplo:
StringBuffer sb = new StringBuffer("testando";
Sb.append(" se mudou");
System.out.println(sb);
// resultado: testando se mudou
4.2.1. Métodos importantes da classe StrinBuffer
•
append - esse método adiciona o conteúdo de uma string ao StringBuffer.
Exemplo:
StringBuffer sb = new StringBuffer("abc");
sb = sb.uppend("def");
System.out.println(sb);
// resultado: abcdef
•
insert - insere uma string no StringBuffer a partir de uma determinada posição.
Exemplo:
StringBuffer sb = new StringBuffer("calla");
sb = sb.insert(2,"rambo");
System.out.println(sb);
// resultado: carambola
sb = sb.insert(22,"-amarga");
System.out.println(sb);
// resultado: carambola-amarga
Como se pôde observar, no caso do número passado como argumento ultrapassar o tamanho da string, a
inserção se dará imediatamente depois da última posição da String.
•
reverse - inverte todos os caracteres do StringBuffer.
Exemplo:
StringBuffer sb = new StringBuffer("lamina");
sb.reverse();
System.out.println(sb);
// resultado: animal
•
equals - O método equals da classe StringBuffer não é substituído, isso significa que ele não compara
valores, portanto, uma questão com essa consideração pode confundir, observe:
Exemplo:
StringBuffer sb1 = new StringBuffer("animal");
StringBuffer sb2 = new StringBuffer("animal");
System.out.println(sb1.equals(sb2));
// resultado 2: false
Apesar de conterem o mesmo valor, o resultado será false, pois é comparado se as variáveis referenciam o
mesmo objeto na memória, e como na memória existem dois objetos distintos, o resultado é false.
4.2.2. Encadeamento de métodos
Essa característica da linguagem Java, muito explorada na programação orientada a objeto, também pode ser
utilizada no desenvolvimento de programas estruturados. Trata-se de aninhar métodos, isto é, um método pode chamar
um segundo método, que por sua vez pode chamar a um outro. Veja o exemplo:
StringBuffer sb = new StringBuffer("zoref");
System.out.println(sb.insert(sb.length()," lamina").reverse().toString());
O resultado dessas linhas de código será o seguinte:
Animal feroz
Pode-se observar o aninhamento dos métodos: insert, reverse e toString. O sb.insert(....) é um StringBuffer e,
portanto, possui o método reverse(), que, por sua vez, tem como resultado um StringBuffer, o qual possui o método
toString. Os métodos foram executados da ESQUERDA para a DIREITA, exatamente como se lê, ou seja, o primeiro
método a ser executado foi o insert, alterando o objeto sb, mudando o StringBuffer para "zoref lamina"; depois, a string
foi invertida para "animal feroz" e, por fim, o método to String.
4.3. Usando a classe Java.lang.Math
Os desenvolvedores da linguagem Java criaram a classe Math, com vários métodos (funções) para uso em
expressões matemáticas. Por se tratar de uma classe estática, seus métodos podem ser acessados diretamente. O
abs, por exemplo, é um método usado para retornar o valor absoluto de um argumento. Veja suas assinaturas:
public
public
public
public
static
static
static
static
int abs(int value)
long abs (long value)
float abs (float value)
double abs (double value)
Esses métodos podem aceitar diversas possibilidades de entrada e saída, ou seja, ele é um método sobreposto.
A seguir, são apresentados três exemplos do uso do abs:
System.out.println("Valor absoluto de "+Math.abs(-25));
System.out.println("Valor absoluto de "+Math.abs(-2342L))
System.out.println("Valor absoluto de "+Math.abs(-5.5F))
// 25
// 2342
// 5.5
O método abs possui duas exceções: o cálculo do abs do limite mínimo para inteiros e long. Por exemplo,
considerando Integer.MIN_VALUE igual a -2147483648 e Long.MIN_VALUE igual a -922337236854775808:
System.out.println("Valor absoluto de "+Math.abs(-2147483648));
// -2147483648
System.out.println("Valor absoluto de "+Math.abs(-922337236854775808));
// -922337236854775808
Quando esses valores forem apresentados como argumento, o método não retornará o valor absoluto.
Outros métodos da classe Math:
•
ceil - Elimina a parte fracionária de um número de tipo flutuante, mantendo o seu tipo, e incrementa uma
unidade (arredonda para cima).
Exemplo:
public static float ceil(float value)
public static double ceil(double value)
System.out.println(Math.ceil(3.8));
// Resultado: 4.0
System.out.println(Math.ceil(-3.3));
// Resultado: -3.0
•
floor - Elimina a parte fracionária de um número de tipo flutuante, mantendo o seu tipo (arredonda para
baixo).
Exemplo:
public static float ceil(float value)
public static double ceil(double value)
System.out.println(Math.floor(-10.9));
System.out.println(Math.floor(12.2));
•
// Resultado: -11.0
// Resultado: 12.0
max - Retorna o maior entre dois argumentos informados como entrada.
Exemplos de assinaturas:
public static int max(int a, int b)
public static long max(long a, long b))
public static float max(float a, float b))
public static double max(double a, double b))
Atenção. Não existe assinatura para os tipos byte e short, pois esses tipos não podem, implicitamente, ser
convertidos para int.
Exemplos:
System.out.println("o
// Resultado: o maior
System.out.println("o
// Resultado: o maior
maior
entre
maior
entre
entre -8 e -9 é "+Math.max(-8,-9));
-8 e -9 é -8
entre -8 e -9 é "+Math.max(-8.0,9));
-8 e 9 é 9.0
Neste último exemplo, apesar de não existir uma assinatura (double,int), o valor 9 é convertido implicitamente
para double, por isso é que foi apresentado o resultado 9.0 (double) e não 9 (int).
•
min - Retorna o menor entre dois argumentos informados como entrada.
Exemplos de assinaturas:
public static int min(int a, int b)
public static long min(long a, long b))
public static float min(float a, float b))
public static double min(double a, double b))
Atenção. Não existe assinatura para os tipos byte e short, pois esses tipos não podem ser convertidos para int.
Exemplos:
System.out.println("o menor entre -8 e -9 é "+Math.max(-8,-9));
// Resultado: o menor entre -8 e -9 é -9
System.out.println("o menor entre -8 e -9 é "+Math.max(-8.0,9));
// Resultado: o menor entre -8 e 9 é 8.0
Neste último exemplo, apesar de não existir uma assinatura (double,int), o valor 8 é convertido implicitamente
para double, por isso é que foi apresentado o resultado 8.0 (double) e não 8 (int).
•
round - Arredonda um número de ponto flutuante recebido como argumento.
Exemplos de assinaturas:
public static int round(float a)
public static long round(double a)
Observe que esse método deve receber um valor de tipo flutuante (float ou
arredondado e convertido para um tipo inteiro (int ou long).
Exemplo:
Class teste {
Public static void main(String args[ ]) {
System.out.println(Math.round(9.4));
//
System.out.println(Math.round(9.5));
//
System.out.println(Math.round(9.9));
//
System.out.println(Math.round(-9.9));
//
}
}
•
•
double) e retornar esse valor
resultado:
9
resultado: 10
resultado: 10
resultado: -10
random - O método Math.random retorna um número double maior ou igual a 0.0 e menor do que 1.0,
escolhido aleatoriamente.
Exemplo:
System.out.println(Math.random());
// resultado: um número nr qualquer, tal que 0.0 <= nr < 1.0
sqrt - Retorna a raiz quadrada de um número. Sua assinatura é: public static double sqrt(double a)
Exemplo:
System.out.println(Math.sqrt(49));
Se o número passado como argumento for negativo, o retorno será NaN.
// resultado: 7.0
Observações importantes da classe Math:
double x;
float p_i = Float.POSITIVE_INFINITY;
double n_i = Double.POSITIVE_INFINITY;
double n_a_n = Double.NaN;
if (n_a_n != n_a_n ) System.out.println("NaN é diferente de NaN");
// resultado: NaN não é igual a nada, nem mesmo a outro NaN
if(Double.isNaN(n_a_n)) System.out.println("é um NaN");
// resultado: é um NaN
x = Math.sqrt(n_i); // alerta geral! Será atribuído um NaN para x
if(Double.isNaN(x)) System.out.println("x é um NaN");
// resultado: x é um NaN
System.out.println( 32 / 0 );
// resultado: Java.lang.ArithmeticException
System.out.println( 32.0 / 0.0 );
// resultado Infinity
System.out.println( 32.0 / 0.0 );
// resultado Infinity
System.out.println( 32.0 / -0.0 );
// resultado -Infinity
System.out.println( -32.0 / 0.0 );
// resultado -Infinity
System.out.println( -32.0 / -0.0 );
// resultado Infinity
System.out.println( 32.0 / 0 );
// resultado Infinity
System.out.println( -32.0 / 0 );
// resultado -Infinity
System.out.println( -32.0 / -0 );
// resultado -Infinity
Entendendo como o Java trata a divisão por 0 (zero)
•
Quando o divisor e o dividendo forem números inteiros, se o divisor for zero, será lançada uma exceção
(erro)
System.out.println( 32 / 0 );
// exceção
System.out.println( 32 / -0 );
// exceção
•
Quando a expressão envolver pelo menos um número de ponto flutuante, se o divisor for 0 (zero inteiro),
nunca haverá a troca de sinais, sempre será mantido o sinal do dividendo e, se o divisor 0.0 (float) sempre
haverá a troca de sinais.
System.out.println( 32.0 / 0 );
// resultado Infinity
System.out.println( -32.0 / 0 );
// resultado -Infinity
System.out.println( 32.0 / 0.0 );
// resultado Infinity
System.out.println( 32.0 / 0.0 );
// resultado Infinity
System.out.println( 32.0 / -0.0 );
// resultado -Infinity
System.out.println( -32.0 / 0.0 );
// resultado -Infinity
System.out.println( -32.0 / -0.0 );
// resultado Infinity
4.3. Usando as classes Wrappers
As classes wrappers têm o papel de encapsular os tipos primitivos para permitir a possibilidade de operações
como: conversões, mudança de bases decimais e algumas operações somente permitidas a objetos. Por exemplo,
trabalhar com coleções (Listas encadeadas e pilhas, entre outros).
Todo tipo primitivo tem uma classe wrapper correspondente. Veja:
Tipo primitivo
byte
short
integer
long
character
Classe wrapper
Byte
Short
Integer
Long
Character
float
double
boolean
Float
Double
Boolean
Para se cria um objeto pode-se fazer o seguinte:
Integer a = new Integer ("10");
Integer b = new Integer (10);
Note que as classes têm os construtores sobrecarregados, ou seja, aceitam o Valor String e o valor int.
Veja outro exemplo:
Float f1 = new Float ("10");
Float b = new Float (10);
Boolean b1 = new Boolean("TRUE")
Boolean b2 = new Boolean("true");
No caso da classe Boolean, pode-se instanciar um objeto passando uma String TRUE ou FALSE,
independentemente de elas estarem escritas com maiúsculas ou minúsculas.
4.4.1. O método valueOf( )
É um método estático encontrado em quase dotas as classes wrappers, o qual retorna o objeto wrapper à classe
relacionada. Esse método tem uma funcionalidade muito interessante, pois pode converter números em bases
diferentes. Observe:
Integer i1 = Integer.valueOf("89");
Essa linha de comando retorna um Integer na base decimal.
4.4.2. O método ...... value( )
Esse método tem a seguinte assinatura:
Public int intValue( )
Public byte byteValue( )
Public short shortValue( )
Public long longValue( )
Public float floatValue( )
Public double doubleValue( )
Esses métodos não são estáticos. Eles têm a função de realizar conversões dentro das classes wrapper:
Public class TestWrappers {
Public static void main(String Args[ ]) {
Float w = Float.valueOf("89");
int i = w.intValue();
System.out.println(w.toString());
System.out.println(i);
}
}
Esse programa faz uma conversão do valor armazenado pelo objeto w e o converte para o tipo primitivo int. Esse
processo poderia ser para conversão de qualquer outro tipo primitivo de variáveis. Veja os demais exemplos:
byte b = w.byteValue();
short s = w.shortValue();
4.4.2. O método estático parse...( )
Outra forma de se converter é usando-se o método parse’s. Note:
int i = Integer.parseInt("12");
A string passada como parâmetro deve corresponder ao tipo primitivo int, senão, uma exceção será lançada,
como se pode ver no seguinte exemplo:
int i = Integer.parseInt("12f");
Nesse caso, será lançada a exceção: Java.lang.NumberFormatException. Da mesma forma, existem o
Double.parseDouble( ) e o Float.parseFloat( ), entre outros.
4.4.3. O método toString
Esse método é utilizado para converter objetos wrapper para string. Sendo int i = 10, a sua conversão para
string poderia ser feita por uma das seguintes formas:
String s = "" + i; ou
String s = new Integer(i).toString(); ou, ainda
String s = Interger.toString(i);
Download