Você está na página 1de 31

2 – Características da linguagem

Afonso Alcantara
Seed Technology Solutions
1

1
Objetivos
„ Palavras-chaves
„ Tipos primitivos
„ Conversões implícitas e explícitas
„ Literais inteiros
„ Literais de ponto flutuante
„ Literais booleanos
„ Literais caracteres
„ Valores padrões
„ Método main
„ Best Practices

Este é o capítulo mais importante, pois se trata da base da


linguagem, sem ele, você terá dificuldades em entender os demais
capítulos.

2
Palavras-chaves
„ São 49 palavras-chaves:
byte – short – char – int – long – float – double
boolean – public – protected – private
static – abstract – final – strictfp – transient
synchronized – native – void – class – interface
implements – extends – if – else – do – while – for
default – switch – case – break – continue
assert – const – goto – throws – throw
new – catch – try – finally – return
this – super – package – import – instanceof
volatile

Em Java são 49 e você deve tê-las em mente para usar na


sua vida profissional, mas não se preocupe, a assimilação é difícil e só será
com o tempo.
Veja a lista abaixo:
byte – short – char – int – long – float – double
boolean – public – protected – private
static – abstract – final – strictfp – transient
synchronized – native – void – class – interface
implements – extends – if – else – do – while – for
default – switch – case – break – continue
assert – const – goto – throws – throw
new – catch – try – finally – return
this – super – package – import – instanceof
volatile
Todas as palavras-chave são minúsculas e qualquer alteração
nesta regra é considerada um erro de sintaxe pelo compilado Java.
Lembre-se: null, true e false são literais e não palavras-chave.

3
Tipos primitivos
„ Temos 8 tipos primitivos em Java, de 8 bits a 64 bits e
literais, com e sem sinal.
byte – inteiro de 8 bits com sinal.
short – inteiro de 16 bits com sinal.
char – caracter UNICODE com 16 bits.
int – inteiro com 32 bits com sinal.
long – inteiro com 64 bits com sinal.
float – ponto flutuante com 32 bits com sinal.
double – ponto flutuante com 64 bits com sinal.
boolean – literal com true e false.

Temos 8 tipos primitivos em Java™, de 8 bits a 64 bits e literais, com e sem


sinal.
byte – inteiro de 8 bits com sinal;
short – inteiro de 16 bits com sinal;
char – caracter UNICODE com 16 bits;
int – inteiro com 32 bits com sinal;
long – inteiro com 64 bits com sinal;
float – ponto flutuante com 32 bits com sinal;
double – ponto flutuante com 64 bits com sinal;
boolean – literal com true e false

4
Tipos primitivos
„ Capacidade(Range) em bytes de cada tipo primitivo.

Importante é que tipos primitivos NÃO são objetos e por isso


tem um comportamento diferente, tanto em memória alocada como em
tratamento. Outra informação importante é que em Java™ todo tipo
primitivo numérico tem sinal, ou seja, pode ser representado tanto na forma
negativa (-), como na forma positiva (+). Veja a tabela abaixo:

A fórmula na verdade é, -2^(bits-1) até 2^(bits -1) -1. Na faixa


positiva o número é subtraído por 1, pois o primeiro bit representa o sinal,
então zero quer dizer que o número em questão é positivo e um para
negativo.

5
Tipos primitivos
„ Exemplo: um byte tem 8 bits, então primeiro bit é usado
para guardar o sinal, então sobraram 7 bits para
representar nosso número. Se convertermos o número
+125 para a representação binária, teremos 1111101 e
ficaria representado 01111101, com o zero indicando
que é um número positivo. Agora se convertermos o
número +128 para a representação binária, teremos
10000000, como esse número é composto por 8 bits,
então não é possível adicionar o bit do sinal e o número
+128 não está no intervalo do tipo byte.

Exemplo: um byte tem 8 bits, então primeiro bit é usado para


guardar o sinal, então sobraram 7 bits para representar nosso número. Se
convertermos o número +125 para a representação binária, teremos
1111101 e ficaria representado 01111101, com o zero indicando que é um
número positivo. Agora se convertermos o número +128 para a
representação binária, teremos 10000000, como esse número é composto
por 8 bits, então não é possível adicionar o bit do sinal e o número +128 não
está no intervalo do tipo byte.
char – É a representado por caracteres UNICODE de 16 bits e
não tem sinal. Também pode ser representado por um número inteiro de 16
bits SEM SINAL, o que quer dizer que podemos aplicar a seguinte fórmula.
2^16 – 1. Traduzindo, pode-se atribuir 10, 100, 14555, 65535, mas não
65536. Essa faixa de valores permite que você represente qualquer
caractere de qualquer idioma do planeta.
float – É um tipo numérico de ponto flutuante de 32 bits com
sinal, porém para a prova você não precisa saber a faixa de valores.
double – É um tipo numérico de ponto flutuante de 64 bits
com sinal e também não é necessário saber sua faixa de valores.
boolean – É um valor literal e os únicos valores permitidos
são: true e false.

