引用类型

关于JS堆栈与拷贝

一笑奈何 提交于 2020-01-06 03:55:45
1、 栈(stack) 和 堆(heap)    stack 为自动分配的内存空间,它由系统自动释放;而 heap 则是动态分配的内存,大小不定也不会自动释放。        2、基本类型和引用类型    基本类型: 存放在栈内存中的简单数据段,数据大小确定,内存空间大小可以分配。   5种基本数据类型有 Undefined、Null、Boolean、Number 和 String ,它们是直接按值存放的,所以可以直接访问。    引用类型: 存放在堆内存中的对象,变量实际保存的是一个指针,这个指针指向另一个位置。每个空间大小不一样,要根据情况开进行特定的分配。   当我们需要访问引用类型(如 对象,数组,函数 等)的值时,首先从栈中获得该对象的地址指针,然后再从堆内存中取得所需的数据。 3、传值与传址   前面之所以要说明什么是内存中的堆、栈以及变量类型,实际上是为下文服务的,就是为了更好的理解什么是“浅拷贝”和“深拷贝”。   基本类型与引用类型最大的区别实际就是 传值与传址的区别 。测试用例: 1 var a = [1,2,3,4,5]; 2 var b = a; 3 var c = a[0]; 4 alert(b);//1,2,3,4,5 5 alert(c);//1 6 //改变数值 7 b[4] = 6; 8 c = 7; 9 alert(a[4]);//6 10

谈谈.NET的协变和逆变

柔情痞子 提交于 2020-01-04 05:25:30
伴随 Visual Studio2010 的发布, C# 这门语言提供一些新的特性,包含协变( Covariant )和逆变( Contravariant )、动态( Dynamic )和 DLR 、命名参数和可选参数、索引属性、 COM 调用优化和嵌入 COM 互操作类型。写本文的目的主要是探讨下泛型类型的协变和逆变,按照以往版本 .NET 新特性的增加,一般是由新的关键字、 Attribute 来标注,继而编译器或者 .NET Runtime 负责解析执行。这两个新特性也是如此,两个关键字 in/out 。 目录 1. 协变逆变的 追本溯源 2. 协变逆变的 深入分析 3. 协变逆变的 场景应用 4. 总结 一. 追本溯源 协变和逆变需 .NET Runtime的支持,但是在以往的几个.NET 版本中,都是提供这种支持。可能大家都纳闷了,C#只是支持.NET平台的一门语言,这两者关系表明C#语言不支持,我们只有干瞪眼,还好沉寂了好几个版本之后,千呼万唤始出来。简明分析下应用场景变迁:以前都是面向对象编程,现在逐渐面向服务编程,泛型类型大量在程序设计结构中的使用,以及.NET3.0 LINQ等等应用活跃。还是举一个code场景,对于泛型接口IEnumerable<T>和IEnumerator<T>,我们经常在foreach循环进行操作,为了保证服务接口的共用性、稳定性、代码重用

final,权限,引用类型数据

