Dificuldade em entender o funcionamento do Double.NaN da classe Double

Oi, eu estou com alguma dificuldade em entender o funcionamento do Double.NaN da classe Double.

Eu tenho o seguinte exemplo:


public class MyClass {
	public static final String stb = "abc";
}


public class Teste {
	public static void main(String[] args) {
String str1 = MyClass.stb;
		String str2 = MyClass.stb;
		
		if(str1 == str1)
			System.out.println("STR1 == STR1");
		
		if(str1 == str2)
			System.out.println("STR1 == STR2");
		
		
		Double i1 = Double.NaN;
		Double i2 = Double.NaN;
		
		if(i1.equals(i2))
			System.out.println("i1.equals(i2)");
		
		if(i1 == i1)
			System.out.println("i1 == i1");
		
		if(i1 == i2)
			System.out.println("i1 == i2");
	}
}

Como resultado final, o output é:

STR1 == STR1
STR1 == STR2
i1.equals(i2)
i1 == i1

A minha pergunta é, porque é que o i1==i2 não aparece no output?

Porque são objetos diferentes, ou seja, estão em lugares diferentes na memória, o == ele avalia se os objetos estão no mesmo endereço de memória.

Então porque razão o STR1 == STR2 é posto no output e i1 == i2 não?

Aparentemente STR1 e STR2 estão no mesmo sítio da memória, mesmo tendo sido instanciado duas classes distintas.

Mas no caso i1 e i2, isso já não acontece. E Double.NaN é uma variável public static final.

Double.NaN é um double, e não um Double.

O culpado por esse resultado é o autoboxing do Java.

Double.NaN não é um objeto, mas um valor primitivo.
É um valor especial de double, que é semelhante ao NULL do SQL - um valor que "não representa um número".
Como você deve saber, o NULL no SQL quer dizer "não disponível" ou "não informado" ou "não sabido"; não quer dizer "vazio".
E é por isso que você não consegue comparar uma coluna com NULL usando "=" ou "<>", porque NULL nunca é igual a NULL, mas NULL também não é diferente de NULL. Estranho, não? No SQL você é obrigado a usar "IS NULL" ou "IS NOT NULL" porque a comparação "= NULL" retorna NULL e a comparação "<> NULL" também retorna NULL.
Da mesma maneira, em Java e outras linguagens que aceitam o valor especial Not-A-Number, nada é igual a NaN, mesmo o NaN.

Veja que NaN é um número tão esquisito que ele é diferente dele mesmo.

class TesteNaN {
    public static void main(String[] args) {
        double d = Double.NaN; // Um Não-É-Um-Número
        System.out.println (Double.isNaN(d)); // true
        System.out.println (d == d); // false
        System.out.println (d != d); // true
        d = Math.PI; // um número normal
        System.out.println (Double.isNaN(d)); // false
        System.out.println (d == d); // true
        System.out.println (d != d); // false
    }
}

Eu sei que é um número esquisito. Por isso pergunto porque razão o número é esquisito e porque razão comporta-se de uma maneira estranha?

Esqueçam a pergunta. Já vi num post acima. A razão é o autoboxing.

É um “não-número” realmente esquisito; para maiores detalhes, leia este artigo na Wikipedia.

(Acho que é mais fácil entender o +Infinity ou o -Infinity, que são realmente números. Mas uma coisa que é um “não-número” é estranha, porque não ensinam isso nas aulas de matemática, só em cálculo numérico. Por isso é que eu comparei com o SQL, onde existe o NULL que tem um comportamento parecido com o NaN.)

Não, o thingol está certo, eu errei. Gomen.

O jeito mais fácil de explicar isso é dizer que eles são números indeterminados. Operações de comparação só existem em numeros que se sabe o valor.

Mas o Bruno também tem razão; é que tem mistura de AutoBoxing com NaN e eu nem me preocupei com o Autoboxing. Que questão zoada