Java新建大小为2^32的字节数组

9
在Java中,我不能像这样使用long:
long size = 0xFFFFFFFF; //2^32-1

byte [] data = new byte[size];

int类型的取值范围最高只能达到0x7FFFFFFF (2^31-1)。是否有可能声明一个这样大小的字节数组?


不一定是重复的,但请参考此链接:https://dev59.com/YXA75IYBdhLWcg3w6Nn8 - John
谢谢,那基本上回答了我的问题。 - Eric B
我本来想说的是,数组中不能有超过2^31-1个元素。而且正如我们所看到的,在某些情况下,甚至都无法达到这个数量。 - biziclop
1
(2^31 - 1) == 0x7FFFFFFF。只是让你知道。 - cHao
6个回答

10

答案是,因为这是最大可能的初始化:

    int size = Integer.MAX_VALUE;
    byte [] data = new byte[size];

1
实际上,即使这样做也不能保证数组能正常工作,特别是如果JVM使用低内存级别。 - Bruno Vieira
@BrunoVieira:确实,需要内存。 - Yogendra Singh
请参阅Java数组是否有最大大小限制 - Hollis Waite

3

你示例中的问题在于数组创建函数需要一个 int 类型的参数,而你传递了一个 long 类型的参数。

以下代码可以编译通过:

long size = 0xFFFFFFFF; //2^32-1

byte [] data = new byte[(int)size];

但是它不能运行。在这个特定的long示例中,它无法运行,因为数字是负数,而且你不能用负数元素创建数组。但是仍然可以使用长变量来创建数组,但需要是正数并需要转换为int,如下所示:

long size = 0x00FFFFFF; //

byte [] data = new byte[(int)size];

这样编译和使用都没有问题。

另外,如果将大小更改为Integer.MAX_VALUE,而此值超过了JVM的内存限制,则不会有任何效果。


我不明白那怎么可能行得通,那个int难道不是负数、INT_MAX或者其他什么吗?在转换后它不可能真的是2^32-1。 - Eric B
内存管理(大部分时间)是JVM的问题。 - Bruno Vieira
1
它编译通过,但在第二行抛出java.lang.NegativeArraySizeException异常,因为(int)size的值为-1 - Yogendra Singh
你看,这是因为你将一个负整数作为参数传递。因此,不可能创建具有负元素的数组。它编译成功是因为强制转换仅在运行时可用,这时它会报NegativeArraySizeException异常。 - Bruno Vieira
更好了。 :) 似乎主要问题不在于操作数大小,而是值的问题,所以。 - cHao
显示剩余2条评论

3

size 声明为 int ,然后再试一次:

int size = 0x7FFFFFFF; // 0x7FFFFFFF == Integer.MAX_vALUE == 2^32-1

一个数组只能声明为具有正的 int 大小,而不是 long。请注意,最大的 int 正值(因此,整数数组的最大可能大小,假设有足够的内存可用)为 0x7FFFFFFF == Integer.MAX_VALUE

一个32位的整数无法存储那么大的值。 - Eric B

3

在许多Java概念中,Integer.MAX_VALUE是限制。例如,String/List的长度不能超过该值。

回到1995年Java创建时,4MB的总内存是常态。

大多数语言都存在同样的问题。但如果我们今天设计一种新语言,肯定会使用long。


1
Java开发人员肯定知道比4GB大得多的内存大小。Sun E10000于1997年发货,是从1996年7月开始计划的Sun产品,支持高达64 GB的内存。它是在Cray Research内部开发的,基于Sun处理器,并在此之前为Sun所知。 - Patricia Shanahan

2

1
你不需要源代码,JLS非常清楚地表明数组索引只能是“int”或其他可以提升为“int”的类型。 - biziclop

2

我同意您不能使用超过Integer.MAX_VALUE个元素的byte[],但是您可以有一个数组的数组。

我建议编写一个类,该类具有:

  • 一个构造函数,它需要一个long类型的size参数,并构建一个足够大的byte[][]来容纳那么多的元素。

  • 使用long类型的索引的Get和Set方法

  • 一个返回long类型的size()方法。

当然,这仅在64位JVM和足够大的内存的情况下才实用。

我甚至在上世纪90年代就感到,选择int而不是long作为数组索引和长度类型是短视的。Sun公司正在销售许多具有数十GB内存的机器,并且最大数组大小逐渐接近内存大小,内存大小也在增长。


Java最初是为在消费者个人电脑上运行小应用程序而设计的。 - irreputable
我很难找到一个4GB数组的实际用途。如果你需要这样一个数组,那很可能是设计错误。 - biziclop
@biziclop 这是我想到的第一个例子 - 用每个碱基对一个字节来表示基因组。即使是人类基因组,有30亿个碱基对,也太大了,无法放入单个Java数组中。一些植物的基因组比人类的还要大得多。 - Patricia Shanahan
我还应该补充一点,在20世纪70年代,我听到过关于数组大小超过64K元素的类似反对意见。内存大小和最大数组大小不断增加是一个持续的历史。 - Patricia Shanahan
@PatriciaShanahan 为什么面向对象的语言适合进行纯数据计算?因人而异。虽然一个虚拟机可用的最大 RAM 不超过1TB,但单个对象超过4G却没有太大意义。当这开始有意义时,将数组索引更改为 long 类型会相对容易且不会带来太多麻烦。 - biziclop
我被告知,即使一些计算机有几兆字节的内存,一个单独大于64 KB的对象也没有意义。今天有什么不同吗?每个数组大小都经历了一个阶段,从不可能到正常,途中有些程序员认为它太大了,没有意义,尽管在某些应用程序中是物理上可支持和需要的。 - Patricia Shanahan

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接