Dentro de uma expressão, é possível usar dois ou mais tipos de dados diferentes, con- tanto que eles sejam compatíveis. Por exemplo, você pode usar short e long dentro de uma expressão porque os dois são tipos numéricos. Quando tipos de dados diferentes são usados em uma expressão, todos são convertidos para o mesmo tipo. Isso é feito com o uso das regras de promoção de tipos de Java.
Primeiro, todos os valores char, byte e short são promovidos a int. Em segui- da, se um operando for long, a expressão inteira será promovida a long. Se um ope- rando for float, a expressão inteira será promovida a float. Se algum dos operandos for double, o resultado será double.
É importante entender que as promoções de tipos só são aplicadas aos valores usados quando uma expressão é avaliada. Por exemplo, se o valor de uma variável
p = false; q = true; System.out.print(p + "\t" + q +"\t"); System.out.print((p&q) + "\t" + (p|q) + "\t"); System.out.println((p^q) + "\t" + (!p)); p = false; q = false; System.out.print(p + "\t" + q +"\t"); System.out.print((p&q) + "\t" + (p|q) + "\t"); System.out.println((p^q) + "\t" + (!p)); } }
Observe os parênteses que delimitam as operações lógicas dentro das instru- ções de exibição. Eles são necessários devido à precedência dos operadores Java. O operador + tem precedência mais alta do que os operadores lógicos. 5. Compile e execute o programa. A tabela a seguir será exibida.
6. Por conta própria, tente modificar o programa para que ele use e exiba uns e zeros em vez de true e false. Isso pode dar um pouco mais de trabalho do que o esperado!
P Q AND OR XOR NOT
true true true true false false
true false false true true false
false true false true true true
byte for promovido a int dentro de uma expressão, fora dela a variável continuará sendo byte. A promoção de tipos só afeta a avaliação de uma expressão.
No entanto, a promoção de tipos pode levar a resultados inesperados. Por exemplo, quando uma operação aritmética envolve dois valores byte, ocorre a seguinte sequência: primeiro, os operandos byte são promovidos a int. Depois ocorre a operação, gerando um resultado int. Logo, o resultado de uma operação que envolve dois valores byte será um int. Isso não era esperado. Considere o programa a seguir:
// O inesperado em uma promoção! class PromDemo {
public static void main(String[] args) { byte b;
int i;
b = 10;
i = b * b; // Certo, não é necessária uma coerção
b = 10;
b = (byte) (b * b); // coerção necessária!!
System.out.println("i and b: " + i + " " + b); }
}
Mesmo parecendo errado, nenhuma coerção é necessária na atribuição de b*b a i, porque b é promovido a int quando a expressão é avaliada. No entanto, quando você tentar atribuir b*b a b, precisará de uma coerção – novamente para byte! Lembre-se disso se receber mensagens de erro inesperadas de incompatibilidade de tipos refe- rentes a expressões que de outra forma estariam perfeitamente corretas.
Situações como essa também ocorrem em operações com chars. Por exemplo, no fragmento a seguir, a coerção novamente para char é necessária devido à promo- ção de ch1 e ch2 a int dentro da expressão:
char ch1 = 'a', ch2 = 'b';
ch1 = (char) (ch1 + ch2);
Sem a coerção, o resultado da soma de ch1 e ch2 seria de tipo int, que não pode ser atribuído a um char.
As coerções não são úteis apenas na conversão entre tipos em uma atribuição. Por exemplo, considere o programa abaixo. Ele usa uma coerção para double a fim de obter um componente fracionário de uma divisão que seria de inteiros.
// Usando uma coerção. class UseCast {
public static void main(String[] args) { int i;
for(i = 0; i < 5; i++) {
Não é necessária a coerção porque o resultado já é elevado a int.
System.out.println(i + " / 3: " + i / 3); System.out.println(i + " / 3 with fractions: " + (double) i / 3); System.out.println();
} } }
A saída do programa é mostrada aqui:
0 / 3: 0 0 / 3 with fractions: 0.0 1 / 3: 0 1 / 3 with fractions: 0.3333333333333333 2 / 3: 0 2 / 3 with fractions: 0.6666666666666666 3 / 3: 1 3 / 3 with fractions: 1.0 4 / 3: 1 4 / 3 with fractions: 1.3333333333333333
Espaçamento e parênteses
Uma expressão em Java pode ter tabulações e espaços para torná-la mais legível. Por exemplo, as duas expressões a seguir são iguais, mas a segunda é mais fácil de ler:
x=10/y*(127/x);
x = 10 / y * (127/x);
Os parênteses aumentam a precedência das operações contidas dentro deles, como na álgebra. O uso de parênteses adicionais não causará erros nem retardará a exe- cução da expressão. É recomendável o seu uso para que a ordem exata da avaliação fique mais clara, tanto para você quanto para as pessoas que precisarem entender seu programa posteriormente. Por exemplo, qual das duas expressões abaixo é mais fácil de ler?
x = y/3-34*temp+127;
EXERCÍCIOS
1. Por que Java especifica rigorosamente o intervalo e o comportamento de seus tipos primitivos?
2. Qual é o tipo de caractere usado em Java e em que ele é diferente do tipo de ca- ractere usado por outras linguagens de programação?
3. Um valor boolean pode ter o valor que você quiser, já que qualquer valor dife- rente de zero é verdadeiro. Verdade ou mentira?
4. Dada esta saída,
One Two Three
usando um único string, mostre a instrução println( ) que a produziu. 5. O que está errado neste fragmento?
for(i = 0; i < 10; i++) { int sum;
sum = sum + i; }
System.out.println("Sum is: " + sum);
6. Explique a diferença entre as formas prefixada e pós-fixada do operador de in- cremento.
7. Mostre como um AND de curto-circuito pode ser usado para impedir um erro de divisão por zero.
8. Em uma expressão, a que tipo são promovidos byte e short? 9. Em geral, quando uma coerção é necessária?
10. Escreva um programa que encontre todos os números primos entre 2 e 100.
11. O uso de parênteses adicionais afeta o desempenho do programa?
12. Um bloco define um escopo?
13. Em algumas linguagens, as variáveis podem conter valores de qualquer tipo. Por
que Java não permite esse comportamento? Isto é, porque Java restringe as variá- veis a conter valores de apenas um tipo, a saber, o tipo declarado para a variável?
14. Crie um programa que atribua o valor 50.000 a uma variável inteira x, atribua
o valor de x*x a uma variável inteira y e então exiba o valor de y. Obteve uma resposta estranha? Se sim, explique por quê.
15. No exemplo BoolDemo, aparece a linha de código a seguir:
System.out.println("10 > 9 is " + (10 > 9));
O que seria exibido (se fosse caso) se os parênteses fossem removidos e a linha contivesse:
System.out.println("10 > 9 is " + 10 > 9);
16. Quais das instruções de atribuição a seguir são válidas em Java? Explique o porquê para cada uma que não for válida.
A. int x = false; B. int x = 3 > 4; C. int x = (3 > 4); D. int x = int y = 3; E. int x = 3.14; F. int x = 3.14L; G. int x = 5,000,000; H. int x = 5_000_000; I. int x = '350'; J. int x = "350"; K. int x = '3'; L. boolean b = (boolean) 5; M. byte b = (byte) 5; N. double d = 1E3.5; O. char c = '\/'; P. char c = '\\'; Q. char c = 3; R. char c = "3";
17. Quais das expressões a seguir são válidas em Java? Se uma expressão não for
válida, explique o porquê. Se for válida, forneça seu valor. Presuma que x é uma variável int de valor 5, y é uma variável double de valor 3.5 e b é uma variável boolean de valor false.
A. (3 + 4 / 5)/3 B. 3 * 4 % 5 / 2 * 6 C. 3 + x++ D. 3 + ++x E. 0/0 F. y/x G. 'a' + 'b' H. 'a' + 'b' + "c" I. "3" + 2 + 1 J. "3" + (2 + 1) K. false < true L. false == true M. 'c' == 99 N. (3+4 > 5) & (4=6) | b O. !((3>4)|(5!=5))&(3<(4*0)) P. !(3>4|5!=5&3<4*0)
18. Suponha que a, b e c sejam variáveis boolean. Encontre um conjunto de valores para a, b e c que façam as expressões (a & b | c) e (!a | !b & c) serem
verdadeiras.
19. Se x é uma variável de tipo int e seu valor é 5, qual será seu valor após a se-
quência de instruções a seguir ser executada?
x += 4; x *= 2; x /= 3; x %= 4;
20. Se x fosse uma variável de tipo boolean e seu valor fosse true, qual seria seu
valor após a sequência de instruções a seguir ser executada?
x |= false; x &= true; x ^= true;
21. Math.random( ) é um método da biblioteca Java que encontra um valor dou-
ble aleatório entre 0 e 1. Por exemplo, a instrução
double x = Math.random();
atribui à variável x um double aleatório entre 0 e 1. Crie um programa que verifique se Math.random( ) funciona bem. Mais precisamente, escreva um programa que chame Math.random( ) 1.000 vezes para criar 1.000 valores, registrando quantos deles são maiores do que 0,5, e então exiba o resultado. Teoricamente seu programa deve exibir um número muito próximo de 500.
22. Escreva um programa que crie três variáveis double aleatórias a, b e c e atribua
a elas valores entre 0 e 1 usando o método Math.random( ) mencionado no exercício anterior. Em seguida, ele deve executar todas as ações a seguir: A. Exibir os três valores.
B. Exibir “All are tiny” se todos os três valores forem menores do que 0,2. C. Exibir “One is tiny” se exatamente um dos três valores for menor do que 0,2.
PRINCIPAIS HABILIDADES E CONCEITOS
䊏 Inserir caracteres a partir do teclado
䊏 Saber a forma completa da instrução if
䊏 Usar a instrução switch
䊏 Saber a forma completa do laço for
䊏 Usar o laço while
䊏 Usar o laço do-while
䊏 Usar break para sair de um laço
䊏 Usar break como uma forma de goto
䊏 Aplicar continue
䊏 Aninhar laços
Neste capítulo, você aprenderá as instruções que controlam o fluxo de execução do programa. As instruções de controle de programa Java podem ser organizadas nas seguintes categorias:
䊏 Instruções de seleção
䊏 Instruções de iteração
䊏 Instruções de salto
As instruções de seleção permitem que o programa selecione diferentes caminhos de execução. As instruções de iteração permitem que uma seção de código seja repetida. As instruções de salto transferem o controle do programa diretamente de um local para outro. As instruções de seleção Java são if e switch; as de iteração são for, while e do-while; e as instruções de salto são break, continue e return. Exceto por return, que será discutida no Capítulo 4, as outras instruções de controle, inclusive as instru- ções if e for sobre as quais você já teve uma pequena introdução, serão examinadas com detalhes aqui.