Java中是否有内置方法来查找任何数据类型的大小?有什么方法可以找到尺寸?
Java中是否有内置方法来查找任何数据类型的大小?有什么方法可以找到尺寸?
Answers:
否。标准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-程序员可能需要知道以便设计节省空间的数据结构。但是,我无法想象为什么在运行时通过方法调用在应用程序代码中需要该信息。
来自JavaWorld中的文章
一个表面的答案是Java不提供C的sizeof()之类的东西。但是,让我们考虑一下为什么Java程序员偶尔会需要它。
AC程序员自己管理大多数数据结构的内存分配,而sizeof()对于了解要分配的内存块大小必不可少。另外,就对象初始化而言,像malloc()这样的C内存分配器几乎什么也不做:程序员必须设置所有对象字段,这些字段是指向其他对象的指针。但是,当一切都说完并编码后,C / C ++内存分配是相当有效的。
相比之下,Java对象的分配和构造是捆绑在一起的(不可能使用已分配但未初始化的对象实例)。如果Java类定义了引用其他对象的字段,则通常在构造时进行设置。因此,分配Java对象经常会分配许多互连的对象实例:一个对象图。再加上自动垃圾回收,这太方便了,可以让您感觉不必担心Java内存分配详细信息。
当然,这仅适用于简单的Java应用程序。与C / C ++相比,等效的Java数据结构倾向于占用更多的物理内存。在企业软件开发中,接近当今32位JVM上的最大可用虚拟内存是常见的可伸缩性约束。因此,Java程序员可能会受益于sizeof()或类似的东西来关注他的数据结构是否太大或是否存在内存瓶颈。幸运的是,Java反射使您可以非常轻松地编写这样的工具。
在继续之前,我将免除对本文问题的一些常见但不正确的答案。谬论:不需要Sizeof(),因为Java基本类型的大小是固定的
是的,在所有JVM和所有平台上,Java int均为32位,但这仅是该数据类型的程序员可感知宽度的语言规范要求。这样的int本质上是一种抽象数据类型,并且可以由64位计算机上的64位物理内存字进行备份。对于非原始类型也是如此:Java语言规范没有说明应如何在物理内存中对齐类字段,或者说布尔数组不能作为JVM内部的紧凑位向量实现。谬误:您可以通过将对象序列化为字节流并查看结果流的长度来测量对象的大小
之所以不起作用,是因为序列化布局仅是真实内存布局的远程反映。一种简单的查看方式是查看字符串的序列化方式:在内存中,每个字符至少为2个字节,但是以序列化形式,字符串是UTF-8编码的,因此任何ASCII内容都占用一半的空间
该Java本机访问库通常用于从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
EhCache提供了一个SizeOf类,该类将尝试使用Instrumentation代理,如果未加载或无法加载代理,则会退回到另一种方法(此处有详细信息)。
另请参阅Heinz Kabutz的经纪人。
试试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