Java获取数组类型的类

时间:2018-09-17 13:35:34

标签: java arrays jvm

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

我对诸如(非详尽列表)之类的事实感兴趣:

  • 都初始化一个空数组吗?
  • 这个空数组是否缓存在JVM中?
  • 它们对某些数组类对象起作用吗?
  • 在字节码级别上是否相同?

注意:也许它是用JLS编写的,但是我在任何地方都找不到合适的描述。

1 个答案:

答案 0 :(得分:3)

表达式new String[0].getClass()被直接编译为指令以创建新数组,然后调用getClass()。相反,类文字String[].class被编译成单个ldc指令,如“How is a class literal compiled to Java bytecode?”所述。

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

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

Demo on 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运算符得到了保证,可以产生具有不同标识的新对象,即{{1 }}。但是在这样的用例中,实例是临时的,并且不执行任何对身份敏感的操作,因此,如果它成为热点,JVM的优化器很可能会取消分配。