[OCPJP6] 022 – Atribuições

Passar variáveis para métodos

Em Java quando você passa uma variável para um método, você estará passando uma cópia dos bits que representam esta variável (pass-by-value). Veja os diferentes comportamentos em variáveis primitivas e de referência (objeto).

Variáveis primitivas

Neste caso o que acontece dentro do escopo (método) “morre” lá, ou seja as alterações feitas sobre a variável primitiva serão perdidas. Veja o exemplo abaixo:

package certificacao;

public class Primitivo {
    private static int order = 0;
    public static void main(String[] args) {
        Primitivo p = new Primitivo();
        int w = 10;
        p.somar(w);
        System.out.println(
            (++order) + " Depois - somar(w): " + w);
    }
    public void somar(int w) {
        w = w + 10;
        System.out.println(
            (++order) + " Dentro - somar(w): " + w);
    }
}

Qual sera o resultado?

1 Dentro - somar(w): 20
2 Depois - somar(w): 10

Repare que o parâmetro “w” foi alterado apenas dentro do escopo (método). Exatamente o comportamento esperado – uma copia dos bits sem alterar a variável “w” criada no main.

Variáveis de referência (objeto)

Já no caso das variáveis de referencia (objeto), os valores do objeto podem ser alterados de acordo com o nível de acesso. Veja os exemplos:

public class ReferenciaMain {
    public static void main(String[] args) {
        ReferenciaObjeto obj = new ReferenciaObjeto();
        somar(obj, 100);
        System.out.println(
            "Depois - somar(obj, 100): " + obj.a);
        alterar(obj);
        System.out.println(
            "Depois - alterar(obj): " + obj.a);
    }
    static void somar(ReferenciaObjeto referencia, int param) {
        referencia.a = referencia.a + param;
    }
    static void alterar(ReferenciaObjeto referencia) {
        referencia.a = 555;
        referencia = new ReferenciaObjeto();
        referencia.a = 2222;
    }
}
class ReferenciaObjeto { int a = 1000; }

E qual seria o primeiro resultado?

1100 é a resposta correta já que um dos valores do objeto foi alterado.

E o segundo?

Essa é uma questão que confunde. A resposta correta é 555, porque o valor da variável foi alterada e em seguida a variável que era referenciada foi apontada para um novo objeto (new). Lembre que na passagem de parâmetro o objeto referenciado cria um link para o objeto e o perdera em uma nova instancia.

Um adicional (sem passagem de parâmetros)

public class Primitivo {
    public static void main(String[] args) {
        int a = 10;
        int b = a;
        a = 20;
        System.out.println("b depois de 'referenciar' a: " + b);
    }
}

E agora? b = 20 ?

No caso acima também será feito uma copia e o valor de “b” resultara em 10. Variáveis primitivas sempre serão copiadas e não referenciadas.

Comentem, estendam o assunto… Compartilhem =)

Anúncios

[OCPJP6] 021 – Atribuições

Cast de tipos primitivos

No post anterior vimos um exemplo de cast com tipo primitivo, vamos complementar o assunto. Veja algumas regras abaixo:

  • Toda soma de número inteiros resulta em int (como vimos no post anterior)
  • Todo número inteiro é implicitamente int. Tome cuidado com o tamanho, talvez seja necessário converter para um tipo maior – por exemplo long
  • Todo número flutuante é implicitamente um double
  • Não precisa de cast quando ocorre ampliação
  • É necessário cast quando houver perda de precisão

Exemplos

Cast para um tipo menor que float (float > int)

float f1 = 128.987f;
int i1 = (int) f1; // PERDA DE PRECISAO
// s1 = 128

Cast para um tipo menor que float (float > short)

float f1 = 128.987f;
short s1 = (short) f1; // PERDA DE PRECISAO
// s1 = 128

Cast para um tipo menor que float (float > byte)

float f1 = 128.987f;
byte b1 = (byte) f1;
// E agora? 128?

Um ponto de atenção no exemplo acima, byte vai de -128 até 127! Qual seria o resultado?

-128 será a resposta, porque a JVM irá remover os primeiros (esquerda) 24 bits, dando o resultado -128.

// Compare os resultados
Integer.toBinaryString((byte)128);
Integer.toBinaryString(-128);

Cast para um tipo maior que float (float > double)

float f1 = 128.545f;
// 32 bits cabe dentro de 64 (cast implicito)
double d1 = f1;
// d1 = 128.98699...
}

Adicional (pegadinhas de cast)

byte b1 = 128; // NÃO COMPILA, certo?

byte b2 = 3;
b2 += 7; // COMPILA :O

byte b3 = 3;
b3 = b3 + 7; // NÃO COMPILA (ahhhh)
b3 = (byte) (b3 + 7); // AGORA COMPILA

No exemplo acima b2 += inclui o cast implicito =D

Comentem, estendam o assunto… Compartilhem =)

[OCPJP6] 020 – Atribuições

Tipos primitivos

Veja a tabela abaixo:

Tipo Tamanho
byte 8 bit
short 16 bit
int 32 bit
long 64 bit
float 32 bit
double 64 bit
boolean
char 16 bit

 Todas expressões com tipos primitivos menor que int (char, byte, short) resultam em int.

Vamos entender melhor em exemplos:

byte

byte a = 1;
byte b = 2;
byte c = a + b; // NAO COMPILA!

short

short a = 1;
short b = 1;
short c = a + b + 1; // NAO COMPILA!
Por que o código acima não compila?

Como destacado anteriormente “toda expressão” (soma, subtração…) com tipos menores que int resultam em int, ou seja, no exemplo de com byte (a + b)  o resultado será um int e consequentemente no exemplo de short a mesma coisa.

E como fazer funcionar?

Transformando c em um int 🙂

byte a = 1;
byte b = 2;
int c = a + b; // =D
Mas e se mesmo assim eu quiser que c seja um byte ou short?

Cast resolve 🙂

byte a = 1;
byte b = 2;
byte c = (byte) (a + b); // =D

Comentem, estendam o assunto… Compartilhem =)