原 分分钟看懂java用引用传递与值传递在

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;  
    }  
}  

结果如图所示:

分析如图所示:

总结

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

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

本文参与腾讯云自媒体分享计划,欢迎正在阅读的你也加入,一起分享。

发表于

我来说两句

0 条评论
登录 后参与评论

相关文章

来自专栏曾大稳的博客

c基础

711
来自专栏lgp20151222

MySql 模糊查询

SQL模糊查询,使用like比较关键字,加上SQL里的通配符,请参考以下:  1、LIKE'Mc%' 将搜索以字母 Mc 开头的所有字符串(如 McBadden...

481
来自专栏函数式编程语言及工具

泛函编程(12)-数据流-Stream

    在前面的章节中我们介绍了List,也讨论了List的数据结构和操作函数。List这个东西从外表看上去挺美,但在现实中使用起来却可能很不实在。为什么?有两...

1865
来自专栏猿人谷

Mysql字符串截取总结:left()、right()、substring()、substring_index()

在实际的项目开发中有时会有对数据库某字段截取部分的需求,这种场景有时直接通过数据库操作来实现比通过代码实现要更方便快捷些,mysql有很多字符串函数可以用来处理...

1925
来自专栏http://www.cnblogs.com

time&datetime模块详解

 一.time模块 1.时间格式转换图: ? 2.time模块中时间表现的格式主要有三种:   a、timestamp时间戳,时间戳表示的是从1970年1月1日...

3629
来自专栏个人随笔

使用集合组织相关数据

一.集合概述   特点:可动态扩容   1.ArrayList(数组列表)     类似于数组,可动态维护     命名空间:System.Collection...

2868
来自专栏coding for love

JS入门难点解析13-属性描述符,数据属性和访问器属性

(注1:如果有问题欢迎留言探讨,一起学习!转载请注明出处,喜欢可以点个赞哦!) (注2:更多内容请查看我的目录。)

421
来自专栏Golang语言社区

Golang语言社区--Go语言基础第三节常量

大家好,我是彬哥;今天继续我们的基础课程的讲解,本篇给大家讲解的是关于Go语言常量的知识。那么在编程语言中何为常量?常量解释如下:

46522
来自专栏猿人谷

Mysql字符串截取总结:left()、right()、substring()、substring_index()

在实际的项目开发中有时会有对数据库某字段截取部分的需求,这种场景有时直接通过数据库操作来实现比通过代码实现要更方便快捷些,mysql有很多字符串函数可以用来处...

2530
来自专栏java一日一条

Java 函数调用是传值还是传引用?从字节码角度来看看 !

https://www.oschina.net/question/2507499_2244027,其中的变量a前后的输出是什么?

733

扫码关注云+社区