I am confused about when to use primitive vs. non-primitive(?) types (i.e. int vs. Integer) in Java. I realize that in some places you can't use primitive types (for example when making use of generics). But what about in "normal" code? Is there a performance penalty for using non-primitive types? What about when working with Android?
***My question is very similar to this question, which was discovered by one of the posters below. The answers to the linked question give additional insights into this question, which are not covered below.
*** "non-primitive" types are officially referred to as reference types.
Short answer: An int is a number; an Integer is a pointer that can reference an object that contains a number. Using Integer for arithmetic involves more CPU cycles and consumes more memory. An int is not an object and cannot passed to any method that requires objects (just like what you said about Generics).
Non-primitive types are objects. They have to be dynamically allocated, garbage collected, and checked for null-ness (although some of these operations may get removed by an optimizing compiler). Reading their actual value requires loading from a pointer. Primitive types are values. They generally take up less space and are faster to access.
A good rule of thumb is, use primitive types unless you need polymorphism, in which case use the corresponding object.
There is a slight penalty for converting between the types (autoboxing). Also int will have a bit less overhead so I would always go with int if you can.
Also see this question: When to use primitive and when reference types in Java
In Java, int is a primitive data type, while Integer is a Wrapper class.
int, being a primitive data type has less flexibility. We can only store the binary value of an integer in it.
Since Integer is a wrapper class for int data type, it gives us more flexibility in storing, converting and manipulating integer data.
Integer is a class and thus it can call various in-built methods defined in the class. Variables of type Integer store references to Integer objects, just as with any other reference (object) type.
You can find a more detailed explanation here.
As an OO purist, you would likely shun the primitives altogether and damn the performance costs and lack of postfix operators. (Yes, there is a performance cost.) You may also adopt this approach simply from extensibility considerations as a designer (without necessarily being hung up on purity.)
As a practical matter (outside of theoretical and aesthetic questions), use the primitives everywhere you can and use the object version where you can't use primitives. (You already mentioned one such case. The language and APIs will drive this decision.)
As a performance freak, you would likely shun the object versions and you may not really care too deeply if you step on a few OO golden rules and sacrosanct no-goes: performance is king and you make your decisions accordingly.
I'd recommend option 2 as a good place to start until you develop your own dogmatic preferences! :)
My view: Using Integer as parameters or return values allows one thing that primitive ints don't allow: Using null. But is this a good idea? I think it rarely ever is.
As far as performance is concerned: The compiler will optimize your code to some degree, so that is most of the time not a real concern.
Related
When I should go for wrapper class over primitive types? Or On what circumstance I should choose between wrapper / Primitive types?
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.
Generally, you should use primitive types unless you need an object for some reason (e.g. to put in a collection). Even then, consider a different approach that doesn't require a object if you want to maximize numeric performance. This is advised by the documentation, and this article demonstrates how auto-boxing can cause a large performance difference.
In my opinion, if my class members are wrapper variables, it does not rely on default values, which is developer friendly behavior.
1.
class Person {
int SSN ; // gets initialized to zero by default
}
2.
class PersonBetter {
Integer SSN; //gets initialized to null by default
}
In the first case, you cannot keep SSN value uninitialized. It may hurt if you are not checking if the value was set before you attempt to use it.
In the second case, you can keep SSN initialized with null. Which can lead to NullPointerException but it is better than unknowingly inserting default values(zero) as SSN into to the database whenever you attempt to use it without initializing SSN field.
I would only use the wrapper types if you have to.
In using them you don't gain much, besides the fact that they are Objects.
And, you lose overhead in memory usage and time spent boxing/unboxing.
Practically I had encountered a situation where use of wrapper class can be explained.
I created a service class which had a long type variable
If the variable is of type long - when not initialized, it will be set to 0 - this will be confusing to the user when displayed in GUI
If the variable is of type Long - when not initialized, it will be set to null - this null value won't show up in GUI.
This applies to Boolean as well where values can be more confusing when we use primitive boolean(as default value is false).
Collections are the typical case for the simple Java wrapper objects. However, you might consider giving the Wrapper a more specific meaning in the code (value object).
IMHO there's almost always a benefit to use value objects when it boils down to readability and maintainance of the code. Wrapping simple data structures inside of objects when they have certain responsibilities often simplifies the code. This is something that is very important in Domain-Driven Design.
There is of course the performance issue, but I tend to ignore that until I have the possibility to measure the performance with proper data and do more directed actions towards the problematic area. It might also be easier to understand the performance issue if the code is easy to understand as well.
performance of applications that are dominated by numerical calculations can benefit greatly from the use of primitives.
primitive types, one uses the == operator, but for wrapper the preferred choice is to call the equals() method.
"Primitive types considered harmful" because they mix "procedural semantics into an otherwise uniform object-oriented model.
Many programmers initialize numbers to 0 (default) or -1 to signify this, but depending on the scenario, this may be incorrect or misleading.
If you want to use Collections, you must use Wrapper classes.
Primitive types, are used for arrays. Also, to represent data that has no behaviour,for example, a counter, or a boolean condition.
Since autoboxing, the "when to use primitive or wrapper" frontier has become quite fuzzy.
But remember, Wrappers are objects, so you get all the fancy Java features. For example, you can use reflexion to create Integer objects, but not int values. Wrapper classes also have methods such as valueOf.
When to Use Primitive Types
When doing a large amount of calculations, primitive types are always faster — they have much less overhead.
When you don’t want the variable to be able to be null.
When you don’t want the default value to be null.
If the method must return a value
When to Use Wrapper Class
When you are using Collections or Generics — it is required
If you want the MIN_SIZE or MAX_SIZE of a type.
When you want the variable to be able to be null.
When you want to default value to be null.
If sometimes the method can return a null value.
from https://medium.com/#bpnorlander/java-understanding-primitive-types-and-wrapper-objects-a6798fb2afe9
If you want to create a value type. Something like a ProductSKU or AirportCode.
When a primitive type (string in my examples) defines equality, you'll want to override equality.
Primitive values in Java are not object. In order to manipulate these values as object the java.lang package provides a wrapper class for each of the primitive data type.
All Wrapper classes are final. The object of all wrapper classes that can be initiated are immutable that means the value in the wrapper object can not be changed.
Although, the void class is considered a wrapper class but it does not wrap any primitive values and is not initiable. It does not have public constructor, it just denotes a class object representing the keyword void.
As a primitive version of Optional*, Java 1.8 provides OptionalInt, OptionalLong and OptionalDouble.
But I cannot find the equivalent OptionalBoolean class.
Are there any technical reasons against having an OptionalBoolean?
*
An Optional may or may not have the presence of a value, is used as an alternative to null.
This quote explains the considerations behind having primitive streams. I'm assuming the same applied to primitive Optionals. In short, primitive streams (and probably Optionals as well) were created for performance reasons. They didn't create them for all 8 primitive types to reduce code duplication and interface pollution.
Quoting the words of Brian Goetz in the lambda mailing list:
More generally: the philosophy behind having specialized
primitive streams (e.g., IntStream) is fraught with nasty tradeoffs.
On the one hand, it's lots of ugly code duplication, interface
pollution, etc. On the other hand, any kind of arithmetic on boxed ops
sucks, and having no story for reducing over ints would be terrible.
So we're in a tough corner, and we're trying to not make it worse.
Trick #1 for not making it worse is: we're not doing all eight
primitive types. We're doing int, long, and double; all the others
could be simulated by these. Arguably we could get rid of int too, but
we don't think most Java developers are ready for that. Yes, there
will be calls for Character, and the answer is "stick it in an int."
(Each specialization is projected to ~100K to the JRE footprint.)
Trick #2 is: we're using primitive streams to expose things that are best done in the primitive domain (sorting, reduction) but not
trying to duplicate everything you can do in the boxed domain. For
example, there's no IntStream.into(), as Aleksey points out. (If there
were, the next question(s) would be "Where is IntCollection?
IntArrayList? IntConcurrentSkipListMap?) The intention is many streams
may start as reference streams and end up as primitive streams, but
not vice versa. That's OK, and that reduces the number of conversions
needed (e.g., no overload of map for int -> T, no specialization of
Function for int -> T, etc.)
And I should mention that I found that quote in the answer to this question.
boolean values are often abused as parameters. Effective Java 2nd edition warns against abuse of booleans. They often lead to badly readable code if they are not for actual boolean true/false arguments. Instead, Joshua Bloch - the writer - tries to convince people to use double valued enum's:
Prefer two-element enum types to boolean parameters. It makes your code easier to read and to write, especially if you're using an IDE that supports autocompletion. Also it makes it easy to add more options later.
Most OptionalBoolean instances would probably be used incorrectly. This is a good reason for not including one. But I cannot say - only Oracle can - if this is the reason why it is not in there.
Apart for the desire to reduce the magnitude of the combinatorial explosion of primitive type specialisation classes I suspect one major reason for the absence of an OptionalBoolean is that the advantage of such a class is much smaller than the advantage of specialisations for the numeric types.
The reason for why the advantage is smaller is that there are only two different values of the type boolean. Because of this, most of the time you only get two object of type Boolean. Those two are cached as Boolean.TRUE and Boolean.FALSE and reused in most cases, e.g. when booleans are auto-boxed. Numeric wrapper types have a number of cached objects for a small range of values, for other values a new object has to be allocated every time a primitive value is stored in a generic container such as Optional.
So an Optional<Boolean> object is almost as efficient as an OptionalBoolean would be since no new Boolean have to be allocated to put an unboxed boolean into it.
I could also be useful to have two cashed Optional<Boolean> available somewhere in the standard library, as Optional.TRUE/FALSE perhaps. I don't know the reason for why there isn't.
Just to be complete about that: There is indeed an OptionalBoolean in Java 8, but not where you would expect it: it is com.sun.javafx.scene.control.behavior.OptionalBoolean.
But, while JavaFX is nowadays a fixed component of Java, it is not advisable to use it outside of JavaFX stuff.
Apart from that, its interface is completely different from the ones you have in java.util.*.
Java does not allow primitive types to be used in generic data structures. E.g. ArrayList<int> is not allowed. The reason is, primitive types can not be directly converted to Object. However Java 1.5 does support auto-boxing, and wrapper classes work in generic data structures. So why couldn't the compiler auto-box it to ArrayList<Integer>? Are there any other reasons for why this can not work?
So as far as I understand it, your proposed ArrayList<int> would be identical to ArrayList<Integer>. Is that right? (In other words, internally it still stores an Integer; and every time you put something in or get it out, it would automatically box/unbox it, but autoboxing/autounboxing already does that for ArrayList<Integer>.)
If it is the same, then I don't understand what the utility of having a duplicate syntax <int> is when it means the same thing as <Integer>. (In fact it will introduce additional problems, because for example int[] is not the same runtime type as Integer[], so if you have T[], and T is int, what would it mean?)
The generic type information is erased at run time. Check this link. Generics have more to do with compile time checking than run time checking. The autoboxing and unboxing are the run time operations. See the link. This is the reason that autoboxing should not work with Generics.
The problem will be in performance. For every get()/set() method, in the list, the JVM will have to unbox/box the respective value for the mentioned method respectively. Remember, autoboxing take primitive types and wraps them into an Object and vice-versa, as stated on Autoboxing:
Finally, there are performance costs associated with boxing and
unboxing, even if it is done automatically.
I think they wanted a List to do simple operation and alleviating performance all together.
I don't think there's any technical reason it couldn't be done like you say, but there are always interface considerations: e.g., if you automatically converted objects of type ArrayList<int> to be ArrayList<Integer>, you lose some explicitness in terms of the interface specifications: it is less obvious that ArrayList in fact store objects, not primitives.
My understanding is that autoboxing is more for compatibility and flexibility in parameter types than for the ease of being able to say "int" instead of "Integer." Java's not exactly known for it's obsession with conciseness...
A small P.S.: I don't think it would technically be correct to say "autobox ArrayLint<int> to ArrayList<Integer>," because you aren't actually wrapping anything in an object "box" -- you're just actually converting a typename ArrayList<int> to "actual" type ArrayList<Integer>
I'm glad it is impossible, because int use much less memory than Integer and is much faster too. Therefore it forces me to think whether it is acceptable to use Collection<Integer> or not (lot of times in business application it's ok, but in other apps it is not).
I would be much happier if Collection<int> was possible and efficient, but it is not.
I don't think this is any sort of problem - do you have any concrete case where is this limiting you somehow? And btw there is difference between int and Integer while the object can be null and primitive type can't.
Java collections only store Objects, not primitive types; however we can store the wrapper classes.
Why this constraint?
It was a Java design decision, and one that some consider a mistake. Containers want Objects and primitives don't derive from Object.
This is one place that .NET designers learned from the JVM and implemented value types and generics such that boxing is eliminated in many cases. In CLR, generic containers can store value types as part of the underlying container structure.
Java opted to add generic support 100% in the compiler without support from the JVM. The JVM being what it is, doesn't support a "non-object" object. Java generics allow you to pretend there is no wrapper, but you still pay the performance price of boxing. This is IMPORTANT for certain classes of programs.
Boxing is a technical compromise, and I feel it is implementation detail leaking into the language. Autoboxing is nice syntactic sugar, but is still a performance penalty. If anything, I'd like the compiler to warn me when it autoboxes. (For all I know, it may now, I wrote this answer in 2010).
A good explanation on SO about boxing: Why do some languages need Boxing and Unboxing?
And criticism of Java generics: Why do some claim that Java's implementation of generics is bad?
In Java's defense, it is easy to look backwards and criticize. The JVM has withstood the test of time, and is a good design in many respects.
Makes the implementation easier. Since Java primitives are not considered Objects, you would need to create a separate collection class for each of these primitives (no template code to share).
You can do that, of course, just see GNU Trove, Apache Commons Primitives or HPPC.
Unless you have really large collections, the overhead for the wrappers does not matter enough for people to care (and when you do have really large primitive collections, you might want to spend the effort to look at using/building a specialized data structure for them).
It's a combination of two facts:
Java primitive types are not reference types (e.g. an int is not an Object)
Java does generics using type-erasure of reference types (e.g. a List<?> is really a List<Object> at run-time)
Since both of these are true, generic Java collections can not store primitive types directly. For convenience, autoboxing is introduced to allow primitive types to be automatically boxed as reference types. Make no mistake about it, though, the collections are still storing object references regardless.
Could this have been avoided? Perhaps.
If an int is an Object, then there's no need for box types at all.
If generics aren't done using type-erasure, then primitives could've been used for type parameters.
There is the concept of auto-boxing and auto-unboxing. If you attempt to store an int in a List<Integer> the Java compiler will automatically convert it to an Integer.
Its not really a constraint is it?
Consider if you wanted to create a collection that stored primitive values. How would you write a collection that can store either int, or float or char? Most likely you will end up with multiple collections, so you will need an intlist and a charlist etc.
Taking advantage of the object oriented nature of Java when you write a collection class it can store any object so you need only one collection class. This idea, polymorphism, is very powerful and greatly simplifies the design of libraries.
The main reason is the java design strategy.
++
1) collections requires objects for manipulation and primitives are not derived from object
so this can be the other reason.
2) Java primitive data types are not reference type for ex. int is not an object.
To Overcome:-
we have concept of auto-boxing and auto-unboxing. so if you are trying to store primitive data types compiler will automatically convert that into object of that primitive data class.
I think we might see progress in this space in the JDK possibly in Java 10 based on this JEP - http://openjdk.java.net/jeps/218.
If you want to avoid boxing primitives in collections today, there are several third party alternatives. In addition to the previously mentioned third party options there is also Eclipse Collections, FastUtil and Koloboke.
A comparison of primitive maps was also published a while ago with the title: Large HashMap overview: JDK, FastUtil, Goldman Sachs, HPPC, Koloboke, Trove. The GS Collections (Goldman Sachs) library was migrated to the Eclipse Foundation and is now Eclipse Collections.
On the very high level, I know that we need to "wrap" the primitive data types, such as int and char, by using their respective wrapper classes to use them within Java collections.I would like to understand how Java collections work at the low level by asking:"why do we need to wrap primitive data types as objects to be able to use them in collections?"I thank you in advance for your help.
Because Java collections can only store Object References (so you need to box primitives to store them in collections).
Read this short article on Autoboxing for more info.
If you want the nitty gritty details, it pretty much boils down to the following:
Local Primitives are stored on the Stack. Collections store their values via a reference to an Object's memory location in the Heap. To get that reference for a local primitive, you have to box (take the value on the Stack and wrap it for storage on the Heap) the value.
At the virtual machine level, it's because primitive types are represented very differently in memory compared to reference types like java.lang.Object and its derived types. Primitive int in Java for example is just 4 bytes in memory, whereas an Object takes up at minimum 8 bytes by itself, plus another 4 bytes for referencing it. Such design is a simple reflection of the fact that CPUs can treat primitive types much more efficiently.
So one answer to your question "why wrapper types are needed" is because of performance improvement that it enables.
But for programmers, such distinction adds some undesirable cognitive overhead (e.g., can't use int and float in collections.) In fact, it's quite possible to do a language design by hiding that distinction --- many scripting languages do this, and CLR does that. Starting 1.5, Java does that, too. This is achieved by letting the compiler silently insert necessary conversion between primitive representation and Object representation (which is commonly referred to as boxing/unboxing.)
So another answer to your question is, "no, we don't need it", because the compiler does that automatically for you, and to certain extent you can forget what's going on behind the scene.
Read all of the answers, but none of them really explains it simply in layman terms.
A wrapper class wraps(encloses) around a data type (can be any primitive data type such as int, char, byte, long) and makes it an object.
Here are a few reasons why wrapper classes are needed:
Allows null values.
Can be used in collection such as List, Map, etc.
Can be used in methods which accepts arguments of Object type.
Can be created like Objects using new ClassName() like other objects:
Integer wrapperInt = new Integer("10");
Makes available all the functions that Object class has such as clone(), equals(), hashCode(), toString() etc.
Wrapper classes can be created in two ways:
Using constructor:
Integer i = new Integer("1"); //new object is created
Using valueOf() static method:
Integer i = Integer.valueOf("100"); //100 is stored in variable
It is advised to use the second way of creating wrapper classes as it takes less memory as a new object is not created.
To store the Primitive type values in Collection. We require Wrapper classes.
Primitive data types can't be referenced as memory addresses. That's why we need wrappers which serve as placeholders for primitive values. These values then can be mutated and accessed, reorganized, sorted or randomized.
Collection uses Generics as the bases. The Collection Framework is designed to collect, store and manipulate the data of any class. So it uses generic type. By using Generics it is capable of storing the data of ANY CLASS whose name you specify in its declaration.
Now we have various scenario in which want to store the primitive data in the same manner in which the collection works. We have no way to store primitive data using Collection classes like ArrayList, HashSet etc because Collection classes can store objects only. So for storing primitive types in Collection we are provided with wrapper classes.
Edit:
Another benefit of having wrapper classes is that absence of an object can be treated as "no data". In case of primitive, you will always have a value.
Say we have method signature as
public void foo(String aString, int aNumber)
you can't make aNumber as optional in above method signature.
But if you make signature like:
public void foo(String aString, Integer aNumber)
you have now made aNumber as optional since user can pass null as a value.
See Boxing and unboxing: when does it come up?
It's for C#, but the same concept apply to Java. And John Skeet wrote the answer.
Well, the reason is because Java collections doesn't differentiate between primitive and Object. It processes them all as Object and therefore, it will need a wrapper. You can easily build your own collection class that doesn't need wrapper, but at the end, you will have to build one for each type char, int, float, double, etc multiply by the types of the collections (Set, Map, List, + their implementation).
Can you imagine how boring that is?
And the fact is, the performance it brings by using no wrapper is almost negligible for most applications. Yet if you need very high performance, some libraries for primitive collections are also available (e.g. http://www.joda.org/joda-primitives/)
Wrapper classes provide useful methods related to corresponding data types which you can make use of in certain cases.
One simple example. Consider this,
Integer x=new Integer(10);
//to get the byte value of 10
x.byteValue();
//but you can't do this,
int x=10;
x.byteValue(); //Wrong!
can you get the point?
If a variable is known to either hold a specific bit pattern representing null or else information which can be used to locate a Java Virtual Machine object header, and if the method for reading an object header given a reference will inherently trap if given the bit pattern associated with null, then the JVM can access the object identified by the variable on the assumption that there is one. If a variable could hold something which wasn't a valid reference but wasn't the specific null bit pattern, any code which tried to use that variable would have to first check whether it identified an object. That would greatly slow down the JVM.
If Object derived from Anything, and class objects derived from Object, but primitives inherited from a different class derived from Anything, then in a 64-bit implementation it might be practical to say that about 3/4 of the possible bit patterns would represent double values below 2^512, 1/8 of them to represent long values in the range +/- 1,152,921,504,606,846,975, a few billion to represent any possible value of any other primitve, and the 1/256 to identify objects. Many kinds of operations on things of type Anything would be slower than with type Object, but such operations would not be terribly frequent; most code would end up casting Anything to some more specific type before trying to work with it; the actual type stored in the Anything would need to be checked before the cast, but not after the cast was performed. Absent a distinction between a variable holding a reference to a heap type, however, versus one holding "anything", there would be no way to avoid having the overhead extend considerably further than it otherwise would or should.
Much like the String class, Wrappers provide added functionality and enable the programmer to do a bit more with the process of data storage. So in the same way people use the String class like....
String uglyString = "fUbAr";
String myStr = uglyString.toLower();
so too, they can with the Wrapper. Similar idea.
This is in addition to the typing issue of collections/generics mentioned above by Bharat.
because int does not belongs any class .
we convert datatype(int) to object(Interger)