Curso de Java - Aula 6
Material de apoio para a vídeo-aula nº 6 do Curso de Java ministrado no Ponto G++, contendo toda a base teórica para um sólido acompanhamento da aula.
Java Curiosa & Divertida
Natal ou Dia das Bruxas?
Uma velha piada Nerd indaga por que os programadores confundem o Natal com o Dia das Bruxas… a resposta infamérrima é: porque Oct 31 = Dec 25.
Não os culpo se acharam esta a piada mais sem graça que já ouviram na vida, porque ela está mais para o humor inglês do que o nosso. Aliás, o seu entendimento exige um pouco de conhecimento da língua inglesa.
Abaixo eu forneço um link para quem quiser uma explicação pormenorizada do assunto, embora seja preciso um bom conhecimento de inglês porque o texto está nesse idioma. Contudo, a explicação dada nesta nossa vídeo-aula é suficiente para esclarecer tudo e, quem sabe, você consiga até rir no final…
Aproveite para aprender um pouco mais sobre os sistemas de numeração usados pelos computadores e, para completar, apresento ainda um programa em Java para confirmar os fundamentos matemáticos da nossa piada Nerd:
package piadaNerd; public class Piada { public static void main(String[] args) { int dec25 = 25; int oct31 = 031; System.out.println(dec25 == oct31); } // resultado da comparação: true (verdadeiro!) }
Tipos Primitivos
Embora Java seja uma linguagem orientada a objeto, fazendo um uso tão intensivo dessa metodologia de programação que podemos afirmar que quase tudo nela é um objeto, esse "quase" indica que possui alguns elementos que não são objetos.
Esses elementos são os denominados Tipos Primitivos, definidos na tabela a seguir:
Se precisarmos fazer muitos cálculos, como quando trabalhamos com gráficos, por exemplo, é interessante dispor de tipos mais simples, de forma a não comprometer o desempenho do aplicativo. Esta é a principal razão da linguagem Java ter mantido essa variedade de tipos primitivos, além disso, eles ocupam bem menos espaço na memória do que seus objetos equivalentes.
Tais objetos existem de fato: são as classes wrapper, que vemos na tabela a seguir, correlacionadas com seus equivalentes primitivos:
Wrapper, em inglês, quer dizer invólucro e, na linguagem Java, são classes especiais que possuem métodos para a conversão de variáveis primitivas, encapsulando tipos primitivos. Voltaremos a este assunto mais tarde, depois de consolidarmos mais o entendimento de orientação a objeto.
Voltando então aos tipos primitivos propriamente ditos, a primeira observação a ser feita é quanto ao tamanho de cada um deles, os quais, independentemente do sistema operacional ou arquitetura do hardware, são aqueles exibidos na tabela acima. Esses tamanhos, por sua vez, definem os limites para os números que podem ser representados em cada um deles.
Podemos subdividi-los em três grandes grupos: booleano, inteiros e de ponto flutuante. O grupo booleano possui apenas um tipo, o boolean, com o tamanho de 1 único bit e que pode assumir apenas os valores true ou false, não admitindo casting, isto é, sua conversão para outro tipo. O grupo dos inteiros são o byte, com o tamanho de 1 byte; o short, com 2 bytes; o int com 4 bytes e o long com 8 bytes, todos eles operando no sistema de complemento de dois, que examinaremos mais adiante. Ainda faz parte do grupo de inteiros o tipo char, com 2 bytes, para a representação de caracteres Unicode, no padrão UTF-16. O último grupo é o Ponto Flutuante, para representar os números fracionários, com os tipos float, de 4 bytes e double de 8 bytes. Do tamanho em bytes decorrem os limites de cada um dos tipos, como pode ser visto na tabela acima.
Complemento de Dois
Como sabemos, a representação dos números, inclusive os caracteres, que também são números relacionados a algum tipo de codificação como ASCII ou UTF-8, é feita nos computadores na base binária, usando um sistema muito bem bolado chamado de Complemento de Dois. Suas regras são as seguintes:
-
O zero é representado colocando todos os bits em zero. No tipo byte, por exemplo, que possui 1 byte ou 8 bits, o zero seria representado como: 0 0 0 0 0 0 0 0
-
O maior número positivo que pode ser representado segue a fórmula: 2(número_de_bits-1) - 1 e o menor negativo obedece a fórmula 2(número_de_bits-1) apenas, pois já existe o zero entre os positivos. No tipo byte, temos então o maior inteiro positivo igual a 2(8-1) - 1 = 27 - 1 = 128 - 1 = 127 e o menor inteiro negativo igual a 2(8-1) = 27 = -128.
-
Para os números negativos, ao invés de iniciarmos com todos os bits colocados em zero como nos positivos, colocamos todos os bits em 1. No tipo byte que estamos usando como exemplo, o -1 seria representado como: 1 1 1 1 1 1 1 1
Vejam na figura a seguir a representação do sistema de complemento de dois para um tipo de apenas 4 bits (denominado tecnicamente de nibble), para ter uma visão mais clara da aplicação das regras acima.
Como os números negativos são o complemento de dois dos positivos e vice-versa, este sistema permite operar com segurança na memória dos computadores pois, se houver um "estouro" do limite, o número apenas converte-se no limite inferior oposto, isto é, 0 se o valor "estourado" for negativo e o menor número negativo possível, se o valor "estourado" for positivo. Vejam na representação gráfica abaixo como isso fica fácil de visualizar: