Java 为什么 DatagramPacket 的构造函数需要字节数组的长度?

Java Why does the constructor for a DatagramPacket need the length of the byte array?

根据 javadocs,DatagramPacket 中的构造函数 class 需要一个字节数组和一个小于或等于该数组长度的整数。 例如:

DatagramPacket(byte[] buf, int length)

我看到的所有示例都像这样简单地传递字节数组的长度属性:

byte[] buffer = new byte[1024];
DatagramPacket packet = new DatagramPacket(buffer, buffer.length);

对于这个(常见的)用例,在构造函数中访问传递的字节数组的长度属性会更简单。为什么所有构造函数都明确需要长度参数?

问题 'why' 的准确答案就是 'because'。规范是这样说的,请注意 DatagramPacket 从一开始就是 java 的一部分(好吧,我猜是在 oak 之后): javadoc 被标记为 @since 1.0.

我们所能做的就是猜测这个 API 的原始开发者在想什么。

所以我会尝试这样做:

  1. 这个 API 早于提供 (dataStore)(dataStore, offset, length) 变体(没有其他变体)的约定。例如,在 new String(byteArray, offset, length, charset) 构造函数中,以及这种概念出现的几乎所有其他地方,您必须在传递整个数据存储区或同时传递偏移量和长度之间做出选择;你永远不能只传递长度并将偏移量默认为 0。但你可以在这里;那是因为这个约定还没有形成。

  2. 概念 'pass an offset and a length' 存在的原因,不仅在这里,还有字符串的基于字节数组的构造函数,以及 OutputStream 的 write 方法,两者都有write(byte[] data) 以及 write(byte[] data, int offset, int length) 变体,以及 许多 核心库中的其他地方,是因为通常您的缓冲区比你拥有的数据量。如果您还不知道要在数据报包中发送多少数据,您可以将所有数据生成到一个自增长结构中,例如 ByteArrayOutputStreamStringBuilderArrayList<Byte>,写出所有数据,然后从中提取一个大小合适的 byte[] 数组。或者,这 VASTLY 更有效,您创建一个字节数组,该数组绝对足够大以存储您要创建的任何内容,如果您可以选择使用 ThreadLocal 重用它必须,一旦你完成了,你现在才知道它实际上有多大。与其制作另一个大小合适的字节数组并复制所有字节,不如发送 'buffer array' 的前 X 个字节,节省内存和复制操作。同样,也有不想从 0 开始的原因。这就是为什么 DatagramPacket 也有一个 (byte[] buf, int offset, int length) 构造函数,这也解释了为什么字节数组的参数名称实际上是 buf (缓冲区的缩写,请注意它不是更明显的名字 data).

  3. ByteBuffer 是专门为做好这一点而设计的概念。我不确定为什么 DatagramPacket 中仍然没有构造函数来处理这些,但 datagrampacket 本身比字节缓冲区早十年或更长时间。如果字节缓冲区从 1.0 开始就成为语言的一部分,那么这可能已经通过字节缓冲区完成了,它完全代表了这种具有固定大小缓冲区的概念,并且非常有效地使用代码来处理可能未知长度的数据 write/read 在正确的位置插入它,并且不超过某个限制,以避免必须在整个地方制作字节数组。