一个小程序引发的思考
时间:2022-05-03
本文章向大家介绍一个小程序引发的思考,主要内容包括值类型与引用类型(这个面试的时候经常会被问到)、这里顺便介绍下栈和堆、基本概念、基础应用、原理机制和需要注意的事项等,并结合实例形式分析了其使用技巧,希望通过本文能帮助到大家理解应用这部分内容。
既然是一个小程序引发的思考,那么我们就先看看这个小程序,看看他有何神奇之处:
namespace ConsoleApplication1
{
class Program
{
static void Main(string[] args)
{
MyClass s = new MyClass();
s.val = 10;
int i = 20;
Console.WriteLine("s.val={0},i={1}",s.val,i);
MyMethod(s, i);
Console.WriteLine("s.val={0},i={1}", s.val, i);
Console.Read();
}
static void MyMethod(MyClass f1,int f2)
{
f1.val = f1.val + 5;
f2 = f2 + 5;
}
}
class MyClass
{
public int val = 20;
}
}
呵呵,大家看了以后可能会感觉这不是很简单的代码吗?有什么特别的地方吗?没有,真没有!但是我想问下大家这两次输出结果会有什么不同吗?分别是什么?有没有得出两次结果都是一样的?这个程序输出的结果是:
可能有些童鞋可能会问,不应该是一样的吗?为什么一个值变了,另外一个没有变呢?这是为什么呢?仔细的同学可能会发现static void MyMethod(MyClass f1,int f2)这个方法两个参数的类型不一样,f1属于引用类型,f2属于类型,是不是因为这个原因才导致两个变量经过同样的处理,s.val的值改变了,i的值却没有变。首先我们了解下什么是值类型,什么是引用类型。
值类型与引用类型(这个面试的时候经常会被问到)
值类型:值类型只需要一段单独的内存,用于存储实际的数据,他存在栈里面
引用类型:引用类型需要两段内存。
- 第一段存储实际的数据,它总是位于堆中。
- 第二段是一个引用指向数据在堆中的位置,它通常位于栈中。
那这样说,像上面s对象,它是一个引用类型,那它应该存放在堆中,但是val又是个值类型,那它不是应该存放在栈中吗?
请记住,对于一个引用类型,其实例部分始终存放在堆里。既然val是对象s的一部分,那么它们都会被存放在堆里,无论它们是值类型还是引用类型。
这里顺便介绍下栈和堆
栈:栈是一个内存数组,是一个LIFO(last-in first- out,后进先出)的数据结构,栈存储几种类型的数据。
- 某些类型变量的值
- 程序当前的执行环境
- 传递给方法的参数 栈有以下几个特征:
- 数据只能从栈的顶端插入和删除。
- 把数据放到栈顶叫入栈(push)。
- 从栈顶删除数据叫出栈(pop) 堆:堆是一块内存区域,在堆里可以分配大块的内存用于存储某些的类型的对象。与栈不同,堆里的内存能够任意顺序存入或移除。
虽然可以在堆里保存数据,但并不能显式地删除它们。CLR的自动GC在判断出程序的代码不会再访问某些数据时,自动清除无主的堆对象。我们因此可以不用操心这项使用其它编程语言时非常容易出错的工作了。
在介绍了值类型、引用类型与堆和栈,那我们解析下上面程序的执行步骤:
- 在方法被调之前,用作实参的变量s已经在栈里了。
- 随着方法的开始,系统在栈中为形参分配空间,并从实参复制值。
- 因为s是引用类型所以引用被复制,结果实参和形参都引用堆中的同一个对象。
- 因为i是值类型,所以值被复制,产生了一个独立的数据项。
- 在方法的结尾,f2和对象f1的字段都被加上5.
- 方法执行后,形参被从栈中弹出。
- i,值类型,它的值不受方法行为的影响。
- s,引用类型,它的值被方法的行为改变了。
亲爱的童鞋们,你们明白了吗?别看一点小程序,原来深挖可以得出那么多信息。其实也侧面说明了基础的重要性,童鞋们加油吧!
- jboss CLI 命令行接口学习(适用JBOSS EAP 6.2+)
- WebComponent魔法堂:深究Custom Element 之 面向痛点编程
- 修复bootstrap daterangepicker中的3个问题
- 搭建AngualarJS开发环境
- CSS魔法堂:重拾Border之——更广阔的遐想
- Jboss EAP:native management API学习
- linux:手动校准系统时间和硬件CMOS时间
- CSS3魔法堂:说说Multi-column Layout
- 数据可视化-EChart2.0使用总结2
- rpc框架之 thrift 学习 2 - 基本概念
- rpc框架之avro 学习 1 - hello world
- 探讨Android中的内置浏览器和Chrome
- java并发编程学习: 阻塞队列 使用 及 实现原理
- CSS魔法堂:说说Float那个被埋没的志向
- JavaScript 教程
- JavaScript 编辑工具
- JavaScript 与HTML
- JavaScript 与Java
- JavaScript 数据结构
- JavaScript 基本数据类型
- JavaScript 特殊数据类型
- JavaScript 运算符
- JavaScript typeof 运算符
- JavaScript 表达式
- JavaScript 类型转换
- JavaScript 基本语法
- JavaScript 注释
- Javascript 基本处理流程
- Javascript 选择结构
- Javascript if 语句
- Javascript if 语句的嵌套
- Javascript switch 语句
- Javascript 循环结构
- Javascript 循环结构实例
- Javascript 跳转语句
- Javascript 控制语句总结
- Javascript 函数介绍
- Javascript 函数的定义
- Javascript 函数调用
- Javascript 几种特殊的函数
- JavaScript 内置函数简介
- Javascript eval() 函数
- Javascript isFinite() 函数
- Javascript isNaN() 函数
- parseInt() 与 parseFloat()
- escape() 与 unescape()
- Javascript 字符串介绍
- Javascript length属性
- javascript 字符串函数
- Javascript 日期对象简介
- Javascript 日期对象用途
- Date 对象属性和方法
- Javascript 数组是什么
- Javascript 创建数组
- Javascript 数组赋值与取值
- Javascript 数组属性和方法
- 一文读懂「分布式架构」
- 老哥,您看我这篇Java集合,还有机会评优吗?
- 在 IDEA 中使用 Java 热部署插件 JRebel
- 后端必备 Git 分支开发:规范指南
- 大量的 TIME_WAIT 状态连接怎么处理?(文末有福利)
- 线上教育系统开发中,购物车功能是如何实现的?
- IntelliJ IDEA 2020.2重磅发布!全面支持Github PR。真香版本?
- 腾讯云智能语音小程序插件实现实时语音识别
- 我还在生产玩 JDK7,JDK 15 却要来了!|新特性尝鲜
- 36个助你成为专家需要掌握的JavaScript概念
- Bulehero 蠕虫病毒安全分析报告
- 一句话加速grep近30倍
- 正道的光!这有个用TensorFlow做的小黄图过滤器
- Bytom侧链Vapor源码浅析-节点出块过程
- Logstash: 启动监控及集中管理