4 de abril de 2013

Octal em Java

Olá Pessoal!

Estamos de volta com um assunto que, para nossa surpresa, tem uma certa frequência no nosso fórum:

O uso de números octais em Java.

Na verdade o assunto não surge como subject das threads, mas sim, como equívocos causados durante o uso da API do projeto.

E por isso, devido a relativa relevância deste "problema", resolvemos criar este post :-)

Vamos lá, o que vocês acham: seria um problema de design da API? Ou simplesmente um error-prone da linguagem Java no que diz respeito a manipulação dos números?

Vamos ao problema,... mas antes consideremos a relevância do problema para nós; bom, nesses 5 anos de projeto JRimum, já chegamos a ter 6 threads relacionadas ao assunto:


Isso nos daria uma média de 1 thread por ano (considerando que uma delas não foi um erro e sim uma sugestão).

Para nós isso tem relevância, pois nos força a explicar, na maioria das vezes, o porquê um usuário da API está enfrentando aquela situação, aparentemente sem lógica para ele. Dessa forma, preferimos criar um post para fazer referência ao problema quando ele ocorrer novamente ano que vem, correto? Isso é, vamos fazer uso do reuso :-)

O Problema:


Normalmente o problema/situação surge na utilização de objetos como:
  • Agencia  
  • Carteira 
  • NumeroDaConta;
Onde esses objetos são instanciados com valores do tipo java.lang.Integer, como:

new Agencia(01234,"7");

O problema está no primeiro zero, mas por quê? Lá vai, simples e direto: porque em Java um número do tipo Inteiro com zero na frente é considerado como um Octal. Veja em:

http://docs.oracle.com/javase/7/docs/api/java/lang/Integer.html

Se você não sabia e ainda está desconfiado, veja o que acontece se executar esse simples exemplo:

Integer inteiro = 0717;
System.out.println(inteiro);

Pois é, a saída será 463 que é o valor de um número do tipo Inteiro correspondente ao Octal "0717" e não o número do tipo Inteiro 717. Mas você que é novato no Java, ou por algum motivo desconhece o uso do Octal, ainda pode pensar: "mas isso é coisa do tal do Autoboxing não?". Ok, então vamos ver agora um outro exemplo:

Integer numero = Integer.valueOf(010);

Será que a saída vai ser 10 (Dez)? Ainda acredita nisso? Sério? É, se você executou esse código, não foi isso que você viu. O que você acabou de ver foi que a variável numero corresponde na verdade a 8 (Oito), pois você atribuiu um 8 (Oito) escrito em Octal (porque começa com zero) a uma variável do tipo Inteiro. E quando você visualiza a saída, daí você vê exatamente o número 8 do tipo Inteiro e não o dez que você escreveu.

Portanto: Integer.valueOf(010) == 8

Para saber mais sobre os tipos numéricos do Java veja em:

http://download.oracle.com/javase/tutorial/java/nutsandbolts/datatypes.html

Calma, não se preocupe caso você tenha cometido erros com Octais. Este não é um equivoco raro entre programadores iniciantes em Java, mas esperamos que este erro não se repita em seus programas nunca mais :-)

E aqueles que acham que é um problema da API? Bom, podemos ver erros semelhantes em outras API de mesmo propósito também:

http://www.guj.com.br/java/262410-stella---boleto---codigo-do-cedente-03036

A Solução?


Caso você ainda não tenha percebido e ache que isso realmente é um problema, então sua solução é:

Remova o(s) zero(s) antes do número do tipo Inteiro.

Pronto, essa era a moral da história. Caso queira saber mais sobre o sistema de numeração Ocatal veja:

http://pt.wikipedia.org/wiki/Octal

Até a próxima!