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.

2 Answers 2

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) {...}
Sign up to request clarification or add additional context in comments.

8 Comments

+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 Correct, that's what is going on.
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 They cannot possibly be the same object - your first example demonstrates it perfectly.
I'm meaning with a lowercase 'f'. According to an evaluation float.class == Float.TYPE. I edited my question with a bit about this.
|
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").

2 Comments

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.
"...the literals are (possibly) replaced during compilation..." And I suppose compiling to the same bytecode proves it.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.