Devemos ter em atenção a ordem pela qual as operações são avaliadas numa expressão. O produto e a divisão, por exemplo, têm prioridade sobre a soma e a subtração.
Se queremos contrariar as prioridades definidas para as operações no Java, temos que usar parentesis.
Quando numa expressão temos vários operadores associativos com igual precedência (por exemplo, +
e -
e *
, /
e %
), a ordem de avaliação é da esquerda para a direita – por exemplo, 6 + 4 - 3
é equivalente a (6 + 4) - 3
.
Considere o seguinte programa:
xpublic class Expressions3 {
public static void main (String [] args) {
int i = 2;
int j = 6;
double d1 = 3.5;
double d2 = 10;
int expr1 = 5 + j – i / 4;
int expr2 = 5 + (j – i) / 4;
int expr3 = (5 + (j – i)) / 4;
double d3 = j / 4;
double d4 = j / 4.0;
String s1 = "Alcibiades", s2 = "Briolanjo";
String s3 = "Oh " + s1 + ", jah viste o " + s2 + " hoje? ";
}
}
Na quarta instrução temos uma atribuição do valor inteiro 10 a uma variável do tipo double
. Isto é possível – o que o computador faz é uma conversão automática do literal inteiro 10 para double
e a sua atribuição à variável d2
. O contrário não é possível, ou seja, atribuir um valor do tipo double
a uma variável do tipo int
(o que é lógico, se pensarmos bem).
No cálculo da expressão a atribuir à variável expr1
, a primeira operação a ser feita é a divisão de i
(cujo valor é 2) por 4 (que dá 0); repare que a divisão que é feita é a divisão inteira, porque tanto i
como 4 são do tipo int
; a seguir, dado que a soma e a subtração têm a mesma prioridade e as operações são associativas à esquerda, é feita a soma de 5 com j
(que dá 11) e, finalmente, a subtração de 11 e 0 que dá 11.
No cálculo da expressão a atribuir à variável expr2
, porque o uso de parentesis muda as prioridades, a primeira operação a ser feita é a subtração j – i
(que dá 4); a seguir, uma vez que a divisão tem maior prioridade que a soma, é feita a divisão inteira entre 4 e 4 (que dá 1) e, finalmente, a soma de 5 e 1 que dá 6.
No cálculo da expressão a atribuir à variável expr3
, a primeira operação a ser feita é também j – i
(que dá 4) mas de seguida é feita a soma desse valor com 5, o que dá 9. Finalmente, é avaliada a divisão inteira de 9 por 4 que dá 2.
Qual o valor atribuído à variável d3
? 1.5? 1.0? Se respondeu 1.0 acertou! Embora a variável seja do tipo double
, a expressão j / 4
é uma divisão entre dois valores do tipo int
(j
é int
e 4 é um literal do tipo int
), logo a divisão que é feita é a divisão inteira, que resulta no inteiro 1, o qual é de seguida automaticamente convertido para double
e atribuído à variável d3
.
A variável d4
já ficará com o valor 1.5 pois a divisão que é efetuada entre j
e 4.0 já é a divisão real – um dos operandos não é inteiro (4.0 é um literal do tipo double
).
A variável s3
ficará com o valor "Oh Alcibiades, jah viste o Briolanjo hoje?" ; quando a expressão "Oh " + s1 + ", jah viste o " + s2 + " hoje? "
é avaliada, é feita a concatenação de todas as strings nela presentes; s1
e s2
, por serem variáveis, representam o seu conteúdo e é esse conteúdo que vai ser usado na avaliação da expressão.
NOTA: Como já deve ter percebido, uma expressão não é uma instrução! Uma expressão representa um valor que é o resultado da sua avaliação. E esse valor deve ser usado para algum objetivo concreto como, por exemplo, ser atribuído a uma variável ou ser escrito no ecrã. Não faz sentido, então, ter uma expressão sózinha no lugar de uma instrução pois, desse modo, nada é feito com o seu valor, depois de avaliada.
double
para int
O Java converte int
para double
automaticamente sempre que necessário, como já vimos acima, pois não se perde nenhuma informação no processo. Por outro lado, para converter double
para int
é necessário fazer algo com a parte decimal, a qual não é representável num inteiro.
O Java não faz isto automaticamente porque é importante que o programador fique ciente da perda dessa parte decimal e também para que seja ele a decidir o que fazer a essa parte decimal – se arredondar ou se truncar (cortar).
Há várias formas de fazer esta conversão, mas para já vamos só ver a mais simples e direta: usar cast de tipos. A forma de obter o cast de tipos é colocar o nome do tipo alvo da conversão entre parêntesis à frente da expressão que se pretende converter.
A primeira das instruções seguintes declara e inicializa uma variável pi
do tipo double
; a segunda instrução converte o valor da variável pi
para int
truncando a parte decimal e atribui esse valor inteiro à variável k
– a variável k
ficará com o valor 3. O conteúdo da variável pi
não é afetado!
xxxxxxxxxx
double pi = 3.14159;
int k = (int) pi;
double x = (int) pi * 20.3;
Na terceira instrução a variável x
fica com o valor 60.9.
O operador de cast tem maior precedência do que a multiplicação (na verdade, maior do que de todos os operadores binários) e, por isso, se quisermos converter o resultado de uma expressão, temos que aplicar o cast sobre essa expressão entre parêntesis.
Com a instrução double y = (int) (pi * 20.3);
, a variável y
fica com o valor 63.0 – a expressão pi * 20.3
, quando avaliada, tem o valor 63.774277 que, truncado pelo cast, fica 63.0.
String
sJá vimos que o operador +
, quando usado com valores do tipo String
, resulta na concatenação dos seus operandos. Quando este operador é usado com uma String
e um valor de outro tipo, o resultado é uma String
.
O seguinte excerto de programa:
xxxxxxxxxx
int idade = 12;
double altura = 1.79;
String nome = "Maria";
String info1 = "Maria tem 12 anos";
String info2 = "Maria tem " + 12 + " anos";
String info3Parcial = "Maria tem " + idade;
String info3 = info3Parcial + " anos";
String info4 = nome + " tem " + idade + " anos";
String info5 = 12 + " anos tem a Maria";
System.out.println(nome + " tem " + idade + " anos");
System.out.println(info1);
System.out.println(info2);
System.out.println(info3);
System.out.println(info4);
System.out.println(info5);
System.out.println(nome + " tem " + altura + " metros de altura " );
int i = 2;
String s = "linha" + i * 10;
System.out.println(s);
produz o seguinte output:
xxxxxxxxxx
Maria tem 12 anos
Maria tem 12 anos
Maria tem 12 anos
Maria tem 12 anos
Maria tem 12 anos
12 anos tem a Maria
Maria tem 1.79 metros de altura
linha20
Os valores atribuídos às variáveis info1
a info4
são iguais, embora tenham sido construídos de forma diferente.
Repare que a expressão à direita da atribuição à variável info2
tem dois operadores iguais, de concatenação; por serem iguais, são avaliados da esquerda para a direita. Na primeira operação, como um dos operandos é do tipo String
, o operador +
é interpretado como concatenação; é feita então como que uma conversão do inteiro 12 em String
antes da concatenação ser avaliada. O valor resultante dessa primeira concatenação é a String
"Maria tem 12" que, de seguida, é concatenada com a string " anos", resultando em "Maria tem 12 anos".
Na atribuição à variável info3Parcial
o esquema de avaliação é o mesmo, com a diferença de que o valor que é concatenado com a String
"Maria tem " é dado por uma variável. É o valor da variável que é usado na concatenação.
A atribuição à variável info3
é uma concatenação vulgar entre duas String
s, em que uma é dada pelo conteúdo da variável info3Parcial
.
À semelhança das expressões matemáticas, podemos incluir numa expressão Java algumas das funções matemáticas mais comuns. Para já, vamos ver só alguns exemplos de como fazer isso; uma explicação mais aprofundada das funções em geral fica para o próximo capítulo.
xxxxxxxxxx
int i = 3;
double raiz = Math.sqrt(17.0 * i);
System.out.println(Math.sin(raiz));
long k = 3 * Math.round(Math.exp(i));
As funções Math.sqrt
, Math.sin
e Math.round
calculam, respetivamente, a raiz quadrada, o seno e o valor arredondado do seu argumento. A função Math.exp
calcula o número de Euler, e, elevado ao seu argumento.
No cálculo do valor de uma função, é feita, em primeiro lugar, a avaliação dos seus argumentos e, de seguida então, a avaliação da função sobre esses valores (na segunda instrução é calculado primeiro o valor de 17.0 * i e de seguida então a raiz quadrada desse resultado).
Na expressão da última instrução temos composição de funções – como o resultado de uma função aplicada a um valor é ele próprio um valor, pode ser usado como argumento de outra função.
Quando queremos usar no nosso programa um valor (pseudo)aleatório, podemos usar a função Math.random
, cujo resultado é um número aleatório do tipo double
, no intervalo [0,1[.
Por exemplo, double umQualquer = Math.random();
Se quisermos um número aleatório num intervalo diferente desse, basta-nos fazer as operações necessárias para o efeito. Como exemplo, a instrução double entre25e50 = (Math.random() + 1) * 25;
gera um valor aleatório no intervalo [25,50[ e atribui esse valor à variável entre25e50
.
Ver em https://docs.oracle.com/javase/9/docs/api/java/lang/Math.html as funções disponíveis mais comuns.
Anterior: 3.4. Revisitando variáveis
Seguinte: 3.6. Comentários, indentação e outros promotores da legibilidade