quinta-feira, 28 de fevereiro de 2008

[11] Tipos de variáveis: tipos primitivos


Vamos aprender um pouco mais sobre os tipos de variáveis existentes no Java: tipos primitivos e tipos de referência. Porém, neste Post daremos ênfase aos tipos primitivos.

Variáveis de tipos primitivos

Uma vez que uma variável é definida como um tipo primitivo, seu tipo não pode ser alterado. Isso implica dizer que ao declarar uma variável de tipo primitivo como a variável "velocidade" abaixo como tipo int, ela não pode, dentro do mesmo escopo, ser redefinida para o tipo float, por exemplo:

int velocidade;
float velocidade;

Cada variável de um tipo primitivo armazena apenas um valor por vez do seu tipo. Os tipos primitivos da linguagem Java são: char, byte, short, int, long, float, double e boolean. Veremos a seguir características e um exemplo de uso para cada tipo primitivo:

_______________________________________________________

char

O tipo char é utilizado para armazenar em uma variável caracteres individuais, tais como: 'A', 'G' ou 'U'. Cada caracter a ser atribuído a uma variável do tipo char deve ser escrito entre aspas simples:

char letra = 'A';
System.out.println("LETRA INICIAL: " + letra);
letra = 'E';
System.out.println("NOVA LETRA: " + letra);


Certamente os valores a serem exibidos após a execução do código acima são:

LETRA INICIAL: A
NOVA LETRA: E

Uma variável do tipo char também pode receber entre aspas simples um valor Unicode:

char caracterUnicode = '\u0041';
System.out.println("Caracter unicode: " + caracterUnicode);


E será exibido na tela:

Caracter unicode: A

Pois o código 0041 na tabela unicode pertence ao caracter 'A', assim como o código 0030 pertence ao número zero e o código 0032 pertence ao número 2.

_______________________________________________________

byte

O tipo byte armazena um valor inteiro de -128 a 127, inclusive:

byte pequenoNumero = 30;
byte outroNumero = 50;
byte soma = pequenoNumero + outroNumero;
System.out.println("Soma: " + soma);

O valor exibido no console é:

Soma: 80

_______________________________________________________

short

O tipo short armazena um valor de -32.768 a 32.767, inclusive:

short valor1 = -1000;
short valor2 = 20600;
short valor3 = valor2 - valor1;
System.out.println("Valor 3: " + valor3);

Saída:

Valor 3: 19600

_______________________________________________________

int

O tipo primitivo int armazena um valor inteiro entre -2.147.483.648 e 2.147.483.647, inclusive:

int idade = 0;
int anoNascimento = 2009;
int saldoNegativo = -3200;
_______________________________________________________

long

O tipo primitivo long armazena um valor inteiro entre -9.223.372.036.854.775.808 e 9.223.372.036.854.775.807. Para deixar explícito que um valor deve ser interpretado como long, é comum que se digite a letra L, minúscula ou maiúscula:

long numeroGrande = 1300333030;
long outroNumeroGrande = 1300333030l;
long maisUmNumeroGrande = 1300333030L;

Todas as variáveis declaradas acima têm o mesmo valor e são do tipo long, porém note que as variáveis "outroNumeroGrande" e "maisUmNumeroGrande" possuem as letras l e L, respectivamente, ao final dos valores atribuídos. O uso da letra L é útil apenas para diferenciar que o valor em questão será armazenado em uma variável do tipo long, e não int, por exemplo. O valor não sofre quaisquer alterações após o uso da letra.

_______________________________________________________

float

Uma variável do tipo primitivo float armazena um número real de 32 bits segundo o padrão IEEE 754. Para deixar explícito que o valor em questão é do tipo float, usa-se a letra F ao final do valor.


float altura = 1.87f;
float peso = 71.5F;
float juros = 1.5;

O valor não sofre quaisquer alterações após o uso da letra.

_______________________________________________________

double

O tipo de dado double é ponto-flutuante de dupla precisão de 64 bits segundo o padrão IEEE 754:

double superValor = 121313.4;
System.out.println("Super valor: " + superValor);

O valor exibido é:

Super valor: 121313.4

_______________________________________________________

boolean

O tipo boolean - ou booleano - só pode receber dois tipos de valores: true ou false:

boolean isOpened = true;
System.out.println("IS OPENED (antes): "+ isOpened);
boolean flag = false;
isOpened = false;
System.out.println("IS OPENED (depois): "+ isOpened);
System.out.println("flag: "+ flag);
A saída exibida será:

IS OPENED (antes): true
IS OPENED (depois): false
flag: false

_______________________________________________________

