Why do people still use primitive types in Java?
In Joshua Bloch's Effective Java, Item 5: "Avoid creating unnecessary objects", he posts the following code example:
public static void main(String[] args) {
Long sum = 0L; // uses Long, not long
for (long i = 0; i <= Integer.MAX_VALUE; i++) {
sum += i;
}
System.out.println(sum);
}
and it takes 43 seconds to run. Taking the Long into the primitive brings it down to 6.8 seconds... If that's any indication why we use primitives.
The lack of native value equality is also a concern (.equals()
is fairly verbose compared to ==
)
for biziclop:
class Biziclop {
public static void main(String[] args) {
System.out.println(new Integer(5) == new Integer(5));
System.out.println(new Integer(500) == new Integer(500));
System.out.println(Integer.valueOf(5) == Integer.valueOf(5));
System.out.println(Integer.valueOf(500) == Integer.valueOf(500));
}
}
Results in:
false
false
true
false
EDIT Why does (3) return true
and (4) return false
?
Because they are two different objects. The 256 integers closest to zero [-128; 127] are cached by the JVM, so they return the same object for those. Beyond that range, though, they aren't cached, so a new object is created. To make things more complicated, the JLS demands that at least 256 flyweights be cached. JVM implementers may add more if they desire, meaning this could run on a system where the nearest 1024 are cached and all of them return true... #awkward
why are there Primitive datatype in Java?
For efficiency. Variables of primitive types contain the value directly; variables of non-primitive types are references, referring to an object stored somewhere else in memory.
Each time you need to use the value of a wrapper type, the JVM needs to lookup the object in memory to get at the value. This isn't needed for primitive types, because the variable contains the value itself, instead of a reference to an object that contains the value.
However, that doesn't explain why primitive types need to be explicitly visible in the Java programming language. The designers of the Java language and the JVM could have chosen to hide primitive types from the language itself, so that you could treat everything as an object; the compiler could then translate it under the covers to more efficient primitive types.
Some newer programming languages that run on the JVM (Groovy, Scala and others) let you do exactly that: in the language itself everything looks like an object, which you can for example call methods on, but below the covers the compiler translates them to primitives.
I guess that in the time the Java language was developed (in the first half of the 1990's) people didn't think of that, and now it's too late for a radical change in the language to allow this.
Should I never use primitive types again?
Using the boxed types does have both performance and memory issues.
When doing comparisons (eg (i == 10)
), java has to unbox the type before doing the comparison. Even using i.equals(TEN)
uses a method call, which is costlier and (IMO) uglier than the == syntax.
Re memory, the object has to be stored on the heap (which also takes a hit on performance) as well as storing the value itself.
A sneaky gotcha? i.equals(j)
when i is null
.
I always use the primitives, except when it may be null
, but always check for null
before comparison in those cases.
When to use primitive and when reference types in Java
In which case should you use primitive
types(int
) or reference types
(Integer
)?
As a rule of thumb, I will use a primitive (such as int
) unless I have to use a class that wraps a primitive.
One of the cases were one must use a wrapper class such as Integer
is in the case of using generics, as Java does not support the use of primitive types as type parameters:
List<int> intList = new ArrayList<int>(); // Not allowed.
List<Integer> integerList = new ArrayList<Integer>(); // Allowed.
And, in many cases, I will take advantage of autoboxing and unboxing, so I don't have to explicitly perform conversions from primitives to its wrapper class and vice versa:
// Autoboxing will turn "1", "2", "3" into Integers from ints.
List<Integer> numbers = Arrays.asList(1, 2, 3);
int sum = 0;
// Integers from the "numbers" List is unboxed into ints.
for (int number : numbers) {
sum += number;
}
Also, as an additional note, when converting from primitives to its wrapper class objects, and unique instances of objects are not necessary, use the valueOf
method provided by the wrapper method, as it performs caching and return the same instance for a certain value, reducing the number of objects which are created:
Integer i1 = Integer.valueOf(1); // Prefer this.
Integer i2 = new Integer(1); // Avoid if not necessary.
For more information on the valueOf
methods, the API specification for the Integer.valueOf
method can serve as a reference for how those methods will behave in the wrapper classes for primitives.
Should I use Primitive or Object for entity and models in Java?
Default value of Long and Integer variable is null.
But default value of long and int is 0
Compare:
If you use Objects:
public class Student {
private Long id; // long ?
private String name;
private Boolean isGraduated; // boolean ?
private Integer age; // int ?
}
id => null
age => null
If you use primitives:
public class Student {
private long id; // long ?
private String name;
private Boolean isGraduated; // boolean ?
private int age; // int ?
}
id => 0
age => 0
In many scenarios having 0 as default value is confusing, so it makes sense to use Objects in this case. If object value is "null" you know for sure that the value was not initialized. But if primitive value is "0", then it is not clear: is it a default uninitialized value, or this value was initialized with "0".
I generally prefer using primitive types, unless I need explicit null-check
Why is it not possible use primitive types with polymorphic return types?
As always with these questions, the answer is that you'd have to ask the language designers. I can't see any reason why this couldn't be done. However in my opinion this feature would be fairly pointless. As you point out in the question it's only when moo
is invoked on a variable of static type IntFoo
that a primitive would get returned; on a variable of type Foo<Integer>
, an Integer
would get returned anyway. So you can achieve essentially the same thing by doing this.
public class IntFoo implements Foo<Integer> {
@Override
public Integer moo() { return mooAsInt(); }
public int mooAsInt() { return 0; }
}
Personally I think this is better because it's much more obvious when boxing does / does not take place. In your proposal, moo()
could return an int
or an Integer
depending on the static type of the variable, which would be extremely confusing.
Is it a better practice to use Reference types or primitive types in Java?
Assuming you mean primitive wrapper types (Integer
, Boolean
, etc.) and not reference types in general: when you have a choice (often you don't: e.g. you are using API which requires one or the other, or you use them as generic type arguments, or you want to be nullable), prefer primitive types, because on the whole this will make your code simpler and faster.
Be careful if you need to switch from one to another, because ==
will still compile but give different results... usually.
When to use wrapper class and primitive type
Others have mentioned that certain constructs such as Collections
require objects and that objects have more overhead than their primitive counterparts (memory & boxing).
Another consideration is:
It can be handy to initialize Objects to null
or send null
parameters into a method/constructor to indicate state or function. This can't be done with primitives.
Many programmers initialize numbers to 0 (default) or -1 to signify this, but depending on the scenario, this may be incorrect or misleading.
This will also set the scene for a NullPointerException
when something is being used incorrectly, which is much more programmer-friendly than some arbitrary bug down the line.
Related Topics
Differencebetween Serializable and Externalizable in Java
What Is the Easiest/Best/Most Correct Way to Iterate Through the Characters of a String in Java
Comparing Strings with == Which Are Declared Final in Java
How to Ensure Order of Processing in Java8 Streams
Hibernate JPA Sequence (Non-Id)
Comparator.Reversed() Does Not Compile Using Lambda
Powermockito Mock Single Static Method and Return Object
Auto Errors Detection in Intellij Idea
Regex to Match a C-Style Multiline Comment
Struts2 Input Result: How Does It Work? How Are Conversion/Validation Errors Handled
Look and Feel Is Not Updating in Swing Jtabbedpane
Why Is Spring's Applicationcontext.Getbean Considered Bad
Java.Lang.Runtimeexception: Uncompilable Source Code - What Can Cause This