6
Conversões implícitas e
explícitas
„ Conversão de tipos primitivos
„ Chamado também de Casting
„ Ex.:
public class Conversão {
public static void main(String[] args) {
int i = 10;
long l = 20;
l=i // perfeitamente possível
i = l; // não é possível
i = (int)l; // É por minha conta e risco!
//To fazendo um casting
}
}

Quando estamos programando, sempre nos deparamos com


situações onde precisamos converter tipos numéricos, mas existe uma regra
que precisa ser seguida para realizar tal operação. Nunca você poderá
converter um tipo de maior valor em um de menor valor. Por exemplo:
public class Conversão {
public static void main(String[] args) {
int i = 10;
long l = 20;
l=i // perfeitamente possível
i = l; // não é possível
i = (int)l; // É por minha conta e risco!
//To fazendo um casting
}
}

Na linha 5 houve uma conversão implícita e perfeitamente


legal, pois foi passado um valor de um tipo menor para um tipo de maior
valor.
Já na linha 6, quebramos a regra que não podíamos quebrar!
Tentamos converter um tipo de maior valor para um de menor valor.

7
Conversões implícitas e
explícitas
byte (8 bits) boolean (true\false)
short (16 bits) char(16bits)
int (32 bits)
long (64 bits)
float (32 bits)
double (64 bits)
Precisa de
Cast

double d= 128.0;
byte b=(byte)d; Qual o resultado ?

b= 100.4; Correto ?
8

Quando estamos programando, sempre nos deparamos com


situações onde precisamos converter tipos numéricos, mas existe uma regra
que precisa ser seguida para realizar tal operação. Nunca você poderá
converter um tipo de maior valor em um de menor valor. Por exemplo:
public class Conversão {
public static void main(String[] args) {
int i = 10;
long l = 20;
l=i // perfeitamente possível
i = l; // não é possível
i = (int)l; // É por minha conta e risco!
//To fazendo um casting
}
}

Na linha 5 houve uma conversão implícita e perfeitamente


legal, pois foi passado um valor de um tipo menor para um tipo de maior
valor.
Já na linha 6, quebramos a regra que não podíamos quebrar!
Tentamos converter um tipo de maior valor para um de menor valor.

8
Conversões implícitas e
explícitas
„ Vamos sempre ter em mente um exemplo para
diferenciar conversão implícita de explícita. Imagine um
copo com a capacidade de 100 mlts e você tem 300
mlts em uma lata.
„ Agora imagine que você quer colocar o conteúdo da
lata no copo. Com toda certeza você não vai colocar
tudo de uma vez.
„ Quando isso acontecer, devemos usar conversão
explícita, mas iremos perder dados, ou seja, o líquido
que restou na lata.

Vamos sempre ter em mente um exemplo para diferenciar


conversão implícita de explícita. Imagine um copo com a capacidade de 100
mlts e você tem 300 mlts em uma lata. Agora imagine que você quer colocar
o conteúdo da lata no copo. Com toda certeza você não vai colocar tudo de
uma vez. Porque? Porque vai transbordar. Certo? É exatamente isso que irá
acontecer caso você queira colocar um valor maior do que o suportado pelo
tipo primitivo em questão. Quando isso acontecer, devemos usar conversão
explícita, porém iremos perder dados, ou seja, o líquido que restou na lata.

9
Literais inteiros
„ É um valor escrito no código fonte e identificado como
um tipo primitivo.
„ Podem ser de três tipos: octal, decimal e hexadecimal.
„ Ex.:
int x = 10; // literal inteiro
char u = 'k'; // literal char
boolean b = false; // literal boolean
double d = 9832.11; // literal double

10

Um literal inteiro em Java™ é um valor escrito no código fonte


e identificado como um tipo primitivo. Por exemplo:
int x = 10; // literal inteiro
char u = 'k'; // literal char
boolean b = false; // literal boolean
double d = 9832.11; // literal double
Há três maneiras de se representar literais inteiros em Java:
octal, decimal e hexadecimal.