Cuidado ao tentar atribuir um valor maior do que um tipo de variável pode suportar, como por exemplo:

byte valorPequeno = 12340;

int valorNaoLong = 2980928320213L;

12340 é considerado como valor inteiro, desde já não é possível atribuir tal valor a uma variável do tipo byte, pois o tipo byte suporta valores inteiros entre
-128 a 127, apenas.

E caso o valor
2980928320213 inão seja seguido pela letra L, o compilador tentará, por padrão, entendê-lo como um valor do tipo int, e como os valores int devem estar entre -2147483648 e 2147483647, o valor 2980928320213 excede esse limite, a compilação falhará e dará a seguinte mensagem:

The literal 2980928320213 of type int is out of range


Cuidado também ao tentar atribuir valores que são incompatíveis ao tipo em questão:

char letra = 1243f;
int number = 1243f;

Estas atribuições causam erro de compilação e geram as seguintes mensagens:

Type mismatch: cannot convert from float to char
Type mismatch: cannot convert from float to int



Os indicadores de tipos primitivos são palavras-chave, desde então você não pode criar identificadores com o mesmo nome que eles. Como, por exemplo, criar uma variável chamada "int" ou "float". Palavras-chave são palavras reservadas.

Vale também ressaltar que os tipos primitivos também podem ser chamados de tipos predefinidos.






Bem, neste Post ficamos por aqui. Na próxima postagem aprenderemos sobre os tipos de referência do Java. Um abraço e até logo.

quarta-feira, 13 de fevereiro de 2008

[10] Ponto-e-vírgula, escopo e variáveis locais

Neste Post vamos aperfeiçoar um pouco os nossos conhecimentos sobre o que vimos até o momento. Entenderemos o motivo do uso do símbolo ";" após a invocação de comandos, entenderemos também do que se trata um escopo e variáveis locais.


PONTO-E-VÍRGULA (;)

Cada comando deve ser finalizado com ponto-e-vírgula (;). Em Posts anteriores já trabalhamos com mais de um comando, por exemplo:


System.out.println(" Primeiro comando ");
System.out.println(" Segundo comando ");

O mesmo acontece com a criação de objetos e chamadas a métodos - se você ainda não sabe, "println()" é um método. Supondo que exista uma classe chamada Porta, onde seus métodos são abrir() e fechar(), veremos o uso de ponto-e-vírgula no final das chamadas:

Porta p = new Porta();
System.out.println("O método abrir() será chamado");
p.abrir();
System.out.println("O método fechar() será chamado");
p.fechar();


E para que não reste mais dúvidas sobre o uso de ponto-e-vírgula, este símbolo também é usado na declaração de atributos:

public class Porta{

boolean estaAberta;
String tipoPorta;

}


ESCOPO

Um escopo delimita o "tempo de vida" de uma variável, seja ela de referência ou de um tipo primitivo. Esta delimitação é definida através dos símbolos "{" e "}", que são equivalentes às instruções "Begin" e "End", respectivamente, em linguagens como Pascal. O espaço delimitado pelos símbolos "{" e "}" é denominado bloco.

Observe a classe Livro abaixo:

public class Livro {
String titulo;

String autor;

int qtdPaginas;
}


Isso significa dizer que os atributos titulo, autor e qtdPaginas de um objeto do tipo Livro existirão enquanto o objeto existir, pois seu escopo está definido para toda a classe. Observe o escopo do método escreverQuantidadePaginas() da classe abaixo:

public class Livro {

String titulo;
String autor;
int qtdPaginas;

public void escreverQuantidadePaginas(){
int quantidade = qtdPaginas;

System.out.println("QUANTIDADE DE PAGINAS: ");

System.out.println(quantidade);
}

}


O escopo da variável "quantidade", está limitado ao método escreverQuantidadePaginas(). Isso implica dizer que quando o método escreverQuantidadePaginas() for encerrado a variável "quantidade" já não mais poderá ser referenciada.

Um ponto importante a se ressaltar é que "quantidade" estará acessível apenas
dentro do método escreverQuantidadePaginas(). Porém, note que a variável "qtdPaginas" está sendo acessada de dentro do método escreverQuantidadePaginas(), isso é possível porque o escopo de "qtdPaginas" foi definido para toda a classe, e o método escreverQuantidadePaginas() pertence à classe. Desde já o atributo "qtdPaginas" pôde ser acessado através do método.

Para melhor compreensão vamos instanciar um objeto do tipo Livro:


public static void main(String[] args){
Livro livro = new Livro();
}

Você pode livremente acessar os atributos do objeto livro como atribuir valores e exibí-los.

