Locura com if in-line

15 respostas
Matheus_Leandro_Ferr

Primeiro a situação que funciona:

Boolean
lb;
						
int
ln1	=	1,
ln2	=	2;
						
lb	=	ln1	==	ln2
		?	true
		:	null;

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

Boolean
lb;
						
int
ln1	=	1,
ln2	=	2;
					
lb
=	ln1	==	0
	?	false
	:	ln2	==	5
		?	true
		:	null
;

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

15 Respostas

ViniGodoy

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

Note que assim não dá erro:
Boolean lb;

        int ln1 = 1, ln2 = 2;

        lb = ln1 == 0 ? Boolean.FALSE : ln2 == 5 ? Boolean.TRUE : null;
ViniGodoy

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.

Matheus_Leandro_Ferr

Já tinha encontrado essa situação:

Boolean lb;

int ln1 = 1, ln2 = 2;

lb = ln1 == 0 ? Boolean.FALSE : ln2 == 5 ? Boolean.TRUE : null;

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 ?

ViniGodoy

É 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.

Matheus_Leandro_Ferr

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

ViniGodoy

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?

Matheus_Leandro_Ferr

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

T

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.

Matheus_Leandro_Ferr

Achei muito bom isso!

Fiz um teste com String:

String   
ls;   
	                               
int   
ln1 =   1,   
ln2 =   2;   
	                           
ls   
=   ln1 ==  0   
    ?   "false"   
    :   ln2 ==  5   
        ?   "true"   
        :   null   
;

Perfeito!

Marky.Vasconcelos
Matheus Leandro Ferreira:
Achei muito bom isso!

Fiz um teste com String:

String   
ls;   
	                               
int   
ln1 =   1,   
ln2 =   2;   
	                           
ls   
=   ln1 ==  0   
    ?   "false"   
    :   ln2 ==  5   
        ?   "true"   
        :   null   
;

Perfeito!

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?

Matheus_Leandro_Ferr
Mark_Ameba:
Matheus Leandro Ferreira:
Achei muito bom isso!

Fiz um teste com String:

String   
ls;   
	                               
int   
ln1 =   1,   
ln2 =   2;   
	                           
ls   
=   ln1 ==  0   
    ?   "false"   
    :   ln2 ==  5   
        ?   "true"   
        :   null   
;

Perfeito!

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?

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.

Matheus_Leandro_Ferr

Outro problema que encontrei foi esse.. Comparando wrappers:

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

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 ???

mario.fts

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

Marky.Vasconcelos

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.

T

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.

Criado 31 de março de 2009
Ultima resposta 1 de abr. de 2009
Respostas 15
Participantes 5