10
Literais inteiros
„ Exemplo de literal inteiro em octal.
public class Octal {
public static void main(String[] args) {
int seis = 06; // idem ao decimal 6
int sete = 07; // idem ao decimal 7
int oito = 010; // idem ao decimal 8
int nove = 011; // idem ao decimal 9
}
}

11

Um código fonte que tem variáveis literais inteiros em octal:


public class Octal {
public static void main(String[] args) {
int seis = 06; // idem ao decimal 6
int sete = 07; // idem ao decimal 7
int oito = 010; // idem ao decimal 8
int nove = 011; // idem ao decimal 9
}
}
Lembre-se de que se você ver um 0(zero) na frente do
número, saiba que este está represen-tado em octal.

11
Literais interios
„ Exemplo de literal inteiro em hexadecimal.
public class Hexadecimal {
public static void main(String[] args) {
int quinze = 0xF; // 15 (decimal)
int vinte_e_nove = 0x1D; // 29 (decimal)
int valor = 0xBAFAFA; // 12253946 (decimal)
int valor = 0XBaFaFa; // 12253946 (decimal)
}
}

12

public class Hexadecimal {


public static void main(String[] args) {
int quinze = 0xF; // 15 (decimal)
int vinte_e_nove = 0x1D; // 29 (decimal)
int valor = 0xBAFAFA; // 12253946 (decimal)
int valor = 0XBaFaFa; // 12253946 (decimal)
}
}
Um número representado em hexadecimal deve vir precedido
do prefixo (0x). Neste caso o compilador Java não faz distinção de letras
minúsculas de letras maiúsculas.

12
Literais de ponto flutuante
„ É por padrão definido como double, 64 bits.
„ Tem um sufixo “f” para tipo float (obrigatório).
„ Tem um sufixo “d” para tipo double (padrão).
public class Teste {
public static void main(String[] args) {
double a = 9223372036854775807.0; // ok tipo
// double
float b = 2147483647; // ok tipo int para float
// conversão implicita
float c = 2147483647.0; // erro! double -> float
float d = (float)2147483647.0; // ok - conversão
float e = 2147483647.0f; // ok
}
}

13

Um literal de ponto flutuante em Java é por padrão definido


como double, 64 bits, e por esse motivo você deve adicionar um sufixo, “f”,
ao final de cada atribuição de variáveis do tipo float, o sufixo para o tipo
double, “d”, é opcional. Estes podem ser minúsculos ou maiúsculos. Veja o
exemplo:

public class Teste {


public static void main(String[] args) {
double a = 9223372036854775807.0; // ok tipo double
float b = 2147483647; // ok tipo int para float conversão implicita
float c = 2147483647.0; // erro! double -> float
float d = (float)2147483647.0; // ok - conversão
float e = 2147483647.0f; // ok
}
}

13
14

Na linha 4, não há erro de compilação, é um literal int e não


double. O compilador irá adicionar “.0” ao final do valor, transformando-o em
ponto flutuante do tipo float.
Na linha 5, temos um erro de compilação, estamos tentando
converter um double para um float, ou seja, estamos tentando colocar 64
bits dentro de 32 bits. Lembre-se do exemplo do copo.
Na linha 6, é feita uma conversão explícita.
Na linha 7, é feita uma atribuição de uma valor dentro da faixa
de 32 bits de ponto flutuante a uma variável do tipo float. Note que
adicionamos o sufixo “f” ao final.

14
Literais booleanos
„ Pode receber ser true ou false.
public class LitBoo {
public static void main(String[] args) {
boolean a = true; // ok
boolean b = false; // ok
boolean c = 1; // erro de compilacao
}
}

15

Os únicos valores que os tipos primitivos booleanos podem


receber são true ou false. Veja o exemplo abaixo:
public class LitBoo {
public static void main(String[] args) {
boolean a = true; // ok
boolean b = false; // ok
boolean c = 1; // erro de compilacao
}
}
Lembre-se que em Java não é como em C e outras
linguagens, onde 1 e 0 representam true e false, respectivamente.

15
Literais caracteres
„ Um único caractere entre apóstrofo
public class Carac {
public static void main(String[] args) {
char a = 'a'; // ok
char b = '@'; // ok
char c = '\u004E'; // refere-se a letra N
}
}

16

Os valores caracteres são compreendidos como um único


caractere entre apóstrofo, ou seja, entre aspas simples. Veja o exemplo
abaixo:
public class Carac {
public static void main(String[] args) {
char a = 'a'; // ok
char b = '@'; // ok
char c = '\u004E'; // refere-se a letra N
}
}

