2016-04-13 2 views
3

Donc, j'ai vu cette ligne de code:Avantages ou utilisations de la fonction Boolean.booleanValue sur Java?

Boolean variable = false; 
/* ..stuff.. */ 
if(variable.booleanValue() == false) { 
/* ..more stuff..*/ 
} 

Et je l'ai fait, dans un endroit différent:

Boolean variable = false; 
/* ..my stuff..*/ 
if(!variable) { 
/* ..more of my stuff..*/ 
} 

La question est: Quelle est la différence/avantages de la premier extrait de code sur le premier?

La version longue est: Étant donné que je peux utiliser la variable booléenne comme une primitive (booléenne), quel est le point sur faire variable.booleanValue() et même le comparer à une valeur booléenne? Cela ne présente-t-il pas aussi le risque (sur le code impossible, mais bon) d'une exception de pointeur nul si la variable n'est pas initialisée?

Dans quel cas est-il recommandé d'utiliser variable.booleanValue juste au-dessus de "variable"?

+0

Le risque de l'exception de pointeur nul est également présent dans le deuxième fragment - seulement masqué, donc on peut considérer qu'il vaut encore la peine. Mon goût est pour la seconde, cependant. Je n'aime pas comparer les valeurs booléennes avec '== true' ou' == false'. Et non, je ne peux pas penser à un exemple où je voudrais appeler 'booleanValue()' explicitement. –

+0

Comme mentionné - vos états ici utilisent la boxe/unboxing. De manière réaliste, c'est la même chose que Boolean val = Boolean.FALSE (ou TRUE), qui peut être déconnecté à un état primitif de vrai/faux en utilisant le qui est le même que d'appeler le .booleanValue() sur l'objet - Big Boolean est utile si vous voulez dire à tout à fait dans les boutons radio de l'application web - Null, True/False il y en a beaucoup d'autres mais c'est le principal pour lequel nous l'utilisons. – VeenarM

Répondre

4

Il n'y a pas de différence entre le comportement des deux extraits.

JLS 5.1.8:

Au moment de l'exécution, le produit de conversion unboxing comme suit:

Si r est une référence de type booléen, puis la conversion unboxing convertit r en r.booleanValue()

Alors if (variable) {...} s'exécutera sous la forme if (variable.booleanValue()) {...}. Et parce qu'ils sont complètement équivalents, ils sont tous deux également sensibles à NPE si variable == null.

Cela signifie qu'un avantage mineur possible de l'appel explicite à booleanValue() est que vous pouvez voir instantanément que variable est en cours d'déréférencé, alors qu'avec variable == false il est un peu moins évidente.

Si vous ajoutez == false ou une négation est une question de goût, je préfère éviter d'utiliser l'opérateur == pour comparer une expression booléenne true ou false.

Mais je pense qu'il est plus important d'éviter complètement Boolean et d'utiliser le type primitif lorsque cela est possible.

+0

+ 1 comme il a mentionné le fait qu'unboxing/boxing est utilisé pour dériver l'Object Boolean de l'état primitif. – VeenarM

+0

Merci! Je ne savais pas que le booleanValue était autocallé (par conséquent, je n'avais pas du tout le sens de la fonction, car je pensais que c'était une sorte de magie java de bas niveau). J'essaie d'éviter ce genre de wrappers, mais vous savez, le code hérité que je ne peux pas toucher. – Neuromante

2

Je suppose que le seul avantage de la première méthode au cours de la seconde ESt la posibility pour compiler le code avec la spécification de JDK ancien/Java languaje avant Java 1.5

1

Boolean a trois états - true, false et null. Si vous n'avez pas initialisé, vous obtiendrez NullPointerException en cas d'écriture !var. Rappelez-vous également, les objets sont auto-initialisés à null tout en booléen primitive à false.

2

La différence est le déballage automatique.

La première version, ce qui est mieux codifiés comme:

if (variable.booleanValue()) 

ne fait pas besoin unboxing automatique, donc peut être utilisé avec les versions de pré 1.5 Java.

La deuxième version utilise le déballage automatique et nécessite donc la version 1.5 et supérieure.

Si vous avez besoin de votre code à exécuter sur et ancienne version Java, vous devez utiliser la version 1.

Les deux peuvent jeter NPE, donc il n'y a pas de différence sur ce point.

2

Les answer by Telcontar points sur la seule chose que je peux penser à techniquement faire une différence: Le deuxième extrait de code repose sur Autoboxing (or rather auto-unboxing), et donc, nécessite la version Java> = 1.5.

En dehors de cela, il n'y a pas de différence technique. Vous avez mentionné

Cela ne présente-t-il pas également le risque (sur le code impossible, mais bon) d'une exception de pointeur nul si la variable n'est pas initialisée?

mais c'est le cas pour les deux versions. Même le second va lancer un NullPointerException lorsque la variable est null.


