Atribuindo variáveis: Widening, Narrowing e Boxing(2)

 
 

 
 

 
 

 
 

Operações com variáveis:

 
 

  • O tipo do resultado da soma de duas variáveis ou literais (constante em tempo de compilação) sempre resultará no tipo do maior operando. Erro comum: Possible Loss of Precision

     
     

    Testes com variáveis

    short s = 7;

    long l = 8;

    int i = s + l;
    // resulta em long

     
     

    int i1 = 1000;

    int i2 = 2000;

    long l5 = i1 + i2;

    // ou

    long l6 = 1000 + 2000;

     
     

    float f1 = 4F;

    float f2 = 5F;

    double d1 = f1 + f2;

    // ou

    double d1 = 4F + 5F;

     
     

    byte b1 = 1, b2 = 2;

    double d = b1 + b2; // ok – um int cabe dentro de um double

    float f = b1 + b2; // ok – um int cabe dentro de um float

    long l = b1 + b2; // ok – um int cabe dentro de um long

    int i = b1 + b2; // ok – um int cabe dentro de um int

     
     

    byte b1 = 1; long l1 = 1;

    double d = b1 + l1; // um long cabe dentro de um double

    float f = b1 + l1; // um long cabe dentro de um float

    long l = b1 + l1; // um long cabe dentro de um long

    int i = b1 + l1;
    // um long não cabe dentro de um int

    Teste.java:9: possible loss of precision

    int i = b1 + l1;

    required: int


    found: long

     
     

     
     

    Testes com literais

    int i = 1L+ 1; // não compila pois o resultado da soma dos literais é do tipo long. O resultado sempre será do tipo maior.

     
     

    float f = 1.75F + 7.25D;
    // não compila pois o resultado é um double

     
     

    long l1 = 2L + 34.4F;        // não compila pois o resultado é um float que não cabe em um long

    long l2 = 2L + 34.4D; // não compila pois o resultado é um double que não cabe em um long

     
     

    float f1 = 2L + 34.4F; // ok – o resultado é um float

    double d1 = 2L + 34.4D; // ok – o resultado é um double

     
     

  • Boxing (regra: Box than Widening)

     
     

    Long l7 = 7+7; // Não compila pois 7 + 7 gera um resultado inteiro que não pode ser autoboxed para Long.

     
     

    int i1 = 1;

    int i2 = 2;

    Long l = (long)(i2 + i1);

    Long l = (Long)(i2 + i1); // ERRO: o resultado, que é um int não pode ser boxed em Long.        

     
     

    //No caso abaixo já compila pois como um operando é do tipo long o resultado será um tipo long que poderá ser boxed para Long.

    Long l = 7L + 7;

     
     

    Number n1 = 34; // box to Integer than Widen to Number

    Number n2 = 34L; // box to Long than Widen to Number

    Number n3 = 34F; // box to Float than Widen to Number

    Number n4 = 34D; // box to Double than Widen to Number

     

     

  • O tipo do resultado com operações sempre será de um tipo nativo (mesmo que ambos os operandos sejam de tipos de referência)

     
     

     
     

    int i1 = 1;

    Long Lng = 1L; // a variável de referência é unboxed para realizar a operação

    int i2 = i1 + Lng; // o resultado é um long – nativo

    Teste.java:8: possible loss of precision

    int i2 = i1 + Lng;

    required: int

    found: long

     
     

     
     

     
     

    Float f = 5F;

    Double d = 5D;

    Float f2 = f + d;
    // o resultado é um double – nativo

    Teste.java:7: incompatible types

    Float f2 = f + d;

    required: Float

    found: double

     
     

    → quando fazemdos f + d, provavelmente o compilador faz:

    float f1 = f.floatValue() // floatValue() retorna o tipo primitivo float

    double d1 = d.doubleValue() // doubleValue() retorna o tipo primitivo double

    f1 + d1 (resulta em um tipo double)

     
     

     
     

  • Para o compilador a soma de dois literais inteiros (ou constantes em tempo de compilação) é diferente do que a soma de duas variáveis inteiras

     
     

    Se a operação consistir na soma de duas variáveis inteiras (seja: byte, short, int) o resultado sempre será do tipo int.

    byte b1 = 7;

    byte b2 = 12;

    byte b3 = b1 – b2; /*ou*/ byte b4 = b2 + b2;
    // não compila pois tem que ser explicitamente convertido

    // o que ocorre acima é que ambas as operações podem “estourar” a capacidade da variável declarada “byte b3 e byte b4”

    Teste.java:8: possible loss of precision

    byte b3 = b1 – b2;

    required: byte

    found: int

     
     

     
     

    byte b3 = (byte) (b1 – b2); // aqui convertemos o resultado que é do tipo ‘int’ para o tipo ‘byte’

     
     

    short s1 = 10, s2 = 20, s3 = s1 + s2;
    // idem acima: também não compila pois tem que ser explicitamente convertido. (s1 + s2 é um int)

     
     

    short s1 = 10, s2 = 20, s3 = (short) (s1 + s2); // compila (foi realizada a devida conversão)

     
     

    O tipo do resultado da soma de dois literais (ou constantes em tempo de compilação) inteiros poderá ser (narrow than box) contanto que caiba na variável de destino.

     
     

    // No caso abaixo o resultado que é um int é ‘narrowed’ para byte para poder caber na variável b. (os literais 7 e 12 são constantes em tempo de compilação)

    byte b = 7 + 12; // compila (narrow o resultado int ’19’ para byte)

    Short sh = 7+7; // compila (narrow o resultado int ’14’ para short than box short para Short)

    short sh = 7+7; // compila (narrow o resultado int ’14’ para short)

    Short sh = 64000 + 1000;
    // não compila pois o resultado que é um ‘int’ estoura a capacidade de ser um short

     
     

    final short s1 = 10, s2 = 20, s3 = s1 + s2; // compila (os argumentos s1 e s2 foram declarados como ‘final’ e, portanto são considerados como Literais ou constantes em tempo de compilação para o compilador.)

     
     

 
 

 
 

 
 

 
 

 
 

