2017-10-02 2 views
5

Java 9 présente les méthodes requireNonNullElse et requireNonNullElseGet à la classe Objects. Sont-ils fonctionnellement différent aux Optional.ofNullable()orElse() et orElseGet() méthodes?Quelle est la différence entre Objects.requireNonNullElse() et Optional.ofNullable(). OrElse()?

String foo = null; 
Objects.requireNonNullElse(foo, "nonNull");//returns the string "nonNull" 
Optional.ofNullable(foo).orElse("nonNull");//also returns the string "nonNull" 

S'ils ont pas de différence fonctionnelle, pourquoi l'on a ajouté Objects maintenant?

Répondre

5

Il y a une petite différence dans leur comportement. Objects.requireNonNullElse() requiert que l'un des paramètres soit non nul, sinon un NullPointerException est levé.

String foo = null, bar = null; 
Optional.ofNullable(foo).orElse(bar);//returns a null value 
Objects.requireNonNullElse(foo, bar);//throws a NullPointerException 
+3

Il y a aussi la différence non fonctionnelle mineure que la 'la version Optional' génère des déchets * (sauf si JIT est assez intelligent pour optimiser cela) *. – Andreas

+3

@Andreas JMH signale qu'il n'y a pas de différence d'allocation entre 'Optional.ofNullable(). OrElse()' et 'Objects.requireNonNullElse()' – ZhekaKozlov

+0

@ZhekaKozlov Seulement si 'foo' est' null', auquel cas 'ofNullable() 'renvoie l'instance constante * vide *. Avez-vous essayé JMH avec un 'foo' non nul? Parce que j'ai pris la question comme demandant quelle est la différence fonctionnelle entre les deux pour * toute * valeur, pas seulement la valeur "null". – Andreas

3

La différence conceptuelle entre le choix d'un par rapport à l'autre est expliquée dans leur documentation. Il repose sur l'approche d'un consommateur API pour choisir lequel d'entre eux est censé être utilisé efficacement par eux.

Optional est un objet conteneur qui peut contenir ou non une valeur non nulle.

Une variable dont le type est Optional ne devrait jamais être lui-même null; doit toujours pointer vers une instance Optional.

C'est une classe basée sur la valeur; utilisation des opérations sensibles (identité y compris l'égalité de référence (==), le code de hachage d'identité ou synchronisation) sur les instances de option peut avoir imprévisibles résultats et doit être évitée.

  • ofNullable

    retourne un Optional avec une valeur actuelle si la valeur spécifiée est non nulle, sinon un vide Optional

  • orElse

    renvoie la valeur si elle est présente sinon, retourne d'autres.

où le comportement suivant:

String foo = null; 
=> Optional.ofNullable(foo).orElse("nonNull") 
=> Optional.ofNullable(null).orElse("nonNull") 
=> Optional.empty().orElse("nonNull") 
=> return otherwise "nonNull" 

même lorsqu'il traverse

String foo = null, bar = null; 
=> Optional.ofNullable(foo).orElse(bar); 
=> Optional.ofNullable(null).orElse(bar); 
=> Optional.empty().orElse(bar) 
=> return otherwise 'bar' 
=> returns null 

Objects est une classe se compose des méthodes utilitaires statiques pour faire fonctionner le objets, ou en vérifiant certaines conditions avant une opération.

Ces utilitaires comprennent des procédés null-ondes ou à haute null pour le calcul du code de hachage d'un objet répondant à une chaîne de caractères pour un objet , en comparant les deux objets et en vérifiant si des index ou des sous-gamme les valeurs sont en dehors des limites.

  • requireNonNullElse

    renvoie le premier argument si il est non nul et autrement le second argument si elle est non nulle

D'où la différence de comportement:

String foo = null; 
=> Objects.requireNonNullElse(foo, "nonNull") 
=> Objects.requireNonNullElse(null, "nonNull"); 

qui évalue plus interne si requireNonNull("nonNull", "defaultObj") puis

=> returns "nonNull" since its a non-null value 

maintenant qu'il traverse

String foo = null, bar = null; 
=> Objects.requireNonNullElse(foo, bar); 
=> Objects.requireNonNullElse(null, bar); 

Il vérifie en interne si requireNonNull(bar, "defaultObj") qui a ensuite

=> throws a NullPointerException 

Comme indiqué et

throws NullPointerException - si les deux obj est nullet defaultObj est null