O segundo exemplo é claramente superior. O significado do segundo exemplo é imediatamente óbvio quando você olha para o código. O significado do primeiro exemplo é apenas óbvio se você memorizou toda a tabela ASCII na sua cabeça.
Você deve distinguir entre a verificação de um caractere específico ou a verificação de um intervalo ou classe de caracteres.
1) Verificando um caractere específico.
Para caracteres comuns, use o literal do caractere, por exemplo, if(ch=='z')...
. Se você verificar caracteres especiais, como tabulação ou quebra de linha, você deve usar as fugas, como if (ch=='\n')...
. Se o caractere que você está verificando for incomum (por exemplo, não imediatamente reconhecível ou não disponível em um teclado padrão), você pode usar um código de caractere hexadecimal em vez do caractere literal. Mas como um código hexadecimal é um "valor mágico", você o extrai para uma constante e o documenta:
const char snowman = 0x2603; // snowman char used to detect encoding issues
...
if (ch==showman)...
Códigos hexadecimais são o modo padrão de especificar códigos de caracteres.
2) Verificando uma classe ou intervalo de caracteres
Você realmente não deveria estar fazendo isso diretamente no código do aplicativo, mas deveria encapsulá-lo em uma classe separada, preocupada apenas com a classificação de caracteres. E você deve variar disso, já que as bibliotecas já existem para esse propósito, e a classificação de caracteres é geralmente mais complexa do que você pensa, pelo menos se você considerar caracteres fora do intervalo ASCII.
Se você está preocupado apenas com os caracteres no intervalo ASCII, você poderia usar literais de caracteres nesta biblioteca, caso contrário, você provavelmente usaria literais hexadecimais. Se você observar o código-fonte da biblioteca de caracteres incorporada em Java, ele também se referirá a valores e intervalos de caracteres usando hexadecimal, pois é assim que eles são especificados no padrão Unicode.