Java获取数组类型的类

问题描述 投票:-1回答:1

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

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

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

注意:可能它以某种方式写在JLS中,但我无法在任何地方找到正确的描述。

java arrays jvm
1个回答
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运算符可以保证生成具有不同标识的新对象,即new String[0] != new String[0]。但是在这样的用例中,实例是临时的并且没有执行身份敏感操作,如果JVM的优化器成为热点,JVM的优化器将消除分配的可能性很高。

© www.soinside.com 2019 - 2024. All rights reserved.