Java数组长度小于0?

28

我在查看一个开源项目时,他们正在创建一个输出流,并遇到了以下方法:

@Override public void write(byte[] buffer, int offset, int length) {
    if (buffer == null) {
        throw new NullPointerException("buffer is null");
    }
    if (buffer.length < 0) { // NOTE HERE
        throw new IllegalArgumentException("buffer length < 0");
    }
    if (offset < 0) {
        throw new IndexOutOfBoundsException(String.format("offset %d < 0", offset));
    }
    if (length < 0) {
        throw new IndexOutOfBoundsException(String.format("length %d < 0", length));
    }
    if (offset > buffer.length || length > buffer.length - offset) {
        throw new IndexOutOfBoundsException(String.format("offset %d + length %d > buffer"                                                       " length %d", offset, length, buffer.length));
    }
}

byte[] buffer只是一个普通的老旧的byte[]数组。我们知道它不是null。它是否可能具有小于0的长度?比如,通过反射可以实现吗,这就是他们需要防范的吗?


3
@EdwardThomson说:“我认为是因为第一个语句检查 buffer == null。” - Greg Hewgill
4
无法有这样的约定。你无法让 array.length < 0 - Marko Topolnik
3
@thalador这里有很多情况下int可以是-1,但数组的长度不能为-1(这是正在检查的内容)。 - yshavit
2
这个方法奇怪的地方在于它什么也没有写。作者是否因为断言而忙得无法编写有用的内容? - Denys Séguret
1
@a_horse_with_no_name 我也见过很多这样的情况,并且我自己也写过一些,但总是在语言不会对那个变量小于0有问题的情况下。现在要检查的是无符号值是否小于0——比如你要检查一个char是否小于0。 - Marko Topolnik
显示剩余15条评论
3个回答

35

不,这是不可能发生的。根据Java规范,长度保证为非负数。

数组类型的成员如下:

  • 公共final字段长度,其中包含数组的组件数。 长度可以是正数或零

来源:JLS §10.7

正如mprivat提到的那样,如果您尝试创建一个负大小的数组,将引发NegativeArraySizeException异常。


9
因为程序员从不犯错误,总是编写最优代码。 - tskuzzy

7

我不相信这是可能的。即使通过反射,它也会被NegativeArraySizeException保护。


1
我尝试通过反射的方式改变数组的长度,但是发现自己无法这样做。getDeclaredFields() 方法对于数组输入返回一个空结果,而 Array 反射类理所当然地没有这样的方法(因为你为什么需要它呢?)我认为除了直接修改内存之外,没有其他方法可以做到这一点,但我怀疑实际上并没有检查会阻止这样做。当然,如果程序在修改内存,那么你面临的问题比参数检查更大... - corsiKa
是的,我认为那只是糟糕的代码。唯一能实现这一点的方法是以某种方式进行字节码修改。而且坦率地说,即使这样做,如果长度以无符号数编码(我怀疑是这种情况),我也不确定你能否成功。 - mprivat
我认为不是这样的,因为你无法编译 int[] a = new int[3000000000]; - 我猜它会像其他任何一个 int 一样被存储。 - corsiKa
你是对的。因为int[] a = new int[-1];确实可以编译通过。当然,它不能按预期运行,但它能编译通过。另外,在JVM中并不存在无符号整数。好问题! - mprivat

0

这只是一个异常处理问题。在Java中,您可以创建一个具有负大小的数组 - 即使在编译时也不会抛出异常。但是,在运行时,除非进行更正,否则您的程序将无法运行。(它将抛出NegativeArraySizeException。)

问题在于此异常在运行时而不是编译时被抛出 - 这就是为什么使用IllegalArgumentException处理异常的原因。


2
你可以在Java中创建一个具有负大小的数组” - 不,你不能。你可以编写 new int[-1] 但是JVM不会创建这样的数组。任何Java数组对象都不会具有负长度。 - dimo414

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