Java有指针吗?

aru*_*una 54 java pointers

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

Bri*_*new 47

正如所指出的,Java有参考.这些有何不同?

  1. 你不能对它们进行算术运算或其他类似的运算
  2. 它们不指向包含该对象的内存(即它们不是另一个名称的指针).JVM可以自由地在VM内存中移动对象,并且很可能在垃圾收集期间执行.然而,参考文献仍然指向该对象,尽管它在内存中移动.

所以它们不像C++引用(直接指向一个对象).也许一个更好的名字将被处理.

  • 实际上有一个着名的指针,NullPointer,在我的应用程序中似乎与Exception结合:) (12认同)
  • 你可以发表以上的参考吗?鉴于JVM可以随意移动对象并维护其引用,我怀疑至少,引用将是指向指针的指针. (7认同)
  • 实际上,在实现级别,引用通常是*指向包含该对象的内存的指针.但是,常规Java程序无法"看到幕后"并使用引用作为类似C的指针. (4认同)
  • @jalf这仅仅是手工操作.要么你实际上有一个实际上这样说的引用,在这种情况下你应该按照要求发布它,或者你没有,这留下了你正在弥补它的结论的空间.我只是查阅了我的编译器实现101本书,其中一本是Aho,Sethi和Ullman,他们都没有说任何这样的东西.JVM文档中"托管指针"和"压缩oops"等语言的存在清楚地表明,对象引用不是直接指针. (2认同)
  • @jalf - 我并不特别怀疑你,但是我想找一些*实际上*描述发生了什么的参考 (2认同)

Edw*_*uck 38

Java没有指针; Java有参考.

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

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

int squares[] = {1, 4, 9, 16, 25, 36, 49};
int* intPointer = squares;
Run Code Online (Sandbox Code Playgroud)

你可能想要取消引用指针并获得值"1",但你也可以:

intPointer++
Run Code Online (Sandbox Code Playgroud)

并且在您执行此操作后,当您取消引用指针时,您将获得值"4".一秒

intPointer++;
Run Code Online (Sandbox Code Playgroud)

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

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

char* charPointer = squares;
charPointer++;

void* voidPointer = squares;
voidPointer++;
Run Code Online (Sandbox Code Playgroud)

由于指针是内存中的地址,因此它们可能(正确地)表示计算机中的任何内存位,但只有当底层数据与指针的类型和对齐方式匹配时,它们才会被正确解除引用.对于不受大量代码管理以使其安全的指针,这意味着您可能会偏离所需信息的数据类型(或对齐),并且取消引用可能以灾难结束.尝试使用自定义代码修复此问题往往会导致一个指针严重减慢,以至于您发现性能问题,并且它为在自定义"指针管理"代码中添加错误打开了大门.

Java端通过返回引用来解决所有这些问题.引用不是指存储器中的任何位置; Java维护一个内部的"指针引用"表.此表获取引用并返回与其关联的数据,无论数据驻留在内存中的何处.这会减慢代码执行速度,因为每次"解除引用"都会进行两次查找,参考表中有一次查找,机器内存中有一次查找.

使用引用的Java的一大优点是可以移动内存而不会破坏可能的指针地址.在C程序中,如果将数据移动到新的存储器位置,则很难知道程序的其他部分是否具有指向数据的指针.如果在移动内存后取消引用陈旧指针,程序将访问损坏的数据,通常崩溃将是缺点.

能够在正在运行的程序中移动内存使程序可以轻松地回收内存.任何不需要内存块的程序都可以释放未使用的内存,但这会在使用过的内存块之间创建未使用内存的内存空洞.内部计算机使用非常大的内存页面.如果稀疏使用的存储器页面可能将少量使用的位移入另一页面,则可以释放一页存储器.这增加了数据到内存的密度,提高了缓存性能.有时,这可以转化为性能改进,这可能非常引人注目.

Java的垃圾收集器通过临时阻止对一组引用的数据访问来利用引用的优势.在访问阻塞期间,它会移动数据(压缩它).在阻塞之后,对地址表的引用具有新的存储器地址.由于代码的"功能"层首先不知道地址,因此该操作不会破坏正在运行的Java程序.


Syn*_*tic 13

Java在存储对数据的引用的变量意义上有指针.Java中Object类型的所有变量都是这个意义上的指针.

但是,Java语言不允许对指针值进行算术运算,就像你能用C语言那样.

  • "直接操作"是一种不精确的:另一个值(=另一个引用)的赋值是可能的,但指针算术(即向指针加1)是不可能的. (2认同)

the*_*oop 7

new 做(大致)以下:

  1. 找到一个连续的堆内存空闲块,它等于您正在创建的类的实例大小,以及一些用于簿记的空间
  2. 零表示空格并将其从空闲列表中删除
  3. 运行构造函数
  4. 将引用(不是指针,如其他帖子所解释的)返回到创建的实例.


小智 5

java.lang.NullPointerException

人们在采访中告诉我“java没有指针”。我通常给他们一些 java 代码,让他们解释一下这段代码中发生了什么:

public class TestPointers {

    public static void main(String args[]) {
        Object p1, p2;
        p1 = new Object();
        p2 = p1;
        p1 = null;
        System.out.println(p2);
    }
}
Run Code Online (Sandbox Code Playgroud)

  • 今天我第一次听 Java 讲座,我对这个例子感到很困惑。为什么大家都说Java有引用?!对我来说,一切都是指针,但你不能进行指针算术。 (6认同)
  • @ThreaT 不,它不会,因为当你修改 p1 时,你使它引用 null,但你不会销毁该对象;对象和它的引用是不同的东西:p2 仍然指向创建的对象,直到您将 p2 引用设为 null;然后,该对象将被 GC 销毁,因为没有任何对象引用它。C 指针与此类似:考虑代码 void main() { int n, *p1, *p2; n = 42;p1 = &n; p2 = p1; *p1 = 100;p1 = 空;printf("%d\n", *p2); 它将打印“100”,因为当您执行 p1 = null 时,您修改的是指针值,而不是它所指向的值。 (2认同)

cel*_*chk 5

Java确实有指针,它们以名称“引用”为人所知。

当人们说“Java 没有指针”时,他们通常会将指针的概念与 C 和 C 派生语言中的指针的特定实现和能力混淆。

特别是:

  • Java 引用不能设置为任意地址。也不能(标准)Pascal 或 Fortran 指针。
  • Java 引用不能设置为指向变量。也不能(标准)Pascal 指针。
  • Java 引用不支持指针算术。Pascal 和 Fortran 指针也没有
  • Java 引用不能指向对象的一部分(如数组的第三个元素)。帕斯卡指针也不能。

此外,与普遍的看法相反,指针不一定是地址。指针通常实现为地址,但没有要求这样做,即使在 C 或 C++ 中也没有。