12

I recently learned that there are Class representations for the primitive types in the JVM. For example, int.class, double.class, and even a void.class.

What I don't understand is why these are there. They don't seem to serve any functional role. Using reflection, I searched through the classes, and they have no constructors, no methods, and no fields. For all intents and purposes, they seem empty and useless. The primitive type variables are not even instances of their respective classes, as indicated by the following returning false:

int a = 3;
int.class.isInstance(a);

So why do they exist? They must serve some purpose, maybe for the compiler or something, but whatever it is is completely beyond me. There is even an explicit reference to int.class in the Integer API (and likewise for each primitive type and its respective wrapper Object). I haven't been able to find any reference to their existence, much less their use, in the JLS.

asteri
  • 11,402
  • 13
  • 60
  • 84

2 Answers2

12

What I don't understand is why these are there.

Consider the following:

public int foo() {
    return 0;
}

...

Method method = someClass.getDeclaredMethod("foo");
Class<?> clazz = method.getReturnType();

Without a Class representation of int, what would the above return? It shouldn't return Integer.class as they're not the same thing. (Imagine trying to distinguish between methods which were overloaded, one with an int and one with an Integer parameter.)

I've used these classes before to provide default values for arguments when calling them via reflection. Based on the parameter type, I've used null for any reference type, and some (boxed, obviously) primitive value for each of the primitive types.

Jon Skeet
  • 1,421,763
  • 867
  • 9,128
  • 9,194
  • 2
    @Jeff: No, reflection isn't only used by the compiler, is it? – Jon Skeet Nov 02 '12 at 14:29
  • @Jeff: What? No, I never suggested the compiler would do that. Where did you get that idea from? I'm suggesting that `int.class` and the like are useful for values in reflection APIs where we need to be able to represent a return type or parameter type which is a primitive type. Note that my answer doesn't even contain the word "compiler". – Jon Skeet Nov 02 '12 at 14:36
  • 2
    A use case: implementing getColumnClass() of Swing TableModel. – Puce Nov 02 '12 at 14:48
  • @Jeff: No, I provided *user* code which was calling `getDeclaredMethod()` and `getReturnType()`... – Jon Skeet Nov 02 '12 at 14:49
2

It is a cheap ass solution that turns out badly.

Before 1.5, Java types can be categorized as

java type
    primitive type
    reference type
        class type (including interface)
        array type

Then ideally, java reflection should provide 5 concepts mirroring these 5 types. But they used a single Class to represent them all, including primitive and array types. So a Class does not necessarily mean a class.

That's still manageable. But after 1.5, Java types become more complicated, so a new Type is introduced. Unfortunately, instead of having a new and clean hierarchy that directly mirror language spec, they decides to make Class a subtype of Type; not only the old mess is brought in, it spawns some new mess, and the whole Type hierarchy is unintelligible.

irreputable
  • 44,725
  • 9
  • 65
  • 93
  • While I agree that `Type` is a pain in the neck, I don't think it has much to do with this question. Put it this way: I believe the question would still have made sense back when Java was at 1.4, but your answer wouldn't. – Jon Skeet Nov 02 '12 at 17:49
  • `int.class` and `"Class for int"` are all cheap dirty hacks from day one. It wasn't too big a deal before 1.5, but now the mistake is more apparent after more types are introduced. – irreputable Nov 02 '12 at 17:56
  • 1
    Well I certainly prefer the C# syntax, but I still say your answer doesn't have much to do with the question, and is more of an off-topic rant. – Jon Skeet Nov 02 '12 at 18:06