64

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?

Tulains Córdova
  • 39,570
  • 13
  • 100
  • 156
Casey Patton
  • 5,241

5 Answers5

56

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.

Random42
  • 10,520
  • 10
  • 52
  • 65
32

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!

vaughandroid
  • 7,609
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.

Of course, since Java 8 you can (and probably should) go one step further and instead of e.g. Integer you could use Optional<Integer> for variables that might or might not have a value.

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.

tobias_k
  • 333
3

In layman's words:

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

Collections can't hold primitives.

Tulains Córdova
  • 39,570
  • 13
  • 100
  • 156
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.

Silvarion
  • 109