Cependant, j'étais curieux de celui-ci aussi bien, et a fait un test:

public class TheManyShadesOfFasle 
{ 
    public static int testBoxedBooleanBooleanValueComparison() 
    { 
     Boolean variable = false; 
     if(variable.booleanValue() == false) 
     { 
      return 0; 
     } 
     return 1; 
    } 

    public static int testBoxedBooleanComparison() 
    { 
     Boolean variable = false; 
     if(variable == Boolean.FALSE) 
     { 
      return 0; 
     } 
     return 1; 
    } 

    public static int testBoxedBooleanBooleanValueDirect() 
    { 
     Boolean variable = false; 
     if(!variable.booleanValue()) 
     { 
      return 0; 
     } 
     return 1; 
    } 

    public static int testBoxedBooleanDirect() 
    { 
     Boolean variable = false; 
     if(!variable) 
     { 
      return 0; 
     } 
     return 1; 
    } 

    public static int testBooleanComparison() 
    { 
     boolean variable = false; 
     if(variable == false) 
     { 
      return 0; 
     } 
     return 1; 
    } 

    public static int testBooleanDirect() 
    { 
     boolean variable = false; 
     if(!variable) 
     { 
      return 0; 
     } 
     return 1; 
    } 

} 

Cela peut être décompilé avec javap -c, pour obtenir le bytecode:

public static int testBoxedBooleanBooleanValueComparison(); 
    Code: 
     0: iconst_0 
     1: invokestatic #2     // Method java/lang/Boolean.valueOf:(Z)Ljava/lang/Boolean; 
     4: astore_0 
     5: aload_0 
     6: invokevirtual #3     // Method java/lang/Boolean.booleanValue:()Z 
     9: ifne   14 
     12: iconst_0 
     13: ireturn 
     14: iconst_1 
     15: ireturn 

    public static int testBoxedBooleanComparison(); 
    Code: 
     0: iconst_0 
     1: invokestatic #2     // Method java/lang/Boolean.valueOf:(Z)Ljava/lang/Boolean; 
     4: astore_0 
     5: aload_0 
     6: getstatic  #4     // Field java/lang/Boolean.FALSE:Ljava/lang/Boolean; 
     9: if_acmpne  14 
     12: iconst_0 
     13: ireturn 
     14: iconst_1 
     15: ireturn 

    public static int testBoxedBooleanBooleanValueDirect(); 
    Code: 
     0: iconst_0 
     1: invokestatic #2     // Method java/lang/Boolean.valueOf:(Z)Ljava/lang/Boolean; 
     4: astore_0 
     5: aload_0 
     6: invokevirtual #3     // Method java/lang/Boolean.booleanValue:()Z 
     9: ifne   14 
     12: iconst_0 
     13: ireturn 
     14: iconst_1 
     15: ireturn 

    public static int testBoxedBooleanDirect(); 
    Code: 
     0: iconst_0 
     1: invokestatic #2     // Method java/lang/Boolean.valueOf:(Z)Ljava/lang/Boolean; 
     4: astore_0 
     5: aload_0 
     6: invokevirtual #3     // Method java/lang/Boolean.booleanValue:()Z 
     9: ifne   14 
     12: iconst_0 
     13: ireturn 
     14: iconst_1 
     15: ireturn 

    public static int testBooleanComparison(); 
    Code: 
     0: iconst_0 
     1: istore_0 
     2: iload_0 
     3: ifne   8 
     6: iconst_0 
     7: ireturn 
     8: iconst_1 
     9: ireturn 

    public static int testBooleanDirect(); 
    Code: 
     0: iconst_0 
     1: istore_0 
     2: iload_0 
     3: ifne   8 
     6: iconst_0 
     7: ireturn 
     8: iconst_1 
     9: ireturn 

Et on peut voir que le bytecode de testBoxedBooleanBooleanValueComparison et testBoxedBooleanDirect (correspondant à votre premier et deuxième extrait de code) sont identique. (Cela signifie essentiellement: L'auto-unboxing est implicitement appelant la méthode booleanValue de Boolean en interne). La même chose pour if(!variable.booleanValue()), comme on peut le voir dans testBoxedBooleanBooleanValueDirect.

Les autres cas sont principalement là pour l'exhaustivité: Les cas testBooleanComparison et testBooleanDirect ont chacun le même bytecode, mais il diffère des autres parce qu'il n'y a pas de déballage ou de derefencing ayant lieu.


Un cas intéressant de souligner: Une comparaison de la variable à Boolean.FALSE ou Boolean.TRUE peut donner un sens, car elle couvre implicitement le cas de la variable null:

if (variable == Boolean.TRUE) { 
    ... 
} else { 
    // Here, the variable is either "false" or "null" 
} 

vs

if (variable == Boolean.FALSE) { 
    ... 
} else { 
    // Here, the variable is either "true" or "null" 
}