web-dev-qa-db-fra.com

Vérification d'une chaîne non nulle et non vide en Java

J'essaie de vérifier si une chaîne Java n'est pas null, ni vide ni espace. 

Dans mon esprit, 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:

Retourne une copie de la chaîne, en omettant les espaces de début et de fin.

Si cet objet String représente une séquence de caractères vide ou si les premier et dernier caractères de la séquence de caractères représentée par cet objet String ont tous deux un code supérieur à '\u0020' (le caractère espace), une référence à cet objet String est renvoyée. 

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 conformément à Java. Un caractère est un caractère d'espacement Java si et seulement si il répond à l'un des critères suivants:

  • Il s'agit d'un caractère d'espace Unicode (SPACE_SEPARATOR, LINE_SEPARATOR ou PARAGRAPH_SEPARATOR), mais il ne s'agit pas également d'un espace insécable ('\u00A0', '\u2007', '\u202F').
  • Il s'agit de '\t', U + 0009 TABULATION HORIZONTALE.
  • C'est '\n', U + 000A LINE FEED.
  • C'est '\u000B', U + 000B TABULATION VERTICALE.
  • C'est '\f', U + 000C FORM FEED.
  • Il s'agit de '\r', U + 000D CARRIAGE RETURN.
  • Il s'agit de '\u001C', U + 001C SEPARATOR FILE.
  • C'est '\u001D', U + 001D GROUP SEPARATOR.
  • C'est '\u001E', U + 001E RECORD SEPARATOR.
  • C'est '\u001F', U + 001F UNIT SEPARATOR.

Si je ne me trompe pas - ou peut-être je ne le lis pas correctement - la String.trim() devrait supprimer tous les caractères vérifiés par Character.isWhiteSpace(). Tous voient au-dessus de '\u0020'

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

  1. Existe-t-il une chaîne qui fera que isEmpty et isBlank se comportent différemment dans un scénario de test?
  2. En supposant qu'il n'y en ait pas, y a-t-il une autre considération à cause de laquelle je devrais choisir isBlank et ne pas utiliser isEmpty?

Pour les personnes intéressées par l'exécution d'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: La discussion a été très intéressante - et c’est la raison pour laquelle j’adore Stack Overflow et les gens d’ici. En passant, pour revenir à la question, nous avons eu:

  • Un programme montrant quels personnages vont se comporter différemment. Le code est à https://ideone.com/ELY5Wv . Merci @Dukeling. 
  • Une raison liée aux performances pour choisir la isBlank() standard. Merci @devconsole. 
  • Une explication complète de @nhahtdh. Merci mon pote. 
61
partha

Existe-t-il une chaîne qui fera que isEmpty et isBlank se comportent différemment dans un scénario de test?

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

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

  • Il s'agit d'un caractère d'espace Unicode (SPACE_SEPARATOR, LINE_SEPARATOR ou PARAGRAPH_SEPARATOR), mais il ne s'agit pas également d'un espace insécable ('\u00A0', '\u2007', '\u202F').

  • [...]

De même, la méthode trim() supprime tous les caractères de contrôle dont les points de code sont inférieurs à U + 0020 et le caractère d'espacement (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 lorsque la chaîne contient des caractères de contrôle qui ne sont pas considérés comme des espaces par la méthode Character.isWhitespace. Par exemple: "\002".

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

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

(Les méthodes isEmpty() et isBlank() autorisent toutes deux la référence null String. Elle n'est donc pas exactement équivalente à la solution regex, mais elle est équivalente, à part ça).

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 la méthode Character.isWhitespace.

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

Ça dépend. Cependant, je pense que l'explication dans la partie ci-dessus devrait être suffisante pour que vous décidiez. 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ôle1 en dessous de U + 0020 et du 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 la méthode Character.isWhitespace, qui inclut des caractères d'espacement Unicode.

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

32
nhahtdh

Les deux méthodes standard ont pour objet de distinguer ces deux cas: 

org.Apache.common.lang.StringUtils.isBlank(" ") (retournera true).

org.Apache.common.lang.StringUtils.isEmpty(" ") (retournera false).

Votre implémentation personnalisée de isEmpty() renverra true.


METTRE À JOUR:

  • org.Apache.common.lang.StringUtils.isEmpty() est utilisé pour rechercher si la chaîne a une longueur de 0 ou une valeur 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 une valeur nulle, mais également s'il s'agit uniquement d'une chaîne d'espaces.

Dans votre cas, vous coupez la chaîne dans la méthode votreisEmpty. La seule différence qui peut se produire maintenant ne peut pas se produire (le cas où vous lui donnez " ") car vous êtes rognage it (supprimer le blanc final - ce qui revient à supprimer tous les espaces).

25
Maroun

Je choisirais isBlank() à isEmpty() car trim() crée un nouvel objet String qui doit être nettoyé ultérieurement. isBlank(), d'autre part, ne crée aucun objet.

14
devconsole

Vous pouvez jeter un oeil à JSR 303 Bean Validtion qui contient les annotatinos @NotEmpty et @NotNull. Bean Validation est cool parce que vous pouvez séparer les problèmes de validation de l'intention initiale de la méthode. 

4
Lukas Eichler

Pourquoi ne pouvez-vous pas simplement utiliser un opérateur ternaire imbriqué pour y parvenir? Consultez le code exemple public static void main(String[] args) { String s = null; String s1=""; String s2="hello"; System.out.println(" 1 "+check(s)); System.out.println(" 2 "+check(s1)); System.out.println(" 3 "+check(s2)); } public static boolean check(String data) { return (data==null?false:(data.isEmpty()?false:true)); }

et la sortie est comme suit 

1 faux 2 faux 3 vrai

ici, le premier 2 scénarios renvoie faux (c'est-à-dire nul et vide) et le troisième scénario renvoie vrai

1
Ancel Litto
<% 
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}
<%} %>
0
arjunsekar1991

Ce code simple fera assez:

public static boolean isNullOrEmpty(String str) {
    return str == null || str.trim().equals("");
}

Et les tests unitaires:

@Test
public void testIsNullOrEmpty() {
    assertEquals(true, AcdsUtils.isNullOrEmpty(""));
    assertEquals(true, AcdsUtils.isNullOrEmpty((String) null));
    assertEquals(false, AcdsUtils.isNullOrEmpty("lol    "));
    assertEquals(false, AcdsUtils.isNullOrEmpty("HallO"));
}
0
Laurent

Avec Java 8, vous pouvez également utiliser la fonctionnalité Facultatif avec le filtrage. Pour vérifier si une chaîne est vide, le code est purement Java SE sans bibliothèque supplémentaire . Le code suivant illustre une implémentation isBlank ().

Comportement String.trim ()

!Optional.ofNullable(tocheck).filter(e -> e != null && e.trim().length() > 0).isPresent()

Comportement StringUtils.isBlank ()

Optional.ofNullable(toCheck)
    .filter(e -> 
        {
            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;

        })
    .isPresent()
0
Nicolas Henneaux