java - Java获取数组类型的类
问题描述
new String[0].getClass()
有区别吗,如果有,那么和有什么区别String[].class
?
我对以下事实感兴趣(非详尽列表):
- 都初始化一个空数组吗?
- 这个空数组缓存在 JVM 中吗?
- 他们是否对某些数组类对象进行操作?
- 它们在字节码级别上是否相同?
注意:可能它以某种方式写在 JLS 中,但我在任何地方都找不到合适的描述。
解决方案
该表达式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(){}
}
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 的优化器很有可能会消除分配,以防它成为热点。
推荐阅读
- c++ - 指向派生类语法实例的基类对象数组?
- sql - 如何获取一个查询的结果并将该列表用作第二个表上另一个查询的键?
- awesome-wm - 很棒的 wm / 在不同的标签上保存应用程序窗口的大小和位置
- javascript - 使用javascript在滚动上缩放图像
- python - 玩家角色没有移动
- python - 编写类型提示时如何正确评估索引的类型?
- testing - 在全日历上拖放柏树测试的问题
- jupyter-notebook - OSX 10.13.6 KernelRestarter:重新启动内核
- php - 获取两个不同mysql表的结果
- batch-file - 批量复制重命名,重复时提示