15 março 2009

SCJP - 03 - Overloading e Autoboxing

É, tem mais pegadinhas. Não fique pensando que ia se livrar fácil daquelas coisas, porque se dá pra complicar ainda mais, é isso que eles vão fazer. Conhece a Lei de Murphy?





Float f  = Float.parseFloat("3.14f");
Double d = f; //FAIL

Float f  = Float.parseFloat("3.14f");
Double d = (Double) f; //FAIL

Não vá achando que é possivel transformar um wrapper em outro. Isso não rola. Não há herança entre eles. Não é possivel fazer um cast entre eles. Dá merda. Tentar fazer isso na passagem por parâmetro então, nem se fala. Mas isso funciona:

Float f  = Float.parseFloat("3.14f");
Object o = (Float) f; //OWNED!

Porque E já que a gente começou a falar de passagem por parâmetro...

Widening: quando a gente transforma uma variável primitiva de um tipo "menos abrangente" para um "mais abrangente".
Boxing: quando a gente "encapsula" um literal em um wrapper.

public class Principal {
    public static void teste(Integer i) {
        System.out.println(
            "Integer");
    }

    public static void teste(long l) {
        System.out.println(
            "long");
    }

    public static void main(String[] args){
        int i = 10;
        teste(i);
    }
}

Quem ganha? Widening. O programa exibe:
long

public class Principal {
    public static void teste(int x, long y) {
        System.out.println(
            "int, long");
    }

    public static void teste(byte... z) {
        System.out.println(
            "byte...");
    }

    public static void main(String[] args){
        byte i = 10;
        teste(i,i);
    }
}

Quem ganha? Widening. O programa exibe:
int, long

public class Principal {
    public static void teste(Byte x, Byte y) {
        System.out.println(
            "Byte, Byte");
    }

    public static void teste(byte... z) {
        System.out.println(
            "byte...");
    }

    public static void main(String[] args){
        byte i = 10;
        teste(i,i);
    }
}

Quem ganha? Widening. O programa exibe:
Byte, Byte

Mas porque? Simples. Em ordem de "custo de implementação", o compilador prefere:
  • Widening
  • Autoboxing
  • Lista variável de parâmetros

Mais pegadinha. Isso compila?

public class Principal {
    public static void teste(Integer i) {
        System.out.println(
            "Integer");
    }


    public static void main(String[] args){
        byte i = 10;
        teste(i);
    }
}

NEGATIVO. Não é possivel fazer um box e um widening (ou vice versa). Quem diz isso é o compilador, então eu não tenho culpa de nada.


Creative Commons License
Esta obra está licenciada sob uma Licença Creative Commons.
Comentários
4 Comentários

4 comments:

Erick disse...

Comecei esse mes a estudar pra scjp e seu site vai me ajudar muito, muito interessante esses testes que vc fez. parabéns

Leonardo Ono disse...

Ola ! Acho que a parte do codigo abaixo nao funciona:

Object o = (Double) f; //OWNED!

Mas, acredito que poderiam ser:

Object o = f;
Object o = (double) f;

Unknown disse...

Olá Leonardo Ono...

De fato, não funciona. Foi um erro de digitação que eu já já vou corrigir :P Não funciona porque, como você sabe, as classes que encapsulam os tipos primitivos não fazem parte da mesma árvore de herança.

Leonardo Ono disse...

Oopa, era mais para tentar ajudar na correção mesmo. Estou estudando para a certificação e o seu material está me ajudando bastante. Parabéns pelo ótimo trabalho =) !

Postar um comentário

Regras são chatas, mas...

- Seu comentário precisa ter relação com o assunto do post;
- Em hipótese alguma faça propaganda de outros blogs ou sites;
- Não inclua links desnecessários no conteúdo do seu comentário;
- Se quiser deixar sua URL, comente usando a opção OpenID;
- CAIXA ALTA, miguxês ou erros de ortografia não serão tolerados;
- Ofensas pessoais, ameaças e xingamentos não são permitidos;