What the difference between Boolean.TRUE and true
Asked Answered
D

4

5

Firstly, I have

private Map<String, Boolean> mem = new HashMap<String, Boolean>();

And then:

  if (wordDict.contains(s) ||  Boolean.TRUE==mem.get(s)) {
        return true;
    }

why can't I use "mem.get(s)==true" in the if statement. There will be a error "Line 6: java.lang.NullPointerException"

I think I still cannot understant wrapper class well. Please give me some guidance. Thank you!

Degree answered 2/8, 2015 at 19:14 Comment(6)
where is wordDict defined? are you sure it's not null?Tillford
wordDict is a array of string. like: wordDict = ["hello","word"]. It is a question from Leetcode NO. 139Degree
show us the code in the line 6.Talbert
public boolean wordBreak(String s, Set<String> wordDict) { if (wordDict.contains(s) || Boolean.TRUE==mem.get(s)) { return true; }Degree
Perhaps mem.get(s) returns null.Talbert
Yes. I don't understand autoboxing well. So I feel confused. Thank you!Degree
P
5

if mem.get(s) is null and will be compared with a primitive boolean value, java will make autoboxing. It means it will call null.booleanValue().

Thats why you get a NPE.

Pittance answered 2/8, 2015 at 19:19 Comment(5)
Oh, got it! Could you give me some explanation why use Boolean.TRUE works? Thank you very much!Degree
@Degree because Boolean is an object and can be null. So your compartion is null == Boolean.TRUE. No autoboxing will be done.Pittance
Oh! Cool! Thank you very very much!! I understand now.Degree
Can I ask you more about this question? I am not sure if my understanding is right. In the hashmap mem, the data are stored as primitive instead of object. But when we take it out, the compiler need to "autobox", which to convert the primitive to an object. But when the mem.get(s) is null, the compiler cannot find a corresponding Boolean to match it. am I right? But when mem.get(s) is null, what it is? an object or a primitive? Thank you! I just fell so confused.Degree
@Degree of course you can ask. In your HashMap objects are stored. not primitives. The runtime environment needs to autoboxes the object value, if you try to compare it with a primitive boolean. It will never autobox the boolean value to an object in this case. mem.get(s)returns null, if there is no value for key s is stored in this hashmap. null is ab object. a primitive can't be null. Hope this thelps. If not feel free to ask again.Pittance
H
3

looks that mem.get(s) returns Boolean type result. In java there are two types for handling logical values. Boolean object type and boolean primitive type.

To evaluate logical expression for if statement, java converts Boolean to boolean using autoboxing.

But if your method returns null instead of Boolean object, then java is unable to unbox this value to boolean primitive type. And you get NullPointerException.

Henotheism answered 2/8, 2015 at 19:26 Comment(1)
OK, I see. That is exactly what I need to understand. Thank you so much!Degree
D
2

This is more a logical problem than a languagebased. if(mem.contains(s) || Boolean.TRUE == mem.get(s)) will only check the second part of the condition, if s isn't in mem. Thus the comparison is equivalent to Boolean.TRUE == null. Since Boolean.TRUE is a Boolean object, the comparison is between two references (and will always return false). boolean on the other hand is a primitive type and thus the Boolean retrieved from mem has to be converted first. Since it's null it can't be converted to the primitive type.

Disputable answered 2/8, 2015 at 19:23 Comment(1)
Thank you for your explanation very much! very useful!Degree
F
1

Any time the dictionary does not contain s (wordDict.contains(s) is false), the second condition (mem.get(s) == true) is evaluated.

In Java's library Maps, attempting to obtain the value for a key which isn't present returns null. So every time that key isn't in the mem map, null is returned, and compared (using ==) with true. When the Boolean type gets compared with, or assigned to, a boolean value, it is 'autounboxed'. This means the Boolean.booleanValue() method is called. If the Boolean is null, this is what causes the exception, because it means calling null.booleanValue(). null is not anything, so it doesn't know how to be a boolean!

The wrapper classes are useful constructs which enable the primitive types to interoperate with types inheriting from Object, that is, reference types (everything else). When you deal with primitive types ('value' types), their values are directly present in the location they're described in - either as part of the memory being used to execute the current function (for local variables) or as part of the memory space allocated to an object in its memory space (for field variables). When you deal with reference types (those inheriting from Object, including Boolean and the other wrapper types), the data being referred to instead exists in a memory space called the Heap. Alongside this Heap memory allocation, in order to know where that object is, the entity analogous to the value for value types is in fact a reference to the memory location of the object, stored as a local variable or a field variable, not the value or data of the object itself. This is what enables these to be null: a null reference says that this variable points to nothing in particular. (Read about Stack and Heap allocation for more detail.)

The reason you're safe comparing to Boolean.TRUE is because on Object types, like Boolean (and any of the wrapper classes for primitive types), the variable of type Boolean is in fact a reference. This means the == operator is actually checking if the references are the same - i.e. if the actual object in memory is the same one (has the same memory location), not if they are 'equal' by some value-based definition of 'equal'. You don't want this, because you can get surprising results like new Boolean(true) == new Boolean(true) returning false. This is incidentally why we have the equals method - this should be defined by any class for an object that wants to be compared by value rather than by reference. On the other hand, for the primitive value types, like boolean, the == operator literally compares the value. This is why it's useful to have the wrapper types box and unbox automatically - a Boolean variable (without being 'dereferenced' - finding the value it points to) is actually a reference value, referring to a memory location. A boolean variable is an actual boolean value. Hence, without unboxing and boxing automagically, it would make no sense to try to compare the two.

If you want to make sure that the value of mem.get(s) is neither null, nor false, use something like mem.containsKey(s) && mem.get(s) == true. The first check ensures that there will be no null reference.

Fairfax answered 2/8, 2015 at 19:49 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.