北城余情 提交于 2020-01-03 07:23:11
1. final关键字 1.概述 为了避免子类出现随意改写父类的情况,java提供了关键字 final ,用于修饰不可改变内容 final:不可改变,可以修饰类,方法和变量 类:被修饰的类,不能用于继承 方法:被修饰的方法,不能被重写 变量:被修饰的变量,不能重新赋值 2.使用方式 修饰类 格式如下: public final class 类名{ } 含义: 当前这个类不能拥有任何的子类. (太监类) 注意: 一个类如果是final的, 那么其中的所有的成员方法都无法进行覆盖重写(没有儿子) String,Math,Scanner这些类都是被final修饰的,目的是供我们使用,而不让我们改变内容 修饰方法 格式: 修饰符 final 返回值类型 方法名(参数列表){ //方法体 } //注意: 对于类,方法来说, abstract关键字和关键字final 不能同时使用,矛盾 重写 final 修饰的方法,编译时就会报错 修饰变量 1.局部变量—基本类型 基本类型的局部变量,被 final 修饰后,只能赋值一次,不能再更改. public class FianlDemo{ public static void main(String[] args){ // 声明变量,被final修饰 final int a; //第一次赋值 a = 10; //第二次赋值直接报错 final int

C# 数据类型

邮差的信 提交于 2020-01-02 08:09:13
类型分类 类型归属 内存分配 内存: 分配: 值类型与引用类型 装箱拆箱 装箱: 是将值类型转换成引用类型。 拆箱: 是将引用类型转换成值类型,只有装箱过的对象才能拆箱。 为何需要装箱?(为何要将值类型转为引用类型?) 一种最普通的场景是,调用一个含类型为Object的参数的方法,该Object可支持任意类型,以便通用。当你需要将一个值类型(如Int32)传入时,需要装箱。 另一种用法是,一个非泛型的容器,同样是为了保证通用,而将元素类型定义为Object。于是,要将值类型数据加入容器时,需要装箱。 装箱其实就是把栈上的数据放到堆上去了。而拆箱就是把堆上的数据放在栈上。在拆箱和装箱的过程中,无可避免的多了数据转换,申请内存等。从而降低了性能。所以我们要避免装箱和拆箱。 来源: CSDN 作者: 奋斗的菇凉 链接: https://blog.csdn.net/qq_40229737/article/details/103771848

Java中的13个原子操作类

空扰寡人 提交于 2020-01-01 15:34:06
目录 原子更新基本类型类 原子更新数组 原子更新引用类型 原子更新字段类 当程序更新一个变量时,如果多线程同时更新这个变量,可能得到期望之外的值,比如变 量i=1, A线程更新i+1, B线程也更新i+ 1, 经过两个线程橾作之后可能i不等于3, 而是等于2。因 为A和B线程在更新变量i的时候拿到的i都是1, 这就是线程不安全的更新操作,通常我们会使 用synchronized来解决这个问题,synchronized会保证多线程不会同时更新变量i。 而Java从JDK 1.5开始提供了java.util.concurrent.atomic包(以下简称Atomic包),这个包中 的原子操作类提供了一种用法简单、性能高效、线程安全地更新一个变量的方式。 因为变量的类型有很多种,所以 在Atomic包里一共提供了13个类,属于4种类型的原子更 新方式,分别是原子更新基本类型、原子更新数组、原子更新引用和原子更新属性(字段)。 Atomic包里的类基本都是使用Unsafe实现的包装类。 原子更新基本类型类 使用原子的方式更新基本类型,Atomic包提供了以下3个类。 AtomicBoolean 原子更新布尔类型。 Atomiclnteger 原子更新整型。 AtomicLong 原子更新长整型。 以上3个类提供的方法几乎一模一样,所以本节仅以Atomiclnteger为例进行讲解,

二、对象访问模式

点点圈 提交于 2020-01-01 07:28:53
句柄、直接指针 很多语言中都存在一个句柄的概念,这个概念的产生主要是在引用数据类型上,比如下面一段代码: Object obj = new Object ( ) ; 这段代码可以按照两个部分考虑 “Object obj” 声明对象,此处表示的是一个本地引用,那么这个本地的引用一定会本身保留一个堆内存的地址,还会包含一个本地变量表的概念,也就是说,引用类型通过本地变量表才能找到一个堆内存的引用数据 obj=new Object(); 实例化对象, 实例化对象就会开辟堆内存空间。 在进行引用设计的过程中,有两种途径 通过句柄访问 当发现需要的是一个引用类型,它会通过一个“对象实例的数据指针”找到一个“对象实例数据”,但是数据本身只是描述对象里的内容,它还需要一个“对象类型数据指针”去找到一个“对象类型数据”。 也就是说,数据和数据的类型是怎么存放的?通过不同的指针来进行不同的引用,这就是通过句柄访问。像C++就是通过句柄访问 直接指针访问 当发现需要的是一个引用类型,会指向“对象实例数据”,在“对象实例数据”中本身就包含了“对象类型数据指针”。不同于句柄,Java直接找的就是数据,当需要操作数据时再根据“数据类型指针”找方法区的“对象类型数据” 虚拟机规范 以上所见的是HotSpot虚拟机本身实现的引用类型的访问机制,但是对于Java虚拟机存在三种规范:

11.Actomic原子类

南楼画角 提交于 2019-12-31 21:34:13
文章目录 1. 原子更新基本类型类 2. 原子更新数组 3. 原子更新引用类型 4. 原子更新字段类 1. 原子更新基本类型类 AtomicBoolean:原子更新布尔类型 AtomicInteger:原子更新整型 AtomicLong:原子更新长整型 常用方法如下: int addAndGet(int delta):以原子方式将输入的数值与实例中的值(AtomicInteger 里的 value)相加,并返回结果 boolean compareAndSet(int expect,int update):如果输入的数值等于预期值,则以原子方式将该值设置为输入的值 int getAndIncrement():以原子方式将当前值加1,注意,这里返回的是自增前的值 void lazySet(int newValue):最终会设置成 newValue,使用 lazySet 设置值后,可能导致其他线程在之后的一小段时间内还是可以读到旧的值 int getAndSet(int newValue):以原子方式设置为 newValue 的值,并返回旧值 原子性的设置原理:通过死循环+CAS实现 public final int getAndAddInt(Object var1, long var2, int var4) { int var5; do { var5 = this

运行库中的泛型

≯℡__Kan透↙ 提交于 2019-12-29 02:36:09
将泛型类型或方法编译为 Microsoft 中间语言 (MSIL) 时,它包含将其标识为具有类型参数的元数据。泛型类型的 MSIL 的使用因所提供的类型参数是值类型还是引用类型而不同。 第一次用值类型作为参数来构造泛型类型时,运行库会创建专用泛型类型,将提供的参数代入到 MSIL 中的适当位置。对于每个用作参数的唯一值类型,都会创建一次专用泛型类型。 例如,假设您的程序代码声明了一个由整数构造的堆栈,如下所示: Stack < int > stack; 在此位置,运行库生成 Stack <T> 类的专用版本,并相应地用整数替换其参数。现在,只要程序代码使用整数堆栈,运行库就会重用生成的专用 Stack<T> 类。在下面的示例中,创建了整数堆栈的两个实例,它们共享 Stack<int> 代码的单个实例: Stack < int > stackOne = new Stack < int > (); Stack < int > stackTwo = new Stack < int > (); 但是,如果在程序代码中的其他位置创建了另一个 Stack<T> 类,这次使用不同的值类型(如 long 或用户定义的结构)作为其参数,则运行库会生成泛型类型的另一版本(这次将在 MSIL 中的适当位置代入 long )。由于每个专用泛型类本身就包含值类型,因此不再需要转换。 对于引用类型

C++右值和移动

自闭症网瘾萝莉.ら 提交于 2019-12-28 16:03:51
自C++11以来,C++进入Modern C++时代。移动语义是C++11里引入的一个重要概念;理解这个概念,是理解很多现代C++里的优化的基准 值分左右 我们常常会说,C++里有左值和右值。这话不完全对。标准里的定义实际更复杂,规定了下面这些值类别(value categories): 我们先理解一下这些名词的字面含义: 一个 lvalue 是通常可以放在等号左边的表达式,左值 一个 rvalue 是通常只能放在等号右边的表达式,右值 一个 glvalue 是 generalized lvalue,广义左值 一个 xvalue 是 expiring lvalue,将亡值 一个 prvalue 是 pure rvalue,纯右值 还是有点晕,是吧?我们暂且抛开这些概念,只看其中两个:lvalue 和 prvalue。 左值 lvalue 是有标识符、可以取地址的表达式,最常见的情况有: 变量、函数或数据成员的名字 返回左值引用的表达式,如 ++x、x = 1、cout << ’ ’ 字符串字面量如 “hello world” 值得注意的是: 函数名属于不可修改的左值。 cout << ''返回的确实std::ostream类型的左值,但由于在basic_ostream类中,operator=被声明为delete,故也不能进行赋值操作。 basic_ostream &

Hotspot 垃圾回收之BarrierSet(一) 源码解析

前提是你 提交于 2019-12-28 08:35:50
目录 一、BarrierSet 1、定义 2、write_ref_field_pre/write_ref_field/write_ref_array/write_region 3、static_write_ref_array_pre / static_write_ref_array_post 二、CardTableModRefBS 1、定义 2、构造函数和initialize 3、inline_write_ref_field_pre/inline_write_ref_field/inline_write_region/inline_write_ref_array 4、mod_card_iterate /dirty_card_iterate /dirty_card_range_after_reset 5、clear /invalidate 6、resize_covered_region 上一篇 《Hotspot 垃圾回收之CollectedHeap 源码解析》 中讲解CollectedHeap的定义时提到了一个BarrierSet类,该类的具体用途没有注释说明,但是该属性的调用方很多,本篇博客就详细探讨这个神秘的BarrierSet的实现和使用。 一、BarrierSet 1、定义 BarrierSet表示一个数据读写动作的栅栏