Para chamada à métodos

 
 

Tipos nativos:

 
 

Em passagem de parâmetros nunca ocorre o narrow para um tipo inteiro:

 
 

public class Teste {

public static void main(String[] args){

calc(1); // o tipo ‘1’ é um inteiro e não será narrowed to byte ou short.

}

public static void calc(byte b){print(“b”);}

public static void calc(short s){print(“s”);}

 
 

public static void print(String s){

System.out.println(s);

}

}

javac:

Teste.java:5: cannot find symbol

calc(1);

^

symbol: method calc(int)

location: class Teste

1 error

 
 

Abaixo demonstramos o que representam os literais por padrão:

 
 

public class Teste {

public static void main(String[] args){

calc(1);

calc(2.0);        

}

public static void calc(byte b){print(“b”);}

public static void calc(short s){print(“s”);}

public static void calc(long l){print(“l”);}

public static void calc(float f){print(“f”);}

public static void calc(double d){print(“d”);}

 
 

public static void print(String s){

System.out.println(s);

}

}

Output

l // – o tipo int ‘1’ cabe dentro de um long.

d // – o tipo ‘2.0’ por padrão é um double

Podemos perceber que um tipo inteiro nativo, vai sendo promovido a tipos mais largos conforme a necessidade:

 
 

// tipo int sendo promovido a long

public class Teste {

public static void main(String[] args){

calc(1);

}

public static void calc(byte b){print(“b”);}

public static void calc(short s){print(“s”);}

public static void calc(long l){print(“l”);}

public static void calc(float f){print(“f”);}

public static void calc(double d){print(“d”);}

 
 

public static void print(String s){

System.out.println(s);

}

}

Output:

l // – o tipo int ‘1’ cabe dentro de um long e foi promovido

 
 

 
 

// tipo int sendo promovido a float

public class Teste {

public static void main(String[] args){

calc(1);

}

public static void calc(byte b){print(“b”);}

public static void calc(short s){print(“s”);}

public static void calc(float f){print(“f”);}

public static void calc(double d){print(“d”);}

 
 

 
 

public static void print(String s){

System.out.println(s);

}

}

Output:

f // – o tipo int ‘1’ cabe dentro de um float então foi promovido

 
 

 
 

// tipo int sendo promovido a double

public class Teste {

public static void main(String[] args){

calc(1);

}

public static void calc(byte b){print(“b”);}

public static void calc(short s){print(“s”);}

public static void calc(double d){print(“d”);}

 
 

 
 

public static void print(String s){

System.out.println(s);

}

}

Output:

d // – o tipo int ‘1’ cabe dentro de um double então foi promovido

 
 

 
 

Tipos de referência:

 
 

No teste abaixo ao passar os literais como parâmetro das funções ocorre o processo de Boxing:

 
 

public class Teste {

public static void main(String[] args){

calc(1); // é um inteiro

calc(1L); // é um long

calc(2.0F); // é um float

calc(2.0); // é um double

 
 

}

public static void calc(Byte b){print(“b”);}

public static void calc(Short s){print(“s”);}

public static void calc(Integer i){print(“i”);}

public static void calc(Long l){print(“l”);}

public static void calc(Float f){print(“f”);}

public static void calc(Double d){print(“d”);}

public static void calc(Number n){print(“n”);} // serviria para Box than Widening

 
 

public static void print(String s){

System.out.println(s);

}

}

 
 

Output:

i // – Boxing to integer

l // – Boxing to long

f // – Boxing to float

d // – Boxing to double

Poderiamos escrever um método genérico de forma que ocorresse nesta ordem: Boxing then Widening:

 
 

public class Teste {

public static void main(String[] args){

calc(1); // é um inteiro

calc(1L); // é um long

calc(2.0F); // é um float

calc(2.0); // é um double

 
 

}

 
 

public static void calc(Number n){print(“n”);} // serviria para Box than Widening

 
 

public static void print(String s){

System.out.println(s);

}

}

Output:

n // Boxing int ‘1’ to Integer than Widening to Number

n // Boxing long ‘1L’ to Long than Widening to Number

n // Boxing float ‘2.0F’ to Float than Widening to Number

n // Boxing double ‘2.0’ to Double than Widening to Number

 
 

Esta entrada foi publicada em Java com as etiquetas . ligação permanente.

Deixe uma Resposta

Preencha os seus detalhes abaixo ou clique num ícone para iniciar sessão:

Logótipo da WordPress.com

Está a comentar usando a sua conta WordPress.com Terminar Sessão / Alterar )

Imagem do Twitter

Está a comentar usando a sua conta Twitter Terminar Sessão / Alterar )

Facebook photo

Está a comentar usando a sua conta Facebook Terminar Sessão / Alterar )

Google+ photo

Está a comentar usando a sua conta Google+ Terminar Sessão / Alterar )

Connecting to %s