首页 > 解决方案 > Java获取数组类型的类

问题描述

new String[0].getClass()有区别吗,如果有,那么和有什么区别String[].class

我对以下事实感兴趣(非详尽列表):

注意:可能它以某种方式写在 JLS 中,但我在任何地方都找不到合适的描述。

标签: javaarraysjvm

解决方案


该表达式new String[0].getClass()被直接编译为创建新数组的指令,然后调用getClass(). 相反,类文字String[].class被编译为一条ldc指令,如“如何将类文字编译为 Java 字节码?”</a> 中所述。

您可以通过运行以下程序来验证这一点

package jvm;

import javax.tools.ToolProvider;

public class GetArrayClass {
    public static Class<?> viaGetClass() {
        return new String[0].getClass();
    }
    public static Class<?> viaClassLiteral() {
        return String[].class;
    }
    public static void main(String[] args) {
        decompile();
    }
    private static void decompile() {
        Object args = new String[]{"-c", GetArrayClass.class.getName()};
        try {
            ToolProvider.getSystemJavaCompiler().getClass().getClassLoader()
                .loadClass("com.sun.tools.javap.Main")
                .getMethod("main", String[].class).invoke(null, args);
        } catch(ReflectiveOperationException ex) {
            throw new IllegalStateException(ex);
        }
    }
    private GetArrayClass(){}
}

Ideone 上的演示

public static java.lang.Class<?> viaGetClass();
    Code:
       0: iconst_0
       1: anewarray     #1                  // class java/lang/String
       4: invokevirtual #2                  // Method java/lang/Object.getClass:()Ljava/lang/Class;
       7: areturn

public static java.lang.Class<?> viaClassLiteral();
    Code:
       0: ldc           #3                  // class "[Ljava/lang/String;"
       2: areturn

该表达式new String[0]不能被共享数组替换,因为该new运算符保证生成具有不同标识的新对象,即new String[0] != new String[0]. 但是在这样的用例中,实例是临时的并且没有执行身份敏感操作,JVM 的优化器很有可能会消除分配,以防它成为热点。


推荐阅读