Java中是否有类似sizeof的方法?


Answers:


61

否。标准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-程序员可能需要知道以便设计节省空间的数据结构。但是,我无法想象为什么在运行时通过方法调用在应用程序代码中需要该信息。


14

来自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内容都占用一半的空间


6
“幸运的是,Java反射使您可以非常轻松地编写这样的工具。” 怎么样?
dfrankow 2012年

我一直想知道“参考”的大小是多少?
Marichyasana

11

Java本机访问库通常用于从Java调用本地共享库。在该库中,存在确定Java对象大小的方法:

getNativeSize(Class cls)方法及其重载将为大多数类提供大小。

另外,如果您的类继承自JNA的Structure类,则该calculateSize(boolean force)方法将可用。


1
感谢您的回答!尝试使用JNA,其中使用C的sizeof()派生参数,而这正是我所需要的!
丹尼尔·威迪斯

@sprocketonline-链接已断开,您能否更新它们
Naman

10

您可以像下面那样进行位操作来获取基元的大小:

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;
}

2
sizeof(用C语言)返回字节数,而这些例程将返回位数。
LarsH

5
使用i<<8代替将给出字节数。
理查德·孙

好吧,是的,您可以像这样计算字节/位,但这是不必要的。Java语言规范保证代表每种基本类型所需的字节数永远不会改变。
Stephen C

9

如前所述这里,也有可能通过他们的包装来获得原始类型的大小。

例如对于long这可能是Long.SIZE / Byte.SIZE从Java 1.5(如zeodtr所述)或Long.BYTES从Java 8


4

有一种当代方法可以对原始数据进行处理。使用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

3

对于Java 1.5中的原始类型,可以使用Integer.SIZE / 8,Double.SIZE / 8等。


1

Instrumentation类具有getObjectSize()方法,但是,您无需在运行时使用它。检查内存使用情况的最简单方法是使用探查器,该探查器旨在帮助您跟踪内存使用情况。



1

我决定在不遵循标准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;
}

1

试试java.lang.Instrumentation.getObjectSize(Object)。但是请注意

它返回指定对象消耗的特定于实现的近似值。结果可能包括对象的部分或全部开销,因此对于在实现中进行比较(而不是在实现之间进行比较)很有用。在JVM的一次调用期间,估计值可能会更改。


0

SourceForge.net上有一个可用的类/ jar,它使用Java工具来计算任何对象的大小。这是描述的链接:java.sizeOf


0

只是一些测试:

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

-1

我不认为它在Java API中。但是其中包含许多元素的大多数数据类型都有一个size()方法。我认为您可以轻松编写一个函数来自行检查大小?


-1

是的..在JAVA中

System.out.println(Integer.SIZE/8);  //gives you 4.
System.out.println(Integer.SIZE);   //gives you 32.

//Similary for Byte,Long,Double....
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.