Locura com if in-line

Primeiro a situação que funciona:

[code]Boolean
lb;

int
ln1 = 1,
ln2 = 2;

lb = ln1 == ln2
? true
: null;[/code]

Segundo a situação que não funciona:

[code]Boolean
lb;

int
ln1 = 1,
ln2 = 2;

lb
= ln1 == 0
? false
: ln2 == 5
? true
: null
;[/code]

A segunda, ocorre NullPointerException. Alguem sabe me informar o motivo ?

Realmente intrigante, mas acho que deve ter algo a ver com o AutoBoxing.

Note que assim não dá erro:

[code] Boolean lb;

    int ln1 = 1, ln2 = 2;

    lb = ln1 == 0 ? Boolean.FALSE : ln2 == 5 ? Boolean.TRUE : null;[/code]

Só um comentário… isso não é um “if com inline”, mas o operador ternário.

Esse operador espera o mesmo tipo de dado de ambos os lados do :

Talvez esteja aí a solução do problema.

Já tinha encontrado essa situação:

[code]Boolean lb;

int ln1 = 1, ln2 = 2;

lb = ln1 == 0 ? Boolean.FALSE : ln2 == 5 ? Boolean.TRUE : null;[/code]

Porém estou utilizando o java 6 e não deveria necessitar o uso de Boolean.FALSE e Boolean.TRUE.

Seria isso bug do Java ?

Obs: Operador ternario é uma forma compacta de expressar o if e else, ou seja, o mesmo que if in-line… ou não ?

É que a palavra inline não é sinônimo para "curto". De qualquer forma, esse operador não é exatamente igual a um if, pq ele exige o retorno de um valor. Você não pode simplesmente fazer:

void x() {
}

void y() {
}

int a = 10;
a < 10 ? x() : y();

Que dá erro.

Claro.
Mas então, o que seria um if inline para você ?

Inline é um código que depois de compilado irá desaparecer. Para mim, um if inline seria analisado em tempo de compilação e só o resultado seria colocado no binário final.

Mas enfim, acho que estamos fugindo do ponto aqui. Ainda estou curioso para saber de onde vem esse NullPointerException. O que acontece é que com Boolean.TRUE e Boolean.FALSE o Java não fará auto-boxing, e por isso, o erro não ocorre.

Ainda assim, eu esperaria que o compilador fosse mais esperto que isso, ou será que meu chute está errado?

Poisé,
também achava que o compilador seria esperto o suficiente para identificar essa situação.

Hum…

O programa é equivalente a este aqui:

class TesteInline {
    public static void main(String[] args) {
        Boolean   lb;  
                           
        int   ln1 =   1,   ln2 =   2;  
        boolean t = (ln2 == 5 ? true : null); // aqui ocorre a NullPointerException, pois null não pode ser "unboxed" para true ou false

        lb = (ln1 ==  0 ? false : t); 
    }
}

Quando na verdade você acharia que ele seria equivalente a este aqui:

class TesteInline {
    public static void main(String[] args) {
        Boolean   lb;  
                           
        int   ln1 =   1,   ln2 =   2;  
        Boolean t = (ln2 == 5 ? true : null);

        lb = (ln1 ==  0 ? Boolean.FALSE : t); 
    }
}

Pensem mais um pouco. Dá a impressão que é algum lado obscuro das regras de “autoboxing” que interferem com a resolução de tipos no “?”. Pode até ser algum bug esquisito do compilador.

Achei muito bom isso!

Fiz um teste com String:

[code]String
ls;

int
ln1 = 1,
ln2 = 2;

ls
= ln1 == 0
? “false”
: ln2 == 5
? “true”
: null
;[/code]

Perfeito!

[quote=Matheus Leandro Ferreira]Achei muito bom isso!

Fiz um teste com String:

[code]String
ls;

int
ln1 = 1,
ln2 = 2;

ls
= ln1 == 0
? “false”
: ln2 == 5
? “true”
: null
;[/code]

Perfeito![/quote]

POG!

O problema é que não é possivel atribuir o valor null a tipos primitivos.

Eu não testei mas isso funciona com int, double, etc?

[quote=Mark_Ameba][quote=Matheus Leandro Ferreira]Achei muito bom isso!

Fiz um teste com String:

[code]String
ls;

int
ln1 = 1,
ln2 = 2;

ls
= ln1 == 0
? “false”
: ln2 == 5
? “true”
: null
;[/code]

Perfeito![/quote]

POG!

O problema é que não é possivel atribuir o valor null a tipos primitivos.

Eu não testei mas isso funciona com int, double, etc?[/quote]

Exato, mas o boolean que utilizei não era primitivo e sim Objeto. (podendo receber valor null)

só com o tipo Boolean da problema! mas o lance é separar as situações mesmo… bug loco no compilador.

Outro problema que encontrei foi esse… Comparando wrappers:

[code]Integer x = 120;
Integer y = 120;
System.out.println(x == y); // true

Integer w = -128;
Integer z = -128;
System.out.println(w == z); // true

Mas quando utilizo -129:

Integer g = -129;
Integer h = -129;
System.out.println(g ==h); // false[/code]

Obs: Quando você usa == para comparar, ele acaba comparando a referencia do objeto e utilizando o método equals() ele compara o valor.
Obs2: Fui atras disso… isso seria um foro na implementação do Flyweight Pattern ???

eu li algo a respeito disso, acho que tem a ver com o fato de 129 não caber em um byte… (caia até na certificação acho) vou dar uma procurada e depois posto aqui

Lembro de ver isso em tópicos bem antigos do GUJ. Mas lembro que após 128 o Integer já aloca um novo espaço. Não lembro direito. Tem que procurar mesmo.

http://www.guj.com.br/posts/list/120688.java diz qual é o limite (-128 a +127) que Integer.valueOf usa para retornar um novo objeto Integer, ou então usar um do cache.