47

I see that Java has Boolean (class) vs boolean (primitive). Likewise, there's an Integer (class) vs int (primitive). What's the best practice on when to use the primitive version vs the class? Should I basically always be using the class version unless I have a specific (performance?) reason not to? What's the most common, accepted way to use each?

42

In Item 5, of Effective Java, Joshua Bloch says

The lesson is clear: prefer primitives to boxed primitives, and watch out for unintentional autoboxing.

One good use for classes is when using them as generic types (including Collection classes, such as lists and maps) or when you want to transform them to other type without implicit casting (for example Integer class has methods doubleValue() or byteValue().

Edit: Joshua Bloch's reason is:

// Hideously slow program! Can you spot the object creation?
public static void main(String[] args) {
    Long sum = 0L;
    for (long i = 0; i < Integer.MAX_VALUE; i++) {
         sum += i;
    }
    System.out.println(sum);
}

This program gets the right answer, but it is much slower than it should be, due to a one-character typographical error. The variable sum is declared as a Long instead of a long, which means that the program constructs about 2^31 unnecessary Long instances (roughly one for each time the long i is added to the Long sum). Changing the declaration of sum from Long to long reduces the runtime from 43 seconds to 6.8 seconds on my machine.

  • 1
    It would help if you listed Bloch's reasons, rather than just quoting his conclusion! – vaughandroid Jul 8 '13 at 12:25
  • @Baqueta I've edited the post. The reason is performance. – m3th0dman Jul 8 '13 at 12:56
  • That's a bit clearer, thanks. I feel justified in posting my own answer now. :) – vaughandroid Jul 8 '13 at 13:38
  • You might find the lmax architecture interesting - "It took a bit more cleverness to go up another order of magnitude. There are several things that the LMAX team found helpful to get there. One was to write custom implementations of the java collections that were designed to be cache-friendly and careful with garbage. An example of this is using primitive java longs as hashmap keys with a specially written array backed Map implementation." – user40980 Jul 8 '13 at 14:17
  • It's looks like something JIT should handle – deFreitas Jul 1 '18 at 11:40
28

The standard practice is to go with the primitives, unless you're dealing with generics (make sure you are aware of autoboxing & unboxing!).

There are a number of good reasons to follow the convention:

1. You avoid simple mistakes:

There are some subtle, non-intuitive cases which often catch out beginners. Even experienced coders slip up and make these mistakes sometimes (hopefully this will be followed by swearing when they debug the code and find the error!).

The most commmon mistake is using a == b instead of a.equals(b). People are used to doing a == b with primitives so it's easily done when you're using the Object wrappers.

Integer a = new Integer(2);
Integer b = new Integer(2);
if (a == b) { // Should be a.equals(b)
    // This never gets executed.
}
Integer c = Integer.valueOf(2);
Integer d = Integer.valueOf(2);
if (c == d) { // Should be a.equals(b), but happens to work with these particular values!
    // This will get executed
}
Integer e = 1000;
Integer f = 1000;
if (e == f) { // Should be a.equals(b)
    // Whether this gets executed depends on which compiler you use!
}

2. Readability:

Consider the following two examples. Most people would say the second is more readable.

Integer a = 2;
Integer b = 2;
if (!a.equals(b)) {
    // ...
}
int c = 2;
int d = 2;
if (c != d) {
    // ...
}

3. Performance:

The fact is it is slower to use the Object wrappers for primitives than just using the primitives. You're adding the cost of object instantiation, method calls, etc. to things that you use all over the place.

Knuth's "...say about 97% of the time: premature optimization is the root of all evil" quote doesn't really apply here. He was talking about optimisations which make the code (or system) more complicated - if you agree with point #2, this is an optimization which makes the code less complicated!

4. It's the convention:

If you make different stylistic choices to 99% of the other Java programmers out there, there are 2 downsides:

  • You will find other people's code harder to read. 99% of the examples/tutorials/etc out there will use primitives. Whenever you read one you'll have the extra cognitive overhead of thinking about how it would look in the style that you're used to.
  • Other people will find your code harder to read. Whenever you ask questions on Stack Overflow you'll have to sift through answers/comments asking "why aren't you using primitives?". If you don't believe me, just look at the battles people have over things like bracket placement, which doesn't even affect the generated code!

Normally I'd list some counter-points, but I honestly can't think of any good reasons to not go with the convention here!

  • 2
    Don't suggets people to compare objects with ==. Objects should be compared with equals(). – Tulains Córdova Jul 8 '13 at 14:35
  • 2
    @user61852 I wasn't suggesting that as a thing to do, but as a common mistake that is made! Should I make that clearer? – vaughandroid Jul 8 '13 at 14:43
  • Yes, you don't mention that objects shoud be compared with equals()... you give them a workaround so that comparing objects with == yields the expected results. – Tulains Córdova Jul 8 '13 at 14:47
  • Good point. Changed it. – vaughandroid Jul 8 '13 at 14:48
  • I added equals() to the second code snippet and changed my vote. – Tulains Córdova Jul 8 '13 at 14:51
12

Usually I go with the primitives. However, one peculiarity of using classes like Integer and Boolean is the possibility of assigning null to those variables. Of course, this means that you have to do null checks all the time, but still better to get a NullPointerException than to have logic errors due to using some int or boolean variable that has not been initialized correctly.

Additionally, it introduces the possibility to use null to assign those variables an "unknown" or "wildcard" value. This can be handy in some situations, for example, in Ternary Logic. Or you might want to check whether a certain object matches some template; in this case you can use null for those variables in the template that can have any value in the object.

  • 2
    (Wasn't my downvote, but...) Java already detects uninitialized variables, and won't let you read a variable til every code path leading up to its use has definitively assigned a value. So you don't gain much from the ability to assign null as a default. On the contrary: you'd be better off not "initializing" the variable at all. Setting any default value, even null, shuts up the compiler... but also keeps it from detecting the lack of useful assignment along all code paths. Thus, an error the compiler could have caught, slips through to runtime. – cHao Apr 2 '14 at 6:37
2

In layman's words:

You use the wrappers when you need to add things to collections.

Collections can't hold primitives.

0

Java features autoboxing as m3th0dman pointed out. Think about in the lowest level possible and you'ĺl see that autoboxing (in or out) a primitive value will imply clock cycles spent in some tasks you don't need if you're working with native data types around your application.

As a general rule, you should try to use native data types whenever possible.

protected by gnat Feb 22 '18 at 21:45

Thank you for your interest in this question. Because it has attracted low-quality or spam answers that had to be removed, posting an answer now requires 10 reputation on this site (the association bonus does not count).

Would you like to answer one of these unanswered questions instead?

Not the answer you're looking for? Browse other questions tagged or ask your own question.