8

The following code for Integer uses object interning:

Integer.valueOf("1")

It is not clear from API documentation whether this code for Boolean also uses interned object:

Boolean.valueOf("true")

Obviously, it may. But does it have to?

UPDATE

I agree that source code can explain what actually happens (BTW, thanks for the answers). To make the question less trivial, is there any part of Java API spec or JSL which tells what MUST happen?

It was natural to ask the question against the code like this:

String str = "true";
if (Boolean.valueOf(str) == Boolean.TRUE) { ... }

The outcome depends on whether "object interning" is guaranteed or not. It's better to avoid this code altogether and use true instead of Boolean.TRUE (rather than looking up details in any specs or sources), but it is a valid reason to ask the question.

NOTE: In fact, I didn't see guarantees of object interning for Integer in any googled specs. So, it may all be just an implementation detail nobody should rely on.

Tunaki
  • 132,869
  • 46
  • 340
  • 423
uvsmtid
  • 4,187
  • 4
  • 38
  • 64
  • 4
    You can check for yourself by looking at the source code –  Jun 19 '16 at 09:00
  • You could also check by invoking it twice and checking if you receive the same Boolean instance twice or not. Why do you care anyway? This shouldn't change anything to your code. – JB Nizet Jun 19 '16 at 09:02
  • @a_horse_with_no_name, **is object interning outside of the specification?** Source-wise I guess it returns object `Boolean.TRUE` (or `Boolean.FALSE` for `"false"`). In fact, with such a small value set (only 2) these constants are enough to model the pool. But is it dictated by specification? – uvsmtid Jun 19 '16 at 09:09
  • Well, if it isn't specified in the API specification (that's what the javadoc is), then the implementation is free to do whatever it wants. – JB Nizet Jun 19 '16 at 09:11
  • @JBNizet, it's not that clear-cut. The specification is split into JSL and API (among others) and this is somewhere on the boundary of both. I agree - depending on these behaviours is obviously confusing (if not unreliable altogether). But when you see something like `if (Boolean.value(str) == Boolean.TRUE)`, it's a valid type of question. – uvsmtid Jun 19 '16 at 09:19
  • 1
    Where did you read in the specification that `Integer.valueOf` might return a cached instance? It is an implementation detail of Sun / Oracle JDK http://stackoverflow.com/questions/31445024/does-autoboxing-call-valueof, that probably other follows; but it is not specified. – Tunaki Jun 19 '16 at 09:23
  • @Tunaki, that's why I ask the question. I couldn't find these parts anywhere. But I this didn't prove to me that such parts cannot exist. – uvsmtid Jun 19 '16 at 09:24
  • The question is asking about `Boolean.valueOf` with the premise that "`Integer.valueOf` uses object interning", when the latter is in fact not specified. I'm not sure what kind of answer you're looking for. – Tunaki Jun 19 '16 at 09:29
  • 2
    @uvsmtid when I see that kind of code, all I see is a bug waiting to happen: the code relies on an undocumented feature of Boolean, and has no advantage over `if (Boolean.valueOf(str))` or `if (Boolean.parseBoolean(str))`. which are more concise, and will work whether valueOf() always returns Boolean.TRUE or not. – JB Nizet Jun 19 '16 at 09:30
  • @JBNizet, totally agree - I even updated the question independently before seeing your comment. However, the fact of discussing this case and revealing uncertainties around possible unreliable outcome helps avoiding the line in question. – uvsmtid Jun 19 '16 at 09:37

3 Answers3

5

Based on the source code, the boolean is parsed as:

public static final Boolean FALSE = new Boolean(false);
public static final Boolean TRUE = new Boolean(true);

public static Boolean valueOf(String s) {
    return toBoolean(s) ? TRUE : FALSE;
}

Where TRUE and FALSE are static (immutable) objects. So yes, parsed booleans are interned.

However, I agree with @JBNizet's comment that one should not derive code contracts from the source code: as long as a feature is not documented, the developers of Java can change their mind. You better use Boolean.equals to check whether two objects are equivalent.

Community
  • 1
  • 1
Willem Van Onsem
  • 443,496
  • 30
  • 428
  • 555
5

The JLS guarantees that:

Integer i = 1;
Boolean b = true;

will use interning (at least between -128 and 127 for Integers, and for true and false for Booleans).

The relevant javadocs also guarantee that:

Integer i = Integer.valueOf(1);
Boolean b = Boolean.valueOf(true);

will return interned objects.

However there is no such explicit guarantees for valueOf(String): although it is the case in the specific implementation you are using, it may not be the case with a different JVM or in future releases. In fact an implementation that would return new Boolean(Boolean.parseBoolean(input)) would be valid.

assylias
  • 321,522
  • 82
  • 660
  • 783
2

Here's the source code:

public static Boolean valueOf(String s) {
    return parseBoolean(s) ? TRUE : FALSE;
}

Where TRUE is:

public static final Boolean TRUE = new Boolean(true);

If you're still not sure, define two variables:

Boolean a = Boolean.valueOf("true");
Boolean b = Boolean.valueOf("true");

and check whatever you want by yourself.

Maroun
  • 94,125
  • 30
  • 188
  • 241