文章目录
Java有指针吗?
许多刚接触Java语言的朋友可能会认为java没有指针(*),加上许多入门教程为了便于初学者理解而去解释说Java不存在像C/CPP那样的指针操作,所以java没有指针这样的认识就产生了,但答案是,java有指针,但是java开发者并不能像c++开发者一样显式地去调用指针。本文将对java指针做一基本讲解。
相关概念
1、指针
指针(Pointer),即一块存储空间的内存地址,若给定了这个内存地址,则顺着这个内存地址就可以访问到相应的内存区域。
java中的指针被称为隐式指针,不能被直接操作;而在c++中,开发中可以直接操作指针,被称为显示指针。
2、Java堆
Java堆(Heap),每一个对象或数组被创建后,该对象的实例都会存放在堆中。
3、虚拟机栈
虚拟机栈(VM Stack),存放对象相应的内存地址,即存放指针,每一个指针指向堆中的
相应对象实例。
4、共享内存
即一个内存地址(指针)被多个实例引用。
5、自动解引用
java 的点号表达式会自动解引用指针以用来访问或赋值数据域。
使用Java的隐式指针
创建一个矩形对象Rectangle
public class Rectangle {
int x;//x轴坐标
int y;//y轴坐标
int width;//宽
int height;//高
public Rectangle(int x, int y, int width, int height) {
this.x = x;
this.y = y;
this.width = width;
this.height = height;
}
public Rectangle() {
}
}
首先,初始化Rectangle对象一个空参实例rect1和含参实例rect2,打印输出用以分析
//初始化Rectangle对象
Rectangle rect1 = new Rectangle();
Rectangle rect2 = new Rectangle(10, 20, 35, 45);
//打印对象观察
//打印对象观察
System.out.println("rect1->"+rect1.x+","+rect1.y+","+rect1.width+","+rect1.height
+","+"----"+rect1);
System.out.println("rect2->"+rect2.x+","+rect2.y+","+rect2.width+","+rect2.height
+","+"----"+rect2);

内存图分析
可以看出,两个实例的数据分别初始化为了0,0,0,0和10,20,35,45,它们分别对应的内存地址是@1089e5f和@141d797,画出内存图,如下,JVM为对象实例开辟了一块堆空间(heap space),并且为内存地址开辟了栈空间(stack space),其中的指针@xxx指向了两个对象实例

共享内存
//初始化Rectangle对象
Rectangle rect1 = new Rectangle();
Rectangle rect2 = new Rectangle(10, 20, 35, 45);
//打印对象观察
System.out.println("rect1->"+rect1.x+","+rect1.y+","+rect1.width+","+rect1.height
+","+"----"+rect1);
System.out.println("rect2->"+rect2.x+","+rect2.y+","+rect2.width+","+rect2.height
+","+"----"+rect2);
//将rect2的内存引用“复制给rect1”,此时rect1和rect2指向同一内存空间
//rect1的原内存被gc
rect1 = rect2;
//打印rect1
System.out.println("rect1->"+rect1.x+","+rect1.y+","+rect1.width+","+rect1.height
+","+"----"+rect1);
//比较内存地址
System.out.print("内存地址比较结果->");
System.out.println(rect1 == rect2);
rect1 = rect2,将rect2的内存地址共享给了rect1,数据域也进行了更改,此时内存图如下
内存图分析

此时,执行程序,rect1和rect2的指针是同一个,使用==比较指针地址,应该返回true

数据同步
其实,上面的程序已经在操作隐式指针了,rect1=rect2就是将指针共享,这时修改rect2的数据域,由于rect1引用了rect2的内存,所以rect1数据会同步修改
//初始化Rectangle对象
Rectangle rect1 = new Rectangle();
Rectangle rect2 = new Rectangle(10, 20, 35, 45);
//打印对象观察
System.out.println("rect1->"+rect1.x+","+rect1.y+","+rect1.width+","+rect1.height
+","+"----"+rect1);
System.out.println("rect2->"+rect2.x+","+rect2.y+","+rect2.width+","+rect2.height
+","+"----"+rect2);
//将rect2的内存引用“复制给rect1”,此时rect1和rect2指向同一内存空间
//rect1的原内存被gc
rect1 = rect2;
//打印rect1
System.out.println("rect1->"+rect1.x+","+rect1.y+","+rect1.width+","+rect1.height
+","+"----"+rect1);
//比较内存地址
System.out.print("内存地址比较结果->");
System.out.println(rect1 == rect2);
//修改rect2的数据,rect1的数据也改变,说明指向同一内存空间
rect2.x = 30;
System.out.println("rect1->"+rect1.x+","+rect1.y+","+rect1.width+","+rect1.height
+","+"----"+rect1);
System.out.println("rect2->"+rect2.x+","+rect2.y+","+rect2.width+","+rect2.height
+","+"----"+rect2);
}


本文深入探讨Java中隐式指针的概念,解析其如何在堆和虚拟机栈中工作,通过创建Rectangle对象实例,展示共享内存和数据同步机制,揭示Java内部对象引用和内存管理的奥秘。
16万+





