Vraag Java: verschillende dubbele en dubbele in vergelijking


dat weet ik Double is een wrapper-klasse en wordt ingepakt double aantal. Vandaag heb ik een ander belangrijk verschil gezien:

double a = 1.0;
double b = 1.0;
Double c = 1.0;
Double d = 1.0;
System.out.println(a == b);  // true
System.out.println(c == d);  // false

Zo vreemd met mij !!!

Dus, als we gebruiken Double, elke keer moeten we zoiets doen:

private static final double delta = 0.0001;
System.out.println(Math.abs(c-d) < delta); 

Ik kan niet uitleggen waarom Double een directe vergelijking verkeerd maakt. Leg het alsjeblieft uit voor mij.

Bedankt :)


11
2017-09-01 09:58


oorsprong


antwoorden:


c en d zijn technisch twee verschillende objecten en == operator vergelijkt alleen referenties.

c.equals(d)

is beter omdat het waarden vergelijkt, niet verwijzingen. Maar nog steeds niet ideaal. Het direct vergelijken van drijvende-kommawaarden moet altijd rekening houden met een fout (epsilon) (Math.abs(c - d) < epsilon).

Let daar op:

Integer c = 1;
Integer d = 1;

hier zou vergelijking kunnen opbrengen true, maar dat is ingewikkelder (Integer interne caching, beschreven in JavaDoc van Integer.valueOf()):

Deze methode cacheert altijd waarden in het bereik -128 tot en met 127 en kan andere waarden buiten dit bereik cachen.

Waarom valueOf()? Omdat deze methode impliciet wordt gebruikt om autoboxing te implementeren:

Integer c = Integer.valueOf(1);
Integer d = Integer.valueOf(1);

Zie ook


23
2017-09-01 10:00



Wanneer toegepast op uitdrukkingen van een klassetype, == zullen altijd een referentievergelijking uitvoeren (JLS-sectie 15.21.3). Dus deze regel:

System.out.println(c == d); 

is het controleren of c en d refereer naar dezelfde objecten. Auto-boksen in Java maakt altijd (denk ik) een nieuw object voor float en double (de situatie is gecompliceerder voor integrale typen1). daarom c en d verwijzen naar verschillende objecten, en dus drukt het af false.

Als je wilt vergelijken voorwerpen voor gelijkheid, moet je bellen equals uitdrukkelijk:

System.out.println(c.equals(d));

Met double, het gebruikt in plaats daarvan numerieke gelijkheid - zoals aangegeven in sectie 15.21.1. Vandaar het verschil in gedrag.


1 Voor integrale autoboxing worden "kleine" waarden in de cache opgeslagen - dus autoboxing 5 (zeg) zal elke keer dezelfde verwijzing retourneren. De definitie van "klein" is implementatiespecifiek, maar is gegarandeerd binnen het bereik van -128 tot 127. Zie onderaan sectie 5.1.7 voor details.


4
2017-09-01 10:02



Gebruik equals() om de gelijkheid van 2 objecten te controleren. == controleert of de 2 referenties verwijzen naar hetzelfde object in het geheugen.


3
2017-09-01 10:00



Inhoudscontrole is alleen betrouwbaar voor == bij het controleren van primitieve types. Voor objecttypen is het altijd beter om de. Te gebruiken equals methode:

c.equals(d)

2
2017-09-01 10:02