博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
Java里面对象的引用问题
阅读量:4095 次
发布时间:2019-05-25

本文共 2008 字,大约阅读时间需要 6 分钟。

            Java初学者,因为之前学过C,所以对于学Java的时候老是能想起来地址、指针问题,感觉挺纠结。

         

      Java定义实例化的对象时,具体对象数据存在堆中,对象名存在栈中,栈中的对象名可以看做C++中的指针,指向堆中具体的对象数据。并且同一类的两个不同对象之间的赋值,实际上是改变栈中对象名的指向,而不是改变堆中的对象数据,当堆中的对象数据没有对象名指向时,这个数据成为垃圾数据,对应的堆内存由Java的垃圾处理机制(GC)自动回收。

         Java的基本类型是没有内存关系的,没有变量名指向变量实体这种说法的,相互赋值用法和C++中变量赋值用法是相同的。有一点区别:C++可以使用函数交换两个变量的值(指针传参),而Java实现相同功能只能用函数返回值(返回数组,保存交换完后的两个数值)

       举例三个不同类型的例子说明一下吧:

基本数据类的值传递

public class PersonDemo{	public static void main(String args[]){		int a = 10;		fun(a);		System.out.println(a);	}		public static void fun (int temp) {		temp = 100;	}}//输出10
        基本数据类型没有内存关系,对于fun函数的传递是值传递,fun函数中temp变量指向了新的数值100,而原本a指向的10不变。fun函数执行完毕后,temp与100均为内存垃圾,被GC回收。

字符串的引用传递

public class PersonDemo{	public static void main(String args[]){		String str = "hello";		fun(str);		System.out.println(str);	}		public static void fun (String temp) {		temp = "world";	}}//输出hello
       
字符串String类型一旦声明赋值则不可改变,此处fun函数的参数传递为引用传递,str与temp均指向堆内存中的“hello”,但是字符串“world”出现时,是在堆内存中重新开辟一个空间(等价于使用string类的new String("world")),赋值“world”,然后temp指向“world”。fun函数执行完毕后,temp与“world”均为内存垃圾,被GC回收。

自定义类的成员变量的引用传递

class Demo {	private String msg;	public void setMsg(String msg) {		this.msg = msg;	}	public String getMsg() {		return this.msg;	}}public class PersonDemo{	public static void main(String args[]){		Demo demo = new Demo();		demo.setMsg("hello");		fun(demo);		System.out.println(demo.getMsg());	}		public static void fun (Demo temp) {		temp.setMsg("world!");	}}//输出world

         自定义类的成员对象的内存关系又不太一样:

         1、Demo demo = new Demo(); 是在栈内存开辟两个空间,存两个名字 类型名(demo和msg),然后再堆内存开辟空间,存类实体,此处为可以指向msg地址的值。

         2、demo.setMsg("hello");  在堆内存开辟空间,存字符串“hello”,然后栈内存中的msg指向此处的“hello”。

         3、fun(demo); 在栈内存开辟空,存类型名 temp,然后将demo的指向赋给temp,即引用传递,此时temp指向的堆内存中的空间与demo所指向的是一样的。

         4、temp.setMsg("world!");  此处“world!”与上面的“hello”相同,需要在堆内存重新开辟空间,然后存“world!”;执行setMsg函数时,在temp所指向的类空间中找到栈空间的msg,然后将msg的指向从“hello”转移至“world!”。fun函数执行完毕后,temp和“hello”将成为内存垃圾。

具体内存变化图如下:

总结

1、java基本类型没有内存关系,变量之间的赋值等效于C、C++;

2、java String类型一旦赋值,则在堆内存中不可改变,只能被GC回收;重新赋值需要开辟新的堆内存空间,改变栈内存中变量名的指向;

3、java 可通过外部函数更改类的成员变量的值(引用传递),具体内存变换见上图。

你可能感兴趣的文章
PHP管理cifs,PHP scandir()在cifs mount上失败,直到php-fpm重启
查看>>
点赞的php代码和css、,jQuery和CSS3实现点赞功能
查看>>
字符串转换成json数组 php,浅谈thinkphp中将字符串转换成json数组的方法
查看>>
php 上传文件程序,php 文件上传
查看>>
oracle exp ora文件,Oracle exp导出时出现ORA-01555和ORA-22924的解决
查看>>
redhat6安装oracle客户端,在redhat6企业版安装oracle10g
查看>>
linux命令菜鸟ping,linux 网络管理 监测等相关的工具 ping 、traceroute、ss、netstat
查看>>
linux 如何关闭文件,Linux文件打开与关闭
查看>>
linux目录数据结构,Linux文件系统的最基本数据结构:inode和block
查看>>
linux 文件添加标签,如何创建自定义SELinux标签
查看>>
linux cmd 权限命令提示符,命令行快速提示:权限
查看>>
linux离线安装httpd服务,Linux系列之离线安装Apache HTTP
查看>>
linux忘记root密码光盘,Linux忘记root密码
查看>>
linux 路径回退,Linux下的常见命令总结
查看>>
linux 脚本详解,Shell脚本编程详解
查看>>
linux分区顺序详解,找到了linux分区顺序错乱修复方法
查看>>
linux convert 添加文字,linux下使用convert命令修改圖片分辨率
查看>>
linux在开始ubifs前错误,UBIFS文件系统说明文档答题.docx
查看>>
linux安装智能输入法,Ubuntu 8.04中安装智能拼音输入法
查看>>
cd linux 官网,cdlinux
查看>>