public static void main(String[] args){

Livro livro = new Livro();
livro.autor = "André Leitão";
livro.qtdPaginas = 100;
System.out.println("QUANTIDADE PÁGINAS: ");

System.out.println(livro.qtdPaginas);


}


Mas você não pode acessar a variável "quantidade", pois seu tempo de vida está delimitado pelo escopo do método escreverQuantidadePaginas(). Desde já seria um erro codificar:
  1. public static void main(String[] args){
  2. Livro livro = new Livro();
  3. livro.qtdPaginas = 100;
  4. livro.quantidade = 20;
  5. }

A funcionalidade da linha 4 insinua algo como: "atribua o valor 10 à variável quantidade, que pertence ao objeto livro". E esta atribuição não será possível porque "quantidade" não será reconhecida como um atributo do objeto livro.

Observe a figura abaixo:


ATRIBUTOS SÃO VARIÁVEIS?

Atributos são variáveis, pois armazenam valores e estes valores podem ser alterados e/ou obtidos.

A diferença básica entre um atributo e uma variável local é que o escopo de um atributo é delimitado pelo bloco de sua classe, e o escopo de uma variável local é delimitado por um outro bloco qualquer.




VARIÁVEIS LOCAIS

Uma variável local não pode ser acessada por toda a classe, apenas dentro do bloco em que foi declarada. Por exemplo:

  1. public class CalculadoraParaSoma(){
  2. int operando1;
  3. int operando2;
  4. public void calcular(){
  5. int resultado = operando1 + operando2;
  6. System.out.println("RESULTADO: ");
  7. System.out.println(resultado);
  8. }
  9. }
Note que na linha 66 uma variável local foi declarada. A variável local resultado receberá a soma dos atributos "operando1" e "operando2". Logo em seguida o resultado da soma é exibido.

"resultado" não estará acessível para toda a classe. Apenas para o método em que ela foi declarada. Portanto seria um erro codificar:

public static void main(String[] args){
CalculadoraParaSoma calc = new CalculadoraParaSoma();
calc.operando1 = 2;
calc.operando2 = 6;
calc.resultado = operando1 + operando2;
}


Ao tentar compilar este código, o compilador exibirá a seguinte mensagem de erro:

"calc.resultado cannot be resolved or is not a field"

Isto é, "resultado" não é reconhecido como membro do objeto calc. "resultado" é acessível apenas dentro do bloco onde foi declarado. No caso, o método calcular().

Várias variáveis locais de diferentes tipos podem ser declaradas dentro um método, e não obrigatoriamente elas precisam ser inicializadas. Observe um bloco qualquer abaixo:

{
int valor1;
int valor2 = 50;
String nome = "Java";
double altura;
altura = 3.4;
valor1 = 8;
}

Este bloco funcionará sem problemas. No total ele tem 4 variáveis locais, o que implica dizer que elas poderão ser acessadas até que o bloco se finalize.

Tente usar o conteúdo deste bloco em algum método como o main, por exemplo - não se esqueça de que main também é um método - e imprima os valores das variáveis locais.

Este Post fica por aqui. Um abraço


sexta-feira, 1 de fevereiro de 2008

[9] Lendo dados a partir do teclado com Scanner

Até o momento só utilizamos o console para exibir saídas como mensagens de "Hello World" ou valores de um objeto. Agora vamos aprender a ler dados a partir do teclado e exibí-los. Para isto, vamos fazer uso de nossa primeira classe da API do Java: a classe Scanner.

Embora ler dados do teclado não seja a única especialidade da classe Scanner, a utilizaremos apenas para este propósito.


Localizando a classe Scanner

Afinal, se a classe Scanner não foi criada por nós, então onde ela se encontra? Como foi dito anteriormente, Scanner é uma classe da API do Java. Mas como teremos acesso à API do Java? Simples, ao criar um projeto no Eclipse, note que "anexado" ao seu projeto se encontra a JRE System Library, que contém todas as classes da Java API.


A API organiza suas classes por pacotes, e toda classe da API está dentro de um pacote. A API Java é muito rica e extensa, desde já é possível que haja classes com nomes iguais. Então, para se utilizar uma determinada classe devemos especificar, em código, em qual pacote a classe se encontra. Com o Scanner não será diferente. Seu caminho é: java->util->Scanner. Isto quer dizer que a classe Scanner está dentro do pacote util, que por sua vez está contido no pacote java.

Ao ato de "usar" uma classe de um pacote externo chamamos de importação de pacotes. Para importar uma classe em Java utilizamos a palavra-chave import seguida do caminho da classe. Logo para importar Scanner usaremos o código:

import java.util.Scanner;


Criando um objeto do tipo Scanner

