O char
, apesar do nome, é um tipo numérico, e seus valores vão de zero a 65535 (conforme especificação da linguagem). Esse número representa o Unicode Code Point do caractere.
De forma bem resumida, o Unicode define que todo caractere possui um valor numérico associado, chamado de code point. No caso dos primeiros 128 valores (ou seja, de zero a 127) os valores são os mesmos da tabela ASCII. Para mais detalhes, ver a documentação.
Enfim, o que acontece é que este número pode ser interpretado/manipulado tanto como um caractere quanto como o seu respectivo valor numérico (são basicamente “intercambiáveis”). Exemplo:
char c = 'a';
System.out.println(c); // imprime "a"
// mas um char também é um número
System.out.println((int) c); // 97 (o valor do caractere "a" na tabela ASCII)
// sendo número, nada impede de somar
c += 3; // soma 3
System.out.println((int) c); // 100
// mas 100 é o valor de outro caractere na tabela ASCII
System.out.println(c); // imprime "d"
//-----------------
// O contrário também é possível: pegar um int e interpretar como caractere
int n = 31021;
System.out.println(n); // imprime o número 31021
System.out.println((char) n); // imprime o caractere correspondente: 礭
O que acontece é que o método println
, ao receber um int
, imprime o valor numérico, e ao receber um char
, imprime o caractere correspondente. Mas o fato de apresentar esta informação de forma diferente não muda o fato de que o char
é um tipo numérico, e portanto seu valor pode ser manipulado como tal.
Então quando você faz int ascii = (int) caracteres[i] + cifra;
, está pegando o char
(no caso, caracteres[i]
, ou seja, o caractere que está na posição i
do array caracteres
) e somando cifra
. Como um char
também é um número, e vc está somando outro número (cifra
), o resultado também será um número (a variável ascii
).
No caso, vc está somando um char
com um int
, e pelas regras da linguagem, o resultado é um int
. Então na verdade nem precisaria do cast, poderia ser apenas int ascii = caracteres[i] + cifra;
. Ou ainda, como o programa só está imprimindo e não usa a variável ascii
para mais nada, poderia ser apenas System.out.print((char) (caracteres[i] + cifra))
.
Como cifra
é 1, o programa imprime o “caractere seguinte”, ou seja, “a” vira “b”, “f” vira “g”, etc (o detalhe é que o “z” vai virar “{”, ou seja, nem tudo vai virar outra letra).