文档章节

分分钟看懂java用引用传递与值传递在堆栈中的规则

边鹏_尛爺鑫
 边鹏_尛爺鑫
发布于 2017/12/14 10:20
字数 1032
阅读 28
收藏 0

1 栈和堆

1.1 栈

栈是一个内存数组,是一个LIFO(Last-In First-Out,后进先出)的数据结构。

栈存储几种类型的数据:

某些类型变量的值;

程序当前的执行环境;

传递给方法的参数。

栈有如下几个特征:

数据只能从栈的顶端插入和删除。

把数据放到栈顶称为入栈(push)。

从栈顶删除数据称为出栈(pop)。

栈是在编译期,由编译器分配好内存空间。

 1.2 堆

堆是一块内存区域,在堆中可以分配大块的内存用于存储某类型的数据对象。

与栈不同,堆里的内存能够以任意顺序存入和删除。

堆是在运行期,根据程序运行情况动态分配内存空间。

 

2 值类型和引用类型

C#数据类型分为两种:值类型和引用类型,这两种类型的对象在内存中的存储方式不同。

值类型:只需要一段单独的内存,用于存储实际的数据。

引用类型:需要两段内存。

第一段存储实际的数据,它总是位于堆中。

第二段是一个引用,指向数据在堆中的存放位置。

一般情况下,对于值类型,数据存放在栈里。对于引用类型,引用存放在栈里,实际数据存放在堆里。如图所示:

当然,上面是一般情况,值类型数据或引用类型的引用部分也会存放在堆中。

比如,当一个值类型或一个引用类型是另一个引用类型对象的数据时,便会存放在堆中。

C#中的值类型和引用类型如图所示:

 

3 值参数和引用参数(值传递和引用传递)

值参数:通过将实参的值复制到形参的方式把数据传递给方法。方法被调用时,系统在栈中为形参分配空间,然后将实参的值复制给形参。

引用参数:在参数前面加 ref 或 out 修饰符 ,实参必须是变量。

ref 和 out 的区别:ref参数传入方法之前必须初始化;out参数不需要,但out参数在方法返回时必需赋值。

3.1 值类型数据作为值参数传递

using System;  
namespace Test  
{  
    class Program  
    {  
        static void Main(string[] args)  
        {  
            int val = 10;  
            MyMethod(val);  
            Console.WriteLine("val的值为:{0}",val);  
        }  
        static void MyMethod(int xxx)  
        {  
            xxx = xxx + 5;  
            Console.WriteLine("xxx的值为:{0}",xxx);  
        }  
    }  
}  

结果如图所示:


分析如图所示:

3.2 值类型数据作为引用参数传递

using System;  
namespace Test  
{  
    class Program  
    {  
        static void Main(string[] args)  
        {  
            int val = 10;  
            MyMethod(ref val);  
            Console.WriteLine("val的值为:{0}",val);  
        }  
        static void MyMethod(ref int xxx)  
        {  
            xxx = xxx + 5;  
            Console.WriteLine("xxx的值为:{0}",xxx);  
        }  
    }  
}  

结果如图所示:

 

分析如图所示:

3.3 引用类型数据作为值参数传递

写了两个例子,注意在方法内部形参p的不同之处!

示例1:

using System;  
namespace Test  
{  
    class Program  
    {  
        static void Main(string[] args)  
        {  
            Person p1 = new Person();  
            p1.name = "lzj";  
            MyMethod(p1);  
            Console.WriteLine("p1.name的值为:{0}",p1.name);  
        }  
        static void MyMethod(Person p)  
        {  
            p.name = "CR7";  
            Console.WriteLine("p.name的值为:{0}",p.name);  
        }  
    }  
    class Person  
    {  
        public string name;  
    }  
}  

结果如图所示:

 


分析如图所示:

示例2:

using System;  
namespace Test  
{  
    class Program  
    {  
        static void Main(string[] args)  
        {  
            Person p1 = new Person();  
            p1.name = "lzj";  
            MyMethod(p1);  
            Console.WriteLine("p1.name的值为:{0}",p1.name);  
        }  
        static void MyMethod(Person p)  
        {  
            p = new Person() { name = "CR7" };  
            Console.WriteLine("p.name的值为:{0}",p.name);  
        }  
    }  
    class Person  
    {  
        public string name;  
    }  
}  

结果如图所示:

 

分析如图所示:

