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(); frame.setContentPane(container); JPanel bottom = new JPanel(); bottom.setBounds(0, 0, 400, 200); bottom.setBackground(Color.WHITE); 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); frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); frame.setVisible(true); } }

Answer

Explanation

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); comp.validate(); comp.repaint(); validateOptimizedDrawing(); }

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

Conclusion

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.

Update

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.