(Not So) Stupid Questions 20: Primitives and Collections
11/27/2007
Editor's note: Sometimes the most interesting discussions begin when someone says, "This may be a stupid question, but ...." If the person asking the question has taken the time to think about the problem before asking, the question is often not stupid at all. The uncertainty points out an ambiguity in the specs, holes in the docs, or a search for how more experienced programmers might address a particular problem. From time to time, we will print one of the "(Not So) Stupid Questions" we receive and invite our readers to answer the question in the feedback section.
Remember that new people are joining the Java community all the time and may be looking for help from those with more experience. Also, those who began with Java as their first language can benefit from those coming to the community with experience in other languages. As always, answer the questions with kindness. You are also welcome to submit your questions to
This may be a stupid question, but ... "Can you really not use primitives in a collection?"
First Thoughts
In an attempt to understand boxing and unboxing, I was rooting around on the Java.sun.com site, and found the J2SE 5.0 page on Autoboxing.
On the first line, it says:
As any Java programmer knows, you can't put an int (or other primitive value) into a collection. Collections can only hold object references, so you have to box primitive values into the appropriate wrapper class (which is Integer in the case of int).
So I tried testing it out with the following code:
public void boxItPrimitive(){
int first = 1;
int second = 2;
int third = 3;
ArrayList listONumbers = new ArrayList();
listONumbers.add(first);
listONumbers.add(second);
listONumbers.add(third);
for(int i=0; i< listONumbers.size(); i++){
System.out.println(listONumbers.get(i));
}
}
ArrayList implements the interface Collection, yet there are no Integers, just ints. To my surprise, I was able to compile and run this method!
The output was:
1
2
3
Is there a reason I can input raw primitives into a collection without boxing them?
Your answer
2008-08-20 22:06:55 romeshnongthombam
[Reply | View]
From jdk5, autoboxing is done automatically. so there is need for developer to wrap the primitive data type.We can add directly the primitive data type in the collections
bit difficult to follow
2008-01-18 12:51:02 eligetiv
[Reply | View]
Here is the example code which i encountered while debugging some code and faced difficulties because of class types.
Class A {
add(int i) {
System.out.println("primitive type");
}
If i dont uncomment the second add method, "primitive type" gets printed and if i uncomment "Object type" is printed. I got confused and due to this debugging has got me into trouble.
because if i try to invoke by using reflection by doing something like this:
Object [] params = new Object {1};
Class[] paramTypes = // reflectively get the params types from params
String methodName = // in this case its add
so invoking something like this is throwing exception:
Since the caller sends me the objects. And the only way it passes to me is the Object array which primitive type is cased to Integer and because of this it could not invoke add(int i)...
autogenerator for primitive collections
2007-12-06 12:57:18 paultyma
[Reply | View]
Here's a project I used to work on. Need an intArrayList? or a floatLinkedList? Just type it in - fully compatible with existing collections, covariant return types (even in jdk 1.4)...
http://www.classhat.com
autogenerator for primitive collections
2008-05-20 10:22:29 xxmhazi
[Reply | View]
Alex writes above that "three higher patterns of behavior ... can be observed in all existing systems":
Data source, action, and workflow.
It seems to me that the concept of MVC works so well and enough parts of it are already implemented for us that we are starting to take it for granted, and that Alex is just describing a web-specific sub-framework for the Model part of MVC. Let's look at MVC again:
MODEL. The model includes both data source and behaviors (doing something useful with the data). If you want actions and workflow to be manipulated by the user at runtime, then they are essentially complex data structures (which can include code as data) that belong in the model. oyun Storing and retrieving them to/from the data source is a responsibility of the model which we often delegate to pre-built systems. For example, my current habit is to use MySQL + JDBC + Hibernate in order to store my model's data. The other part of the model, behavior, represents what the application actually does so it would be typically written by the programmer. My current habit is to use POJOs to represent specific behaviors.
VIEW. Nothing in MVC says that the view has to be a computer monitor, as Alex implies. Plenty of existing desktop and web applications include support for a "print view", which is realized on paper or saved for later as PDF. The view is an abstract concept. oyun It can be implemented to be consumed by any of the senses - vision, hearing, smell, taste, touch. For example, if you've ever played a game console and felt the joystick vibrate when something explodes on screen, then you've experienced a view implementation for the sense of touch.
Back to web development -- since in web development the model is easily separated from the view (application and client) and since basic controllers already exist to tie them together (Apache,IIS,...), it's easy to misunderstand how our work fits in to this. The developer has choices:
Is the application being written for a thin client or a rich client? If it's a thin client such as a non-Javascript enabled browser, then the view code must be written for and run on the server platform (Perl,Python,Java...), and it must generate HTML that the thin browser can process for display. If the thin browser has sound, smell, and touch capabilities, the HTML can include tags for these. Don't want to change the HTML spec? Use the "object" and "embed" tags to reference the content for the senses. If it's a rich client such as an Ajax-capable or Flash-capable browser, then the view code can be written in JavaScript or Flash and run on the browser, retrieving only serialized data from the server, the serialized data being provided by the model, and this can be in any data format the developer wants... XML, HTML, WDDL, JSON, YAML, MPEG, Flash...
CONTROLLER. The controller is responsible for coordinating events that happen in the model and the view. In a desktop application it's easy to see that the controller is responsible for handling mouse events etc. It's easy to identify work that needs to be done by the developer to implement the controller. But in a web application, it's not so easy, because the controller code can be partitioned into several layers or components, and this partitioning depends on the architecture: thin clients such as browsers already process mouse events, such as clicking links and submitting forms, but there's usually more controller code to be written by the developer on the server in order to keep these details out of the model; whereas in rich clients the developer may be writing more controller code for the client in the form of a Flash or Ajax client-side application and writing less controller code for the server.
Alex writes that the "core concern of the servlet framework" is to manage data source, action, and workflow objects. If that's what he needs, then he's right to look for a framework that does that. But I disagree about the purpose of frameworks. oyunlar In my opinion, the purpose of a framework is to enable a programmer to concentrate on what is important. When using the MVC architecture, then obviously a good framework should make it easy to focus on just the interesting parts of the model, view, controller, or any combination of the three.
Struts works well as a controller framework for applications with a pre-determined workflow and actions, because you just configure the connections between actions and other actions or views in XML files and start writing code. Your code is in the form of actions, which are an interface to the controller framework, and your own model, however you like it.
Freemarker is a framework for generating text so it works well with thin clients that consume HTML in order to implement the view, such as a web browser.
Hibernate is a helpful framework for managing the data storage aspect of the model. If your application is designed so that actions and workflows can be manipulated at runtime, then those are just data in your model and you could use a business rules or workflow framework to help you manage that, such as Drools. In that case, you might still want to use Struts or another controller framework to manage the non-dynamic portions of your application.
If your design includes a rich client, then you may want to use a rich client framework such as Flex or GWT to create that client. The rich client itself may be designed with an MVC architecture, treating the external behavior of your server application as the model and implementing in itself the controller and the view.
You get to decide in your design if the client is both controller and view or if a server implements the model and controller and the client is just the view. After you decide, pick the frameworks that help you write just the interesting parts.
Alex notes that there are many good frameworks for views and that the web servlet framework shouldn't reinvent that. He also says that he is interested in applications where the workflow and actions are manipulated at runtime. So for Alex, the task is to find a model framework that will manage his data source and workflows, so all he has to do is write the actions and let the framework arrange them and provide access to data. Then he has to find a controller framework that will complement this nicely. By the way, that framework could still be Struts (or Stripes, etc). Then he has to choose one of the many available view frameworks.
So I disagree with Alex about what the higher abstraction is. I think MVC is a higher abstraction than his special case of a certain type of web application, because MVC also works for other web applications and for non-web applications, where as Alex's abstraction doesn't.
autogenerator for primitive collections
2007-12-06 13:09:02 paultyma
[Reply | View]
just to add.. these are "real" primitive collections.. not autoboxed.
Highlighting autoboxing in editor
2007-11-29 03:31:16 wfrech
[Reply | View]
The reason why the sample code works is obviously autoboxing. In a sense, the primitives are boxed, but not explicitly.
The reason _for_ the autoboxing feature is more complicated. I would say, it works in most cases as the programmer expects. On the other hand, it introduces tricky effects, for example the add(1)/remove(1) bug, mentioned above.
A promising approach is highlighting auto-boxing/unboxing in the IDE. At least one could see that remove(1) is _not_ boxed.
Highlighting autoboxing in editor
2007-11-29 07:12:22 samkass
[Reply | View]
But it turns a whole class of bugs from a compile-time error to a runtime-error, and is generally a good way to introduce hard-to-debug performance problems.
Consider this misguided code:
Integer i = new Integer(2);
Integer j = new Integer(2);
assertTrue(i >= j); // success
assertTrue(i <= j); // success
assertTrue(i == j); // failure!
In this case, auto-boxing gets invoked for the >= and the <=, and they are compared as ints, since there is no definition for >= with regard to objects. But not for ==, since that operation is defined as pointer-comparison between the objects.
These types of bugs were hard enough to track down without auto-boxing. Any possible benefit auto-boxing brought in coding-time optimizations are more than lost in debug-time problems.
Autoboxing not reflected
2007-11-28 12:17:33 yardena
[Reply | View]
Coincidentally I just noticed that reflection APIs pretty much ignore auto-boxing - http://sensualjava.blogspot.com/2007/11/reflection-and-auto-boxing.html.
How does one submit a proposal to remove an existing feature from the language in JDK 7? If there's ever a feature that should be evaluated for removal, it's auto-boxing. It increases bugs, obfuscates meaning, hides performance problems, and in the end doesn't really save anyone much effort. And where it does, it often just moves the effort from early in the development process (where things are easy to fix) to later in the debugging process (where things are hard to fix).
A JSR that simply reads "Remove all 'auto-boxing' features from the language" would warm my heart.
I first compiled your code, then decompiled it. Here is the result:
public void boxItPrimitive()
{
int first = 1;
int second = 2;
int third = 3;
ArrayList listONumbers = new ArrayList();
listONumbers.add(Integer.valueOf(first));
listONumbers.add(Integer.valueOf(second));
listONumbers.add(Integer.valueOf(third));
for(int i = 0; i < listONumbers.size(); i++)
{
System.out.println(listONumbers.get(i));
}
}
This works, but is quite inefficient. If speed/memory performance become important, take a look at a library like Trove (http://trove4j.sourceforge.net/) which does primitive collections.
The compiler picks the exact method signature match. The compiler first attempts to match methods without the aid of box/unbox. If that fails, it will try to match with box/unbox applied.
This is why good interface design is a key. The problem is that they have overloaded the "remove" method with two different behaviors. One removes a specific value, one removes the object at a specific index.
In reality, they should have been named:
remove(Object object);
removeAt(int index);
But, due to backward compatibility, we're stuck with this, unless you want to use a third party library instead of java.util collections.
Autoboxing/unboxing brings extra responsibilities. Since you can add null as a valid entry, it will fail when you assume it will be retrieved as an int. For example
List<Integer> list = new ArrayList<Integer>();
list.add(1);
list.add(null);
for(int i:list)
System.out.println(i);
throws NullPointerException
It depends on java version
2007-11-27 06:48:20 riccardocossu
[Reply | View]
It depends on the java version you are using; java 1.5 and later have a feature called autoboxing which boxes the primitives for you whenever appropriate.
If you try it under java 1.4 or lower, you will see some errors :-)
It depends on java version
2007-11-27 06:58:57 riccardocossu
[Reply | View]
I didn't see the link on the top ;-)
Of course this is the case where the compiler does the boxing for you, so you write:
listONumbers.add(first);
but it is compiled as it was:
listONumbers.add(new Integer(first));
It depends on java version
2007-11-27 12:16:06 hontvari
[Reply | View]
It should be compiled as listONumbers.add(Integer.valueOf(first));
This way smaller Integer instances are shared, so no memory allocation is necessary.