3.4 引用类型数据作为引用参数传递

using System;  
namespace Test  
{  
    class Program  
    {  
        static void Main(string[] args)  
        {  
            Person p1 = new Person();  
            p1.name = "lzj";  
            MyMethod(ref p1);  
            Console.WriteLine("p1.name的值为:{0}",p1.name);  
        }  
        static void MyMethod(ref Person p)  
        {  
            p = new Person() { name = "CR7" };  
            Console.WriteLine("p.name的值为:{0}",p.name);  
        }  
    }  
    class Person  
    {  
        public string name;  
    }  
}  

结果如图所示:

 

分析如图所示:

总结

作为值参数(即值传递)时:传递的是栈中的数据。

作为引用参数(即引用传递时):传递的是栈本身的地址。

© 著作权归作者所有

共有 人打赏支持
边鹏_尛爺鑫
粉丝 29
博文 30
码字总数 24888
作品 0
成都
程序员
私信 提问
Java的方法传递参数的本质---值传递

JAVA中只有值传递,没有引用传递 任何数据(不管是基本类型,还是引用类型)传到一个方法里时,都是拷贝了一份,所以无法在一个方法里修改他们的值,当然,如果传递的是对象的话,也就是引用...

Zhao-Qian
2012/10/18
0
2
《俗人笔记》之《Java基础语法上》

基础前言: 二进制: 十进制转二进制:使用除以2获取余数来算 二进制转十进制:按8421编码 字节: 最小的存储单位是字节,最小的信息单位是位(bit) 1B=8bit 1KB=1024B 依次类推 DOS命令 盘符...

钱无极
2018/12/10
0
0
Java中的JVM基础:数据类型和堆栈

数据类型 Java虚拟机中,数据类型可以分为两类:基本类型和引用类型。基本类型的变量保存原始值,即:他代表的值就是数值本身;而引用类型的变量保存引用值。“引用值”代表了某个对象的引用,...

疯狂的兔子
2015/03/26
0
0
Java值传递与引用传递

Java面试题: 当一个对象被当作参数传递到一个方法后,此方法可改变这个对象的属性,并可返回变化后的结果,那么这里到底是值传递还是引用传递? 答案基本上是:值传递 说明:得出这种结论的前...

长平狐
2013/01/06
150
0
java方法参数和C方法参数的区别

方法调用(call by) 是一个标准的计算机科学术语。方法调用根据参数传递的情况又分为值调用( call by reference ) 和引用调用( call by value ) 。江湖上有很多关于这两种调用的定义 ,最通常...

墙头草
2011/09/09
0
0

没有更多内容

加载失败,请刷新页面

加载更多

Android 动画Animation

动画分为视图动画(view animation)和属性动画(property animation),视图动画又分为帧动画和补间动画 视图动画控件(iv)点击事件(OnClickListener接口)触发位置在原位置 1.帧动画(Fra...

Coding缘
28分钟前
1
0
Mysql-常用日期查询

今天: SELECT * FROM A WHERE create_time = create_time(now()); 昨天: SELECT * FROM A WHERE TO_DAYS( NOW( ) ) - TO_DAYS( create_time) <= 1; 最近7天: SELECT * FROM A where DATE......

米饭有毒
30分钟前
1
0
如何离线分析Kafka海量业务消息?1分钟快速为您支招

场景介绍 说起Kafka,许多使用者对它是又爱又恨。Kafka是一种分布式的、基于发布/订阅的消息系统,其极致体验让人欲罢不能,但操心的运维、复杂的安全策略、可靠性易用性的缺失等,仍需要使用...

中间件小哥
33分钟前
3
0
ThreadLocal类

ThreadLocal类和synchronized关键字在线程同步机制中的不同作用。 synchronized关键字通过锁机制保证在同一时刻,多线程中只有一个线程访问变量,执行操作; 而ThreadLocal类保证每个线程都会...

某只小强
36分钟前
1
0
一文纵览EMAS 到底内含多少阿里核心技术能力

申请阿里云EMAS,体验一站式移动研发平台,更多精彩尽在开发者会场 EMAS的整体定位是阿里巴巴移动技术对外输出的主窗口,沉淀了阿里巴巴近10年在移动互联网技术架构上的积累以及在一系列垂直...

阿里云云栖社区
40分钟前
2
0

没有更多内容

加载失败,请刷新页面

加载更多

返回顶部
顶部