16
Valores padrões
„ Para tipos numéricos o valor é “0”
„ Para tipos de ponto flutuante o valor é “0.0”
„ Para tipos booleanos o valor é “false”
„ Para tipos caracteres o valor é “\u0000” e tipos objetos
o valor é “null”

17

Todo e qualquer tipo primitivo, objeto ou array tem um valor


quando é construído. Isto vale para apenas membros de classes ou
atributos, como são também conhecidos. Em variáveis locais apenas os
arrays têm valores padrões adotados. Abaixo estão os valores para cada
tipo.
Para tipos numéricos o valor é “0”. Para tipos de ponto
flutuante o valor é “0.0”. Para tipos booleanos o valor é “false”. Para tipos
caracteres o valor é “\u0000” e tipos objetos o valor é “null”.

17
Método main
„ Sempre será primeiro chamado quando a classe for
executada.
„ Formas:
public static void main(String[] args) {} //Recomendado
static public void main(String[] args) {}
public static void main(String[] a) {}
public static void main(String [] a) {}
public static void main(String a[]) {}
public static void main(String a []) {}

18

A JVM sempre irá procurar um método para começar a rodar


seu programa. Esse método deve estar presente na classe em que você
declarou quando executou o comando Java na linha de comandos, caso
isso não aconteça uma exceção será lançada.
Existem algumas maneiras de se declarar o método main.
Veja a lista abaixo:
public static void main(String[] args) {} //Recomendado
static public void main(String[] args) {}
public static void main(String[] a) {}
public static void main(String [] a) {}
public static void main(String a[]) {}
public static void main(String a []) {}

