【发布时间】:2010-03-03 10:15:01
【问题描述】:
Java 中是否有任何内置方法来查找任何数据类型的大小? 有什么方法可以找到尺寸吗?
【问题讨论】:
-
您可能会发现 javaworld.com/javaworld/javaqa/2003-12/02-qa-1226-sizeof.html 有趣的阅读(顺便说一句,这是我在谷歌上搜索“sizeof Java”时得到的第一个结果)。
标签: java
Java 中是否有任何内置方法来查找任何数据类型的大小? 有什么方法可以找到尺寸吗?
【问题讨论】:
标签: java
没有。标准的 Java SE 类库中没有这样的方法。
设计者的观点是 Java 不需要它,因为该语言不需要应用程序1 知道需要为原始值(对象)保留多少空间或具有给定元素数量的数组。
您可能认为 sizeof 运算符对于需要知道其数据结构占用多少空间的人很有用。但是,您也可以使用 Java 内存分析器简单可靠地获取这些信息及更多信息,因此不需要 sizeof 方法。
之前的评论者指出sizeof(someType) 比4 更具可读性。如果您接受该可读性论点,那么补救措施就在您手中。像这样简单地定义一个类...
public class PrimitiveSizes {
public static int sizeof(byte b) { return 1; }
public static int sizeof(short s) { return 2; }
// etcetera
}
...并静态导入它...
import static PrimitiveSizes.*;
或者定义一些命名常量;例如
public static final int SIZE_OF_INT = 4;
或者(Java 8 及更高版本)使用Integer.BYTES 常量,依此类推。
为什么 Java 设计者没有在标准库中实现这一点?我的猜测是:
还有一个问题是下一个需求是sizeof(Object o)方法,这充满了技术困难。
上面的关键词是“他们”!
1 - 程序员可能需要知道以设计节省空间的数据结构。但是,我无法想象为什么在运行时通过方法调用在应用程序代码中需要这些信息。
【讨论】:
一个肤浅的答案是 Java 没有提供像 C 的 sizeof() 这样的东西。然而, 让我们考虑一下为什么 Java 程序员可能偶尔需要它。
C 程序员自己管理大多数数据结构内存分配, 并且 sizeof() 对于了解内存块大小是必不可少的 分配。此外,像 malloc() 这样的 C 内存分配器几乎 就对象初始化而言,什么都没有:程序员 必须设置所有指向更多对象的对象字段。但 综上所述,C/C++ 内存分配相当 高效。
相比之下,Java 对象的分配和构造是绑在一起的 一起(不可能使用已分配但未初始化的 对象实例)。如果 Java 类定义了引用的字段 为了进一步的对象,将它们设置在构造中也很常见 时间。因此,分配一个 Java 对象经常会分配大量 互连的对象实例:对象图。再加上 自动垃圾收集,这太方便了,可以使 你觉得你永远不必担心 Java 内存分配 详情。
当然,这只适用于简单的 Java 应用程序。和....相比 C/C++,等价的Java数据结构往往占用更多的物理 记忆。在企业软件开发中,越来越接近 当今 32 位 JVM 上的最大可用虚拟内存是常见的 可扩展性约束。因此,Java 程序员可以从 sizeof() 或类似的东西来密切关注他的 数据结构变得太大或包含内存瓶颈。 幸运的是,Java 反射允许你编写这样一个工具 很容易。
在继续之前,我将省略一些经常但不正确的 本文问题的答案。谬误:不需要 Sizeof() 因为 Java 基本类型的大小是固定的
是的,Java int 在所有 JVM 和所有平台上都是 32 位的,但这 只是语言规范要求 此数据类型的程序员可感知宽度。这样的 int 是 本质上是一种抽象数据类型,并且可以由例如 64 位机器上的 64 位物理内存字。这同样适用于 非原始类型:Java 语言规范只字未提 类字段应如何在物理内存或数组中对齐 的布尔值无法实现为内部的紧凑位向量 JVM。谬误:您可以通过将对象序列化为 一个字节流并查看生成的流长度
这不起作用的原因是因为序列化布局是 只是真实内存布局的远程反映。一种简单的方法 通过查看字符串如何序列化来查看它:在内存中 char 至少为 2 个字节,但以序列化形式字符串为 UTF-8 编码,因此任何 ASCII 内容占用一半的空间
【讨论】:
Java Native Access 库通常用于从 Java 调用本机共享库。在这个库中,存在确定 Java 对象大小的方法:
getNativeSize(Class cls) 方法及其重载将为大多数类提供大小。
或者,如果您的类继承自 JNA 的 Structure 类,则 calculateSize(boolean force) 方法将可用。
【讨论】:
您可以像下面这样进行位操作来获取图元的大小:
public int sizeofInt() {
int i = 1, j = 0;
while (i != 0) {
i = (i<<1); j++;
}
return j;
}
public int sizeofChar() {
char i = 1, j = 0;
while (i != 0) {
i = (char) (i<<1); j++;
}
return j;
}
【讨论】:
i<<8 会给出字节数。
对于基元,有一种现代方法可以做到这一点。使用BYTES 的类型。
System.out.println("byte " + Byte.BYTES);
System.out.println("char " + Character.BYTES);
System.out.println("int " + Integer.BYTES);
System.out.println("long " + Long.BYTES);
System.out.println("short " + Short.BYTES);
System.out.println("double " + Double.BYTES);
System.out.println("float " + Float.BYTES);
结果,
byte 1
char 2
int 4
long 8
short 2
double 8
float 4
【讨论】:
对于 Java 1.5 中的原始类型,您可以使用 Integer.SIZE / 8、Double.SIZE / 8 等。
【讨论】:
Instrumentation 类有一个 getObjectSize() 方法,但是,您不需要在运行时使用它。检查内存使用情况的最简单方法是使用旨在帮助您跟踪内存使用情况的分析器。
【讨论】:
EhCache 提供了一个SizeOf 类,该类将尝试使用Instrumentation 代理,如果代理未加载或无法加载(details here),它将回退到不同的方法。
【讨论】:
我决定在不遵循标准 Java 约定的情况下创建一个枚举。也许你喜欢这个。
public enum sizeof {
;
public static final int FLOAT = Float.SIZE / 8;
public static final int INTEGER = Integer.SIZE / 8;
public static final int DOUBLE = Double.SIZE / 8;
}
【讨论】:
试试java.lang.Instrumentation.getObjectSize(Object)。但请注意
它返回指定对象消耗的存储量的特定于实现的近似值。结果可能包括对象的部分或全部开销,因此对于实现内的比较有用,而不是实现之间的比较。估计值可能会在 JVM 的单次调用期间发生变化。
【讨论】:
SourceForge.net 上有一个可用的类/jar,它使用 Java 工具来计算任何对象的大小。这是描述的链接:java.sizeOf
【讨论】:
只是一些测试:
public class PrimitiveTypesV2 {
public static void main (String[] args) {
Class typesList[] = {
Boolean.class , Byte.class, Character.class, Short.class, Integer.class,
Long.class, Float.class, Double.class, Boolean.TYPE, Byte.TYPE, Character.TYPE,
Short.TYPE, Integer.TYPE, Long.TYPE, Float.TYPE, Double.TYPE
};
try {
for ( Class type : typesList ) {
if (type.isPrimitive()) {
System.out.println("Primitive type:\t" + type);
}
else {
boolean hasSize = false;
java.lang.reflect.Field fields[] = type.getFields();
for (int count=0; count<fields.length; count++) {
if (fields[count].getName().contains("SIZE")) hasSize = true;
}
if (hasSize) {
System.out.println("Bits size of type " + type + " :\t\t\t" + type.getField("SIZE").getInt(type) );
double value = type.getField("MIN_VALUE").getDouble(type);
long longVal = Math.round(value);
if ( (value - longVal) == 0) {
System.out.println("Min value for type " + type + " :\t\t" + longVal );
longVal = Math.round(type.getField("MAX_VALUE").getDouble(type));
System.out.println("Max value for type " + type + " :\t\t" + longVal );
}
else {
System.out.println("Min value for type " + type + " :\t\t" + value );
value = type.getField("MAX_VALUE").getDouble(type);
System.out.println("Max value for type " + type + " :\t\t" + value );
}
}
else {
System.out.println(type + "\t\t\t type without SIZE field.");
}
} // if not primitive
} // for typesList
} catch (Exception e) {e.printStackTrace();}
} // main
} // class PrimitiveTypes
【讨论】:
我不认为它在 java API 中。但大多数包含许多元素的数据类型都有size() 方法。我认为您可以轻松编写一个函数来检查自己的大小?
【讨论】:
是的..在 JAVA 中
System.out.println(Integer.SIZE/8); //gives you 4.
System.out.println(Integer.SIZE); //gives you 32.
//Similary for Byte,Long,Double....
【讨论】: