Java有指针吗?

2022-08-31 17:11:26

如果Java没有指针,那么关键字在Java中有什么作用?new


答案 1

正如所指出的,Java有参考。它们有何不同?

  1. 您无法对这些操作执行算术或其他此类操作
  2. 它们不指向包含对象的内存(即它们不是其他名称的指针)。JVM 可以自由地在 VM 内存中移动对象,并且很可能在垃圾回收期间执行此操作。然而,引用仍然指向该对象,尽管它在内存中移动。

因此,它们不像C++引用(直接指向对象)。也许一个更好的名字会是处理


答案 2

Java没有指针;Java有参考。

这是一个很好的观点,但是指针具有您可能(或可能不会)通常使用的额外操作;引用缺少这些操作,因为这些操作可能不安全。

例如,如果您使用指针为数组的第一个元素编制索引,如下所示:

int squares[] = {1, 4, 9, 16, 25, 36, 49};
int* intPointer = squares;

您可能希望取消引用指针并获取值“1”,但您也可以:

intPointer++

执行此操作后,当您取消引用指针时,您将获得值“4”。一秒钟

intPointer++;

将,在取消引用时,为您提供值“9”。这是因为 ++ 操作在内存中将指针向前移动一个“单位”。

问题来自C / C++类型检查系统中的弱点(C++必须保持与C的兼容性,因此它允许相同的问题)。指针将地址存储在内存中,++ 操作将适当数量的字节添加到该地址。在许多系统上,一个int会增加四个字节,但如果指针是char指针++,它应该只添加一个字节。请注意,由于指针的基础数据类型是内存中的地址,因此以下内容是合法的(但不推荐):

char* charPointer = squares;
charPointer++;

void* voidPointer = squares;
voidPointer++;

由于指针是内存中的地址,因此它们可能(正确)表示计算机中的任何内存位,但只有当基础数据与指针的类型和对齐方式相混淆时,它们才会被正确取消引用。对于未由大量代码管理以使其安全的指针,这意味着您可能会偏离所需信息的数据类型(或对齐方式),并且取消引用可能会以灾难告终。尝试使用自定义代码解决此问题往往会严重减慢一个指针的速度,以至于您注意到性能问题,并且它为在自定义“指针管理”代码中添加错误打开了大门。

Java 端通过返回引用来执行所有这些问题。引用不引用内存中的任何位置;Java 维护一个内部的“对指针的引用”表。此表获取引用并返回与其关联的数据,无论该数据驻留在内存中的什么位置。这会减慢代码执行速度,因为每个“取消引用”都执行两次查找,一次在引用表中,一次在计算机内存中。

Java使用引用的一大优点是,可以在不破坏潜在指针地址的情况下移动内存。在C程序中,如果将数据移动到新的内存位置,则很难知道程序的其他部分是否具有指向数据的指针。如果在移动内存后取消引用过时的指针,程序将访问损坏的数据,并且通常崩溃将是缺点。

能够在正在运行的程序中移动内存,使程序能够轻松回收内存。任何不需要内存块的程序都可以释放未使用的内存,但这会在已用内存块之间创建未使用内存的内存孔。在内部,计算机使用非常大的内存页。如果稀疏使用的内存页可以将少数已用位移动到另一页,则可以释放一页内存。这增加了数据到内存的密度,从而提高了缓存性能。有时,这转化为性能改进,这可能是非常戏剧性的。

Java 的垃圾回收器通过临时阻止对一组引用的数据的访问来利用引用的使用。在访问阻塞期间,它会移动数据(以压缩数据)。阻塞后,对地址表的引用具有新的内存地址。由于代码的“功能”层从一开始就不知道地址,因此此操作不会破坏正在运行的Java程序。