O procedimento para se criar uma instância de Scanner é semelhante à criação do objeto Window - classe em que trabalhamos no Post anterior.

Para exemplificar vamos criar um objeto do tipo Scanner que se chamará "entrada":

Scanner entrada = new Scanner(System.in);

Não se preocupe com o trecho:
new Scanner(System.in);
Mantenha em mente que um objeto do tipo Scanner está sendo criado e que devemos nos concentrar apenas em ler dados a partir do teclado.


Criando a classe EntradaDados

Antes de mais nada, para rodarmos um programa Java lembre-se de que precisamos de uma classe que contenha o método main. Então, vamos criar uma classe chamada EntradaDados, e logo em seguida implementamos o método main dentro dela:

public class EntradaDados {

public static void main(String[] args) {

}

}


Esquecemos apenas de inserir o código de instanciação do objeto "entrada" dentro do método main. Inserindo-o teremos:

public class EntradaDados {

public static void main(String[] args) {
Scanner entrada = new Scanner(System.in);
}

}

O código acima falhará no processo de compilação, pois Scanner é reconhecido como um símbolo estranho, ou seja, o javac não reconhecerá Scanner como uma classe, pois você não a importou. Para resolver o problema importaremos a classe Scanner antes da declaração da classe EntradaDados. Observe o código resultante:

import java.util.Scanner;

public class EntradaDados {

public static void main(String[] args) {
Scanner entrada = new Scanner(System.in);
}

}


Agora seu programa pode ser compilado e executado sem erros. Porém, sua única funcionalidade é criar um objeto do tipo Scanner e encerrar sua execução.


Scanner também contém métodos

Ora, se Scanner é uma classe que lê dados - observe a ação: LER - então ela possui métodos que possibilitam esta ação. O que difere uma classe de outra, do ponto de vista genérico, são as funcionalidades de seus métodos.


Através do objeto "entrada", que é do tipo Scanner, temos acesso a diversos métodos para leitura de teclado. São alguns deles:

* next() : para ler textos
* nextInt() : para ler números inteiros
* nextFloat() : para ler números reais - ou números de ponto flutuante.
* nextDouble() : para ler números reais - ou números de ponto flutuante com dupla precisão



Lendo um texto com Scanner


Vamos fazer com que nosso programa leia e escreva o nome do usuário. Logo após a criação do objeto entrada inclua o código:

System.out.println("Digite seu nome: ");
String nome = entrada.next();
System.out.println("Seu nome: ");
System.out.println(nome);

Note que ao executar o programa, a seguinte saída será exibida no console:

Digite seu nome:

Este é o momento em que o usuário deve digitar seu nome no console. Após a digitação, ela deve ser confirmada com o pressionamento da tecla Enter. Logo, a seguinte saída será mostrada:

Digite seu nome:
Schneider
Seu nome:
Schneider

Ao digitar o nome e pressionar teclar Enter, o valor do nome é armazenado em uma variável local chamada "nome", e logo o valor contido na variável "nome" é usado para ser exibido.


Lendo um número inteiro com Scanner

Vamos agora criar um programa que leia a idade do usuário e a exiba:


System.out.println("Digite sua idade: ");
int idade = entrada.nextInt();
System.out.println("Sua idade é: ");
System.out.println(idade);


Assim como o método next(), o método nextInt() também aguardará uma entrada do usuário e o pressionamento da tecla Enter para que o programa prossiga sua execução. Porém, o método nextInt exige que o usuário digite apenas números, nada de letras ou caracteres especiais.




VARIÁVEIS LOCAIS...

As variáveis locais serão melhor abordadas no próximo Post.
Como você deve ter percebido, uma variável local armazena um valor, assim como um atributo de uma classe. Na verdade, um atributo é uma variável, porém pertencente à classe em questão, diferentemente de uma variável local, que possui tempo de vida limitado e não pertence a uma classe.




RESUMO

*
Scanner pertence ao pacote java.util
* Você aprendeu a criar um objeto do tipo Scanner:

Scanner entrada = new Scanner(System.in);

* Para capturar uma entrada de texto do teclado usa-se o método next():

entrada.next();

* Para capturar uma entrada numérica usa-se:

entrada.nextInt() para capturar números inteiros
entrada.nextFloat() para capturar números reais
entrada.nextDouble() para capturar números reais com dupla precisão



Exercícios

1. Construa um programa que leia o nome e a idade do usuário e exiba-os logo em seguida.

2. Construa um programa que leia o nome e o sobrenome do usuário e exiba-os logo em seguida.

3. Construa um programa que leia a altura do usuário e exiba-a na tela.


Ficamos por aqui. Até a próxima