Don’t Rely on Autoboxing in Java

Question: What does the following code display?

import java.awt.Color;

import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JLayeredPane;
import javax.swing.JPanel;

public class Demo {
  public static void main(String[] args) {
    JFrame frame = new JFrame();
    JLayeredPane container = new JLayeredPane();

    JPanel bottom = new JPanel();
    bottom.setBounds(0, 0, 400, 200);
    container.add(bottom); // default level is 0

    JLabel intLabel = new JLabel("I'm an int");
    intLabel.setBounds(0, 10, 400, 30);
    int layer = 10;
    container.add(intLabel, layer);

    JLabel integerLabel = new JLabel("I'm an Integer");
    integerLabel.setBounds(0, 50, 400, 30);
    container.add(integerLabel, new Integer(10));

    JLabel literalLabel = new JLabel("I'm a literal");
    literalLabel.setBounds(0, 100, 400, 30);
    container.add(literalLabel, 10);

    JLabel longLabel = new JLabel("I'm a long");
    longLabel.setBounds(0, 150, 400, 30);
    container.add(longLabel, new Long(10));

    frame.setSize(400, 200);


I'm an Integer


If you open docs for JLayeredPane, you can see the following code snippets:

layeredPane.add(child, new Integer(10));
layeredPaneParent.setLayer(child, 10);

You can see Integer there and literal 10 here. Subconsciously, you think: who cares, 10 is the same thing as new Integer(10) because Java has autoboxing, right? WRONG!

The only right way to interact with layeredPane.add is an Integer that you box yourself. Let’s take a peek at its source code…

protected void addImpl(Component comp, Object constraints, int index) {
    int layer = DEFAULT_LAYER.intValue();
    int pos;

    if(constraints instanceof Integer) { // A-ha!
        layer = ((Integer)constraints).intValue();
        setLayer(comp, layer);
    } else
        layer = getLayer(comp);

    pos = insertIndexForLayer(layer, index);
    super.addImpl(comp, constraints, pos);

Ironically, even though it uses int internally, it wouldn’t recognize it as a parameter.


Autoboxing works, except for when it doesn’t. Be defensive with APIs (even core Java) and when something is wrong do try all those ideas that seem obviously crazy at first. When writing your own API that uses type identification, remember that int and Integer are completely different beasts and both need to be included.

This example is from Swing, but it can happen anywhere. I’ve tripped on this issue before when I was implementing a CRUD framework or renderers, but did not expect it in core library.


As frimble pointed out at reddit, there is one more reason why it would never work. In addition to add(Component comp, Object constraints), Container also has add(Component comp, int index).

Having two overloaded versions of a method, one of them accepting Integer and another for int, when both do completely different things, is even worse than what I criticized in the first place.

Rant: Yet another example of extremely poor design in core Java API. Just like Object.equals() having specification that’s impossible to meet in a reasonable way or the hierarchy of java.util.Date. They use Java to teach OOP. Apparently it’s just as good for teaching how NOT to program.

Leave a Reply

Your email address will not be published. Required fields are marked *

Spam protection by WP Captcha-Free