3

See Boolean#TYPE for an example of what I'm referring to.

All of the wrapper classes (Boolean, Double, Integer, etc) have a static Class field associated with them called TYPE. What is the meaning of this?

Specifically, here are a few soft tests:

System.out.println(Boolean.class == Boolean.TYPE);
System.out.println(Boolean.TYPE.isInstance(Boolean.valueOf(true)));

Both evaluate as false. (And as a side note, an .equals comparison is unnecessary since Class does not override equals from Object.)

Both Boolean.class and Boolean.TYPE are Class<Boolean> because they are == comparable without an error. Comparing two objects with differently declared generic types is illegal.

On further inspection, the TYPE fields are retrieved by calling a package-private native method Class#getPrimitiveClass along the lines of the following:

public static final Class<Boolean> TYPE = Class.getPrimitiveClass("boolean");

The comment on the method itself is not particularly informative either. It says it returns the VM's class object for the type which is fairly obvious since it is a native method.

I can't find any documentation on this beyond the Java docs' vague allusion to "representing the primitive type". Is there some kind of use for this field? It's unused in the wrapper classes themselves.

(Edited)

System.out.println(boolean.class == Boolean.TYPE);

Is true.

Also one use is then reflection:

try {
    Constructor ctor = Boolean.class.getConstructor(Boolean.class);
} catch (Exception e) {
    System.out.println("NoSuchMethodException gets thrown");
}

try {
    Constructor ctor = Boolean.class.getConstructor(Boolean.TYPE);
    System.out.println(ctor.newInstance(true));
} catch (Exception e) {
    // (no exception thrown)
}

And I've found some SO threads that cite that, such as this one. I guess I came from the "wrong end" of Google so-to-speak to not find any results on it.

But considering the existence of the "primitive classes" (boolean.class, int.class etc.) that doesn't really explain the TYPE field existence. Basically it's "just there"? I still don't really get it.

Community
  • 1
  • 1
Radiodef
  • 37,180
  • 14
  • 90
  • 125

2 Answers2

4

The class representing the primitive type is useful in specifying or examining methods that take or return primitives. For example, if your class has a method that looks like this

class Test {
    static int round(float val) {...}
}

and you wish to access this method through reflection, you would need to do this:

Method round = Test.class.getMethod("round", Float.TYPE);

You can examine the return type, too:

if (round.getReturnType == Integer.TYPE) {
    System.out.println("Method 'round' returns an int.");
}

Using Float.class instead

Method round = Test.class.getMethod("round", Float.class);

would not work, because that would pull a different method - this one:

static int round(Float val) {...}
Sergey Kalinichenko
  • 714,442
  • 84
  • 1,110
  • 1,523
  • 1
    +1 So in other words, `Float.TYPE` refers to the actual primitive class, but `Float.class` returns to the wrapper type that extends `Object`. – mellamokb Nov 26 '13 at 03:59
  • @mellamokb Correct, that's what is going on. – Sergey Kalinichenko Nov 26 '13 at 04:00
  • Do you know if there's any distinction between, say `Float.TYPE` and `float.class`? I mean *technically*, not just *in use* since they are apparently the same object at run time. – Radiodef Nov 26 '13 at 04:02
  • 1
    @Radiodef They cannot possibly be the same object - your first example demonstrates it perfectly. – Sergey Kalinichenko Nov 26 '13 at 04:05
  • I'm meaning with a lowercase 'f'. According to an evaluation `float.class == Float.TYPE`. I edited my question with a bit about this. – Radiodef Nov 26 '13 at 04:07
  • In the end I guess the `float.class`/`Float.TYPE` distinction doesn't really matter, but now I'm curious where the "primitive.class" comes from. That's really a different question though. Thanks. : ) – Radiodef Nov 26 '13 at 04:14
  • @Radiodef I am reasonably sure that `float.class` syntax has been enabled after `Float.TYPE`, which has been around since Java 1.1. I remember trying to find the class for the primitive `int` back in Java 1.2 times (way before stack overflow sites), and finally finding `Integer.TYPE`. I'm nearly certain that I've tried `int.class` at some point, but it did not work. – Sergey Kalinichenko Nov 26 '13 at 04:17
  • I'm a bit late, but the reason that both, `float.class` and `Float.TYPE` exists, is quiet simple: the former gets compiled to the latter. Since there is no byte code operation to get the `Class` for a primitive type, there is an API needed for that. That's also the reason why the initialization of the `TYPE` field uses a `native` method; there is no ordinary operation to get the `Class` object and using a class literal at this point would be circular. For non-primitive types [this answer](https://stackoverflow.com/a/46060724/2711488) applies. – Holger Jan 20 '18 at 14:37
1

(Don't have the rep to comment, so must answer.)

To put it succinctly: Float.TYPE == float.class, and Float.class != float.class. Consider:

class Test {
    void func() {
        Class clazz;
        // The two statements do the same thing.  On my system, they even compile
        //   to the same bytecode.
        clazz = Integer.TYPE;    // explicitly asking for this
        clazz = int.class;       // must yield the same object as above.

        // Both of these below are valid, as the `true' is autoboxed.  In 
        //   Java < 1.5, both had to be explicitly boxed
        Test.class.getMethod("test", Boolean.class).invoke(this, true);
            // calls method A
        Test.class.getMethod("test", boolean.class).invoke(this, true);
            // calls method B.  Could also use getMethod("test", Boolean.TYPE) 
    }

    void test(Boolean b) { System.out.println("Method A"); }
    void test(boolean b) { System.out.println("Method B"); }
}

I would assume both int.class andInteger.TYPE have been around from the beginning of Java, though I may be wrong. Integer.TYPE can be initially assigned with Class.getPrimitiveClass("int").

Menachem
  • 911
  • 7
  • 22
  • After doing some more searching I've found that the .class literals are just basically shortcuts for the .TYPE fields. They were both added at the same time with the reflection API (Java 1.1) and the literals are (possibly) replaced during compilation similar to autoboxing. – Radiodef Dec 09 '13 at 22:58
  • *"...the literals are (possibly) replaced during compilation..."* And I suppose compiling to the same bytecode proves it. – Radiodef Dec 09 '13 at 23:11