62 votes

Vérification d'une chaîne de caractères non nulle et non vide en Java

J'essaie de vérifier si une chaîne de caractères Java n'est pas null pas vide et pas un espace blanc.

À mon avis, ce code aurait dû être tout à fait à la hauteur de la tâche.

public static boolean isEmpty(String s) {
    if ((s != null) && (s.trim().length() > 0))
        return false;
    else
        return true;
}

Selon la documentation, String.trim() devrait fonctionner ainsi :

Renvoie une copie de la chaîne de caractères, en omettant les espaces en tête et en fin de chaîne.

Si cela String représente une séquence de caractères vide, ou les premier et dernier caractères de la séquence de caractères représentée par l'objet String Les deux objets ont des codes supérieurs à '\u0020' (le caractère espace), puis une référence à cette String est renvoyé.

Cependant, apache/commons/lang/StringUtils.java le fait un peu différemment.

public static boolean isBlank(String str) {
    int strLen;
    if (str == null || (strLen = str.length()) == 0) {
        return true;
    }
    for (int i = 0; i < strLen; i++) {
        if ((Character.isWhitespace(str.charAt(i)) == false)) {
            return false;
        }
    }
    return true;
}

Selon la documentation, Character.isWhitespace() :

Détermine si le caractère spécifié est un espace blanc selon Java. Un caractère est un caractère d'espace blanc Java si et seulement s'il répond à l'un des critères suivants :

  • Il s'agit d'un caractère d'espacement Unicode ( SPACE_SEPARATOR , LINE_SEPARATOR ou PARAGRAPH_SEPARATOR ) mais n'est pas également un espace non cassant ( '\u00A0' , '\u2007' , '\u202F' ).
  • Il est '\t' , U+0009 TABULATION HORIZONTALE.
  • Il est '\n' , U+000A SAUT DE LIGNE.
  • Il est '\u000B' , U+000B TABULATION VERTICALE.
  • Il est '\f' , U+000C FORM FEED.
  • Il est '\r' , U+000D RETOUR CHARIOT.
  • Il est '\u001C' , U+001C SÉPARATEUR DE FICHIERS.
  • Il est '\u001D' , U+001D SÉPARATEUR DE GROUPES.
  • Il est '\u001E' , U+001E SÉPARATEUR D'ENREGISTREMENTS.
  • Il est '\u001F' , U+001F SÉPARATEUR D'UNITÉS.

Si je ne me trompe pas - ou si je ne l'ai pas lu correctement - l'objectif de l'UE est d'améliorer la qualité de vie des citoyens. String.trim() devrait enlever tous les caractères qui sont vérifiés par Character.isWhiteSpace() . Tous voient qu'ils sont au-dessus de '\u0020' .

Dans ce cas, le plus simple isEmpty semble couvrir tous les scénarios que la fonction plus longue isBlank couvre.

  1. Existe-t-il une chaîne de caractères qui rendra le isEmpty et isBlank se comporte-t-il différemment dans un cas d'essai ?
  2. En supposant qu'il n'y en ait pas, y a-t-il une autre considération pour laquelle je devrais choisir isBlank et ne pas utiliser isEmpty ?

Pour ceux qui souhaitent exécuter un test, voici les méthodes et les tests unitaires.

public class StringUtil {

    public static boolean isEmpty(String s) {
        if ((s != null) && (s.trim().length() > 0))
            return false;
        else
            return true;
    }

    public static boolean isBlank(String str) {
        int strLen;
        if (str == null || (strLen = str.length()) == 0) {
            return true;
        }
        for (int i = 0; i < strLen; i++) {
            if ((Character.isWhitespace(str.charAt(i)) == false)) {
                return false;
            }
        }
        return true;
    }
}

Et des tests unitaires

@Test
public void test() {

    String s = null; 
    assertTrue(StringUtil.isEmpty(s)) ;
    assertTrue(StringUtil.isBlank(s)) ;

    s = ""; 
    assertTrue(StringUtil.isEmpty(s)) ;
    assertTrue(StringUtil.isBlank(s)); 

    s = " "; 
    assertTrue(StringUtil.isEmpty(s)) ;
    assertTrue(StringUtil.isBlank(s)) ;

    s = "   "; 
    assertTrue(StringUtil.isEmpty(s)) ;
    assertTrue(StringUtil.isBlank(s)) ;

    s = "   a     "; 
    assertTrue(StringUtil.isEmpty(s)==false) ;    
    assertTrue(StringUtil.isBlank(s)==false) ;       

}

Mise à jour : C'était une discussion vraiment intéressante - et c'est pourquoi j'aime Stack Overflow et les gens ici. Au fait, pour en revenir à la question, nous avons obtenu :

  • Un programme montrant que tous les caractères font se comporter différemment. Le code est à https://ideone.com/ELY5Wv . Merci @Dukeling.
  • Une raison liée à la performance pour choisir la norme isBlank() . Merci @devconsole.
  • Une explication complète par @nhahtdh. Merci mon pote.