18
Método main
„ public class Test {
public static void main(String[] args) {
System.out.println("Meu nome é:
"+args[0]+args[1]);
}
}
„ c:\>java Test Java Spirit
„ c:\>java Test “Java Spirit”
//arg[0] <---> Java Spirit

19

Se você seguir todas as regras de arrays não terá dificuldades


com essas declarações. Mas qual é a finalidade de um array nesse método
e porque ele é assinado como static?
Respondendo a primeira questão. O array é utilizado para
receber parâmetros que são passados para o programa através de linha de
comando. Veja o exemplo abaixo:
public class Test {
public static void main(String[] args) {
System.out.println("Meu nome é: "+args[0]+args[1]);
}
}
c:\>java Test Java Spirit

19
Método main
„ Meu Nome é: Java Spirit.
„ O método é static para que ele seja carregado por um
programa a JVM chamado ClassLoader.
„ Nele estão todos os métodos e atributos que não tem e
não devem ter referência na pilha de memória.

20

Neste exemplo, estamos passando dois parâmetros para o


programa. O resultado impresso será: Meu Nome é: Java Spirit.
O método é static para que ele seja carregado por um
programa a JVM chamado ClassLoader. Nele estão todos os métodos e
atributos que não tem e não devem ter referência na pilha de memória.
Como nosso método é o primeiro que está na classe a ser chamada, é
claro, que não tem como ele ter uma referência na memória. Por isso ele é
assinado como static.

20
Javadoc - Documentação
„ Javadoc é um eficiente gerador de documentação para suas
classes
‹ Geração de documentos através de comentários inseridos no código
fonte
‹ Facilita verificar se cada método está de acordo com o que foi
especificado
‹ Permite o entendimento imediato do que cada método se propõe a
fazer, sem necessidade de verificar a implementação

21

Use javadoc à vontade. A documentação gerada permite entender


facilmente o comportamento de uma classe, seus atributos e métodos. Com a
documentação é possível também verificar se cada método está de acordo com
aquilo que foi especificado, facilitando o trabalho de checar os requisitos.

21
Javadoc - Documentação
„ Exemplo:

22

22
Javadoc - Documentação
„ Use corretamente os comentários Javadoc
‹ Os comentários para javadoc devem sempre aparecer imediatamente
acima do método, classe ou atributo a que se referem.
‹ Seja objetivo na primeira sentença da descrição. Ela será usada na
tabela de sumário gerada.
‹ No caso de sobrecarga de métodos, use a primeira sentença de modo
a deixar clara a diferença entre um método e outro.

23

23
Javadoc - Documentação
„ As tags Javadoc devem aparecer nesta ordem:
‹ @author (obrigatória em classes e interfaces)
‹ @version (obrigatória em classes e interfaces)
‹ @param
‹ @return
‹ @exception ou @throws
‹ @see
‹ @since
‹ @serial
‹ @deprecated

24

É importante lembrar a ordem em que as tags devem aparecer nos


comentários. Lembrando que nos comentários referentes ao cabeçalho de classe e
interfaces, as tags @author e @version são obrigatórias, as demais tags devem ser
usadas sempre que possível para garantir uma boa documentação e especificação
de cada classe.

24
Javadoc - Documentação
„ Quando usar @deprecated ?
‹ Usado para marcar classes e métodos que não devem mais ser
usados, mas que ainda são mantidos por motivos de compatibilidade
de versões.
‹ Use com sabedoria, sempre sirva os usuários da classe com
substitutos para permitir a migração do código para uma nova versão.
‹ Razões válidas para seu uso: existência de bugs, implementação
ineficiente, falta de segurança.

25

Quando for necessário, use a tag @deprecated para alertar os


usuários sobre os métodos que não devem mais ser utilizados, seja por questões
de segurança, ou porque você está provendo um método com implementação
melhor.

25
Best Practices Comuns
„ Evite concatenar Strings.
‹ Usando o operador + criam-se novos objetos em memória,
prejudicando a performance.
‹ Prefira usar StringBuffer.append no lugar de concatenar usando o
operador +.

26

InstanceOf faz uma comparação com um tipo específico de classe, e


com isso prendemos nossa implementação a este tipo de classe. Com excessão de
seu uso para implementar o método equals, isso deve ser evitado pois aumenta o
acoplamento entre as classes, dimuindo a flexibilidade do código. Procure utilizar
mais o polimorfismo, para garantir a flexibilidade e baixo acoplamento, aumentando
assim o reuso.
Outra má prática comum é concatenar Strings com o operador +.
Strings são imutáveis. Logo, quando se concatena uma String dessa forma, a JVM
na verdade está criando um novo objeto para obter esse resultado. Procure usar a
classe StringBuffer no seu lugar, pois ela é mutável e permite a concatenação
através do método append, sem ocasionar este tipo de desperdicio de recursos.

26
Best Practices Comuns
„ Atenção à portabilidade!
‹ Não confie sua lógica às prioridades de Threads, pois seu
funcionamento pode variar dependendo do sistema operacional.
‹ Evite usar métodos nativos.
‹ Sempre use layout managers quando montar uma GUI, pois
posicionamento absoluto difere de sistema para sistema.
‹ Use sempre Properties ou XML(DOM ou SAX) para definir ítens como
caminhos para arquivos, caracteres de quebra de linha, etc.

27

A prioridade das threads varia de acordo com o sistema operacional.


Com isso, é impossível garantir que a mesma implementação funcione com a
mesma eficiência em plataformas diferentes. O ideal é sincronizar suas threads
para ter o controle da situação e garantir o bom fluxo de sua lógica. Coisa
semelhante acontece com os layout managers. A implementação das GUI
dependem muito de detalhes do sistema operacional, assim sendo, evite usar
posicionamento absoluto, já que ele pode ser completamente diferente em outra
plataforma.
Outros detalhes que podem mudar de plataforma para plataforma são
caracteres de quebra de linha, forma de indicar o caminho de um arquivo, etc. Com
isso, para melhorar a portabilidade, utilize Properties para configurar estes ítens,
facilitando a adaptação a outras plataformas.

27
Best Practices Comuns
„ Use o método main para testes
‹ Mesmo que sua classe não necessite de um método main, você
pode usá-lo para fazer testes.
‹ Testes individuais ajudam a verificar se a classe está realmente se
comportando como o esperado.
‹ Após os testes, simplesmente mude seu escopo para private para
isolá-lo.
‹ Usar ferramentas de teste é uma ótima idéia. Ferramentas como o
JUnit ajudam muito no desenvolvimento e debug.

28

Use o método main para fazer testes de unidade com as suas


classes.
Assim é possível checar se os métodos da classe estão se
comportando como previsto. O ideal para isso é utilizar dados de teste que se saiba
quais devem ser os resultados.

28
Best Practices Comuns
„ Exemplo:

29

Usando novamente o exemplo do testDrive, implementamos o


método main para testar a classe.

29
Exercícios

30

Exercício:
1) Crie um programa que faça conversões implícitas e explícitas com os
tipos int e long, float e double.
2) Crie um programa que imprima os valores padrões de quatro atributos
com os tipos int e long, float e double.

30
Sumário
Nesta lição você aprendeu:
„ Quais as palavras-chaves

„ Os tipos-primitivos

„ As conversões permitidas

„ Sobre os literais inteiros, ponto flutuantes, booleanos e

caracteres
„ Quais os valores padrões

„ Características do método main

„ As melhores Best Practices.

31

31

Você também pode gostar