关键词:
【中文标题】零长度数组如何在内存中表示?【英文标题】:How is the zero length array represented in memory? 【发布时间】:2015-07-19 21:43:28 【问题描述】:Java 原语对象被映射到本机原语。
所以我的问题是char value[] = new char[0];
是如何表示的?
它是否取决于(本机代码的)gcc 编译器实现?这是否意味着所有空的 Java String
s 都指向同一个地址?
【问题讨论】:
Java 原语不一定映射到本机原语。 Java int 是 4 个字节,即使它是在 8 位架构上实现的。 Java char 总是两个字节。 您是指String
对象本身还是字符串的字符内部表示?
一个空字符串将是一个长度为0
的对象,并且该length 应该存储在某个地方。是否所有空字符串都指向同一个地址有关系吗?
@CaptainMan:内部表示
@Jim,空数组和空数组是完全不同的,你不能将一个交换另一个。
【参考方案1】:
Java 数组是对象。它们继承自 Object
类。
JVM 规范没有规定对象的任何特定实现,只要它们的行为符合规范即可。在实践中,它是通过一个标头后跟对象的实际字段来实现的。
Java 中的数组不只是其原始组件的序列。它是一个对象,具有length
字段,并且具有方法。因此,与任何其他对象一样,它具有标头,然后是长度,然后是所有数组组件。
分配大小为零的数组是具有标头和大小但没有为实际组件分配空间的对象。
对数组的引用就像对任何其他对象的引用一样。 Java 中的数组与 C 中的数组不同,如果数组大小为零,则指向其开头的指针实际上是无效的。对数组的引用指向数组object,它的长度恰好为零并且没有实际项目。如果您尝试寻址此类数组中的任何元素,则不会出现有效指针问题。数组引用本身指向一个有效对象。然后,边界检查将显示任何索引超出范围,因此不会发生进一步的指针取消引用。
所以底线是对char[0]
的引用是对实际分配对象的有效引用。它根本没有超出长度的数据。
这与null
不同,null
是一个位全为零的引用,因此根本不指向任何地方。除了引用本身之外,没有分配任何内存,而对于char[0]
,为标头和长度分配了足够的内存。
对于字符串,两个空字符串不一定指向同一个字符数组。例如,如果你写:
String a = new String();
String b = new String();
你会得到两个不同的空字符串对象。它们中的每一个都有一个它指向的不同的空字符数组。这是因为String
类的无参数构造函数是这样实现的:
public String()
this.value = new char[0];
您看到new
关键字的用法了吗?这意味着分配了一个新的数组对象,而不是从任何地方复制。
但请注意,如果您的来源是:
String a = "";
String b = "";
然后由于实习,它们将指向同一个字符串对象,因此指向同一个字符数组。另外,如果是:
String a = new String();
String b = new String(a);
然后你会有两个不同的String
对象,但它们都指向同一个内部字符数组。这是因为第二行的构造函数是:
public String(String original)
this.value = original.value;
this.hash = original.hash;
同样,指向空字符串的指针肯定不同于空指针。它指向一个实际的字符串对象,该对象指向一个实际的字符数组对象。
【讨论】:
要获得额外奖励,请查看 OpenJDK 的 [Java Object Layout ](openjdk.java.net/projects/code-tools/jol) 工具,该工具可让您检查 Java 类的填充等之后的实际对象布局。【参考方案2】:内存布局未定义,因为它是一个实现细节。
这是他们的 64 位 JVM 的 how IBM describes the memory layout of an array:
-
64 位类指针(即信号
char
)
64 位用于标志(例如,表示此对象是一个数组)
64 位用于锁定数据(用于同步)
64 位数组长度(仅使用 32 位,但字段边界对齐)
0 位数据,因为数组没有元素
总共 256 位或 32 字节。
在 Java 中,String
和 char[]
不是一回事。 String
将是一个单独的对象,其中包含对 char[]
的引用。
【讨论】:
char[0]
的内存布局是什么?
@Jim 答案试图以位级细节来解释这一点。有什么不清楚的地方吗?
所以基本上char[0]
在访问时会转到第4个字并找到长度为0,这意味着不存在数据,即第5个字及以上没有有效的内存地址。那有什么帮助,而不是仅仅有 null 呢?而且在 C++ 中也不一样吧?
null
不是一个对象。 null
与空数组完全不同。
@Jim 我不明白。您的意思是“为什么要使用空数组而不是 null?”有很多原因,在别处详细描述,但没有一个是关于内部内存表示的。【参考方案3】:
由于每个数组对象都有length
属性,所以写的时候
char a[] = new char[0];
然后length
属性得到值 0,它代表数组的大小。 length
字段为 4 个字节,该数组有一个通常为 8 个字节的正常标头。
空数组没有什么特别之处,它和其他数组一样,但它不包含元素。
值得一提的是,空数组和初始化为null
的数组是两个不同的东西。例如,有时从方法返回空数组比 null
更容易。
【讨论】:
【参考方案4】:使用new
创建的两个不同对象在引用相等性方面必须不同,所以不,它们不是同一个对象。
另外,任何两个 Java String
对常量字符串 "" 的引用都将引用同一个对象,因为编译时常量字符串会被保留。
【讨论】:
那么char[0]
是一个有效的内存地址吗?因为我认为这是编译器的某种“语法”糖
不,new char[0]
创建一个新的、完全有效的空数组对象。
空数组对象是什么意思?这是一个长度为 0 的数组。这个“完全有效的空数组对象”的表示是什么?
是的,它是一个长度为 0 的数组。在 32 位 HotSpot 上,数组由所有对象的正常 8 字节标头表示,长度字段用 4 字节表示,然后是数组的内容,零长度数组的工作方式与任何其他数组相同。
一贯如此。它被四舍五入到填充大小的倍数。 零长度数组没有什么特别之处。如何在 Rust 中表示指向 C 数组的指针?
】如何在Rust中表示指向C数组的指针?【英文标题】:HowtorepresentapointertoaCarrayinRust?【发布时间】:2017-01-0515:17:26【问题描述】:我需要Rust中的extern"C"FFI函数,并希望接受一个固定大小的数组。C代码传递如下内容://Ccodee... 查看详情
如何在 ember-data 模型中表示数组?
】如何在ember-data模型中表示数组?【英文标题】:Howtorepresentarrayswithinember-datamodels?【发布时间】:2012-08-2312:15:15【问题描述】:当模型包含数组时,是否有必要使用DS.hasMany指向DS.Model?即使数组元素不是真正的模型(没有自己... 查看详情
如何在java中的内存中表示null[duplicate](代码片段)
可能重复:WhatexactlyisnullinJavamemory有没有人知道如何在对象或任何东西的内存中表示空值。在点网中,它由空指示符布尔值和相应类型的值(Referhere)表示。那么有谁知道它是如何在java中完成的?答案来自JVMspecification,section2.4:... 查看详情
在固定长度向量中表示文档集合的最佳方法是啥?
】在固定长度向量中表示文档集合的最佳方法是啥?【英文标题】:Whatisthebestwaytorepresentacollectionofdocumentsinafixedlengthvector?在固定长度向量中表示文档集合的最佳方法是什么?【发布时间】:2019-10-2711:14:46【问题描述】:我正在... 查看详情
如何在java中表示一个空列表? [复制]
...问题描述】:我有这个类的构造函数以一个字符串和一个数组列表作为参数;classFooStringide;ArrayListlist;publicTypeOperator(Stringide,ArrayListlist)this.ide=ide; 查看详情
在字节数组中表示一个数字(java编程)
】在字节数组中表示一个数字(java编程)【英文标题】:Representinganumberinabytearray(javaprogramming)【发布时间】:2011-02-2113:42:01【问题描述】:我试图在一个两字节数组中表示端口号9876(或十六进制的0x2694):classfoopublicstaticvoidmain... 查看详情
如果它们来自数据源,如何在 graphql 模式中表示枚举?
...个RESTapi。其中一个路径是/types/,它只返回一个json字符串数组,每个字符串都是一个类型的名称。此类型在架构中的其他地方用作其他对象的类型枚举值。我如何在gr 查看详情
如何在 proto 文件中表示接口实现
】如何在proto文件中表示接口实现【英文标题】:Howtorepresentinterfaceimplementationinprotofile【发布时间】:2018-08-0107:29:49【问题描述】:我正在使用protogen工具从.proto文件生成c#类。我想知道是否有可能在原型文件中表示接口实现。例... 查看详情
你如何在 Haskell 中表示一个图形?
】你如何在Haskell中表示一个图形?【英文标题】:HowdoyourepresentagraphinHaskell?【发布时间】:2012-04-0116:33:56【问题描述】:使用代数数据类型在haskell中表示树或列表很容易。但是您将如何以印刷方式表示图形?看来你需要有指针... 查看详情
在 C++ 中表示二维数组的最佳方法,其大小在运行时确定
】在C++中表示二维数组的最佳方法,其大小在运行时确定【英文标题】:Bestwaytorepresenta2-DarrayinC++withsizedeterminedatruntime【发布时间】:2010-09-2008:32:03【问题描述】:在C++中,我想做类似的事情:intn=get_int_from_user();char*matrix=newchar[n... 查看详情
如何在 Python 中表示无限数?
】如何在Python中表示无限数?【英文标题】:HowcanIrepresentaninfinitenumberinPython?【发布时间】:2011-12-0812:53:54【问题描述】:如何在python中表示无限数?无论您在程序中输入哪个数字,任何数字都不应大于这个无穷大的表示。【问... 查看详情
如何在 javascript 中表示其他语言?
】如何在javascript中表示其他语言?【英文标题】:HowdoIrepresentotherlanguagesinjavascript?【发布时间】:2016-12-2410:20:42【问题描述】:我尝试在网站中表示文本。但是,该文本是从Perl返回的HTML结果中提取的。所以它已经是UTF-8了。英... 查看详情
如何在 TypeOrm 中表示视图?
】如何在TypeOrm中表示视图?【英文标题】:HowtoRepresentaViewinTypeOrm?【发布时间】:2019-08-2311:41:04【问题描述】:我需要将数据库视图表示为typeOrm中的实体以对这些视图应用查询,有没有办法做到这一点?【问题讨论】:【参考... 查看详情
如何在 Swift 中表示通用 JSON 结构?
】如何在Swift中表示通用JSON结构?【英文标题】:HowtorepresentagenericJSONstructureinSwift?【发布时间】:2017-10-0605:13:08【问题描述】:我想在Swift中表示一个通用的JSON对象:letfoo:[String:Any]=["foo":1,"bar":"baz",]但是编译器建议的[String:Any]... 查看详情
如何在 GADT 中表示此 FSM
】如何在GADT中表示此FSM【英文标题】:HowtorepresentthisFSMinGADT【发布时间】:2022-01-0600:02:43【问题描述】:我正在观看this视频并了解了Scala中的GADT。我能够代表下面的状态机这是我的代码typeIdletypeMovingenumDirection:caseEast,West,North,Sou... 查看详情
如何在 Perl 中表示集合?
】如何在Perl中表示集合?【英文标题】:HowcanIrepresentsetsinPerl?【发布时间】:2011-04-1115:09:57【问题描述】:我想用Perl表示一个集合。我通常做的是使用带有一些虚拟值的哈希,例如:my%hash=();$hash"element1"=1;$hash"element5"=1;然后使... 查看详情
如何在 JavaScript 中表示浮点数? [复制]
】如何在JavaScript中表示浮点数?[复制]【英文标题】:HowcanirepresentafloatinJavaScript?[duplicate]【发布时间】:2021-10-1520:34:45【问题描述】:我是JavaScript的新手。在python中,我可以创建一个条件来检查数字是否是这样的浮点数:num=1.5... 查看详情
如何在字符串中表示逗号? [复制]
】如何在字符串中表示逗号?[复制]【英文标题】:Howtorepresentcomma\'sinstring?[duplicate]【发布时间】:2013-03-2613:15:00【问题描述】:我有一个像这样的整数,即3356890。我正在将其转换为字符串并显示在屏幕上。现在我想像这样显示... 查看详情