32voto

nhahtdh Points 28167

Existe-t-il une chaîne de caractères qui rendra le isEmpty et isBlank se comporte-t-il différemment dans un cas d'essai ?

Notez que Character.isWhitespace peut reconnaître les caractères Unicode et renvoyer true pour les caractères d'espacement Unicode.

Détermine si le caractère spécifié est un espace blanc selon Java. Un caractère est un caractère d'espace blanc Java si et seulement s'il répond à l'un des critères suivants :

  • Il s'agit d'un caractère d'espacement Unicode ( SPACE_SEPARATOR , LINE_SEPARATOR ou PARAGRAPH_SEPARATOR ) mais n'est pas également un espace non cassant ( '\u00A0' , '\u2007' , '\u202F' ).

  • [...]

D'un autre côté, trim() couperait tous les caractères de contrôle dont les points de code sont inférieurs à U+0020 et le caractère espace (U+0020).

Par conséquent, les deux méthodes se comporteraient différemment en présence d'un caractère d'espacement Unicode. Par exemple : "\u2008" . Ou quand la chaîne de caractères contient des caractères de contrôle qui ne sont pas considérés comme des espaces blancs par Character.isWhitespace méthode. Par exemple : "\002" .

Si vous deviez écrire une expression régulière pour faire cela (ce qui est plus lent que de faire une boucle dans la chaîne et de la vérifier) :

  • isEmpty() serait équivalent à .matches("[\\x00-\\x20]*")
  • isBlank() serait équivalent à .matches("\\p{javaWhitespace}*")

(Le isEmpty() et isBlank() permettent toutes deux null String reference, donc ce n'est pas exactement équivalent à la solution regex, mais en mettant cela de côté, c'est équivalent).

Notez que \p{javaWhitespace} comme son nom l'indique, est une syntaxe spécifique à Java pour accéder à la classe de caractères définie par Character.isWhitespace méthode.

En supposant qu'il n'y en ait pas, y a-t-il une autre considération pour laquelle je devrais choisir isBlank et ne pas utiliser isEmpty ?

Cela dépend. Cependant, je pense que l'explication dans la partie ci-dessus devrait être suffisante pour que vous puissiez décider. Pour résumer la différence :

  • isEmpty() considèrera que la chaîne est vide si elle ne contient que des caractères de contrôle. 1 en dessous de U+0020 et le caractère espace (U+0020)

  • isBlank considérera que la chaîne est vide si elle ne contient que des caractères d'espacement tels que définis par Character.isWhitespace qui inclut les caractères d'espacement Unicode.

1 Il y a aussi le caractère de contrôle à U+007F DELETE qui n'est pas réduit par trim() méthode.

25voto

Maroun Maroun Points 31217

L'objectif des deux standard est de faire la distinction entre ces deux cas :

org.apache.common.lang.StringUtils.isBlank(" ") (retournera vrai ).

org.apache.common.lang.StringUtils.isEmpty(" ") (retournera faux ).

Votre mise en œuvre personnalisée de isEmpty() retournera vrai .


UPDATE :

  • org.apache.common.lang.StringUtils.isEmpty() est utilisé pour déterminer si la chaîne a une longueur de 0 ou si elle est nulle.

  • org.apache.common.lang.StringUtils.isBlank() fait un pas en avant. Il vérifie non seulement si la chaîne a une longueur de 0 ou est nulle, mais aussi s'il s'agit uniquement d'une chaîne d'espacement.

Dans votre cas, vous coupez la chaîne en votre isEmpty méthode. La seule différence qui peut se produire maintenant ne peut pas se produire (le cas que vous lui donnez " " ) parce que vous êtes taillage (En supprimant l'espace blanc de fin de ligne - ce qui dans ce cas revient à supprimer tous espaces).

14voto

devconsole Points 3027

Je choisirais isBlank() sur isEmpty() parce que trim() crée un nouvel objet String qui devra être ramassé plus tard. isBlank() en revanche, ne crée aucun objet.

4voto

Templar Points 1915

Vous pouvez consulter la JSR 303 Bean Validtion qui contient les annotations. @NotEmpty et @NotNull . Bean Validation est intéressant car il permet de séparer les questions de validation de l'intention initiale de la méthode.

0voto

arjunsekar1991 Points 1
<% 
System.out.println(request.getParameter("userName")+"*");

if (request.getParameter("userName").trim().length() == 0 | request.getParameter("userName") == null) { %>
<jsp:forward page="HandleIt.jsp" />
<% }
 else { %>
Hello ${param.userName}
<%} %>

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X