原始包装器和静态“TYPE”类对象

时间:2013-11-26 03:47:04

标签: java class types wrapper primitive

请参阅Boolean#TYPE,了解我所指的内容。

所有包装类(Boolean,Double,Integer等)都有一个与之关联的静态类字段TYPE。这是什么意思?

具体来说,这里有一些软测试:

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

两者都评价为假。 (并且作为旁注,.equals比较是不必要的,因为Class不会从Object重写equals。)

Boolean.classBoolean.TYPE都是Class<Boolean>,因为它们==可比,没有错误。使用不同声明的泛型类型比较两个对象是非法的。

在进一步检查时,通过调用包 - 私有本机方法TYPE来检索Class#getPrimitiveClass字段,如下所示:

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

对方法本身的评论也不是特别有用。它表示它返回VM的类对象,因为它是一种本机方法,因此非常明显。

我找不到任何有关此文档的文档,除了Java文档的模糊暗示“表示原始类型”。这个领域有用吗?它在包装器本身中没有使用。

(编辑)的

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

是真的。

然后还有一个用途就是反思:

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)
}

我发现了一些引用它的SO线程,例如this one。我想我来自谷歌的“错误结局”,因此没有找到任何结果。

但考虑到“原始类”(boolean.classint.class等)的存在并不能真正解释TYPE字段的存在。基本上它就是“就在那里”?我仍然没有得到它。

2 个答案:

答案 0 :(得分:4)

表示基本类型的类在指定或检查获取或返回基元的方法时很有用。例如,如果您的类有一个类似于此的方法

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

并且您希望通过反射访问此方法,您需要执行此操作:

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

您也可以检查返回类型:

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

使用Float.class代替

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

不会起作用,因为那将采用不同的方法 - 这一个:

static int round(Float val) {...}

答案 1 :(得分:1)

(没有代表发表评论,所以必须回答。)

简明扼要地说:Float.TYPE == float.classFloat.class != float.class。考虑:

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"); }
}

我认为int.classInteger.TYPE都是从Java开头出现的,尽管我可能错了。 Integer.TYPE最初可以Class.getPrimitiveClass("int")分配。