首页 诗词 字典 板报 句子 名言 友答 励志 学校 网站地图
当前位置: 首页 > 教程频道 > 开发语言 > 编程 >

基础部类与引用类型引申

2012-09-08 
基础类型与引用类型引申?一.基本类型与引用类型的值????????在计算机高级语言变量中包含两种不同数据类型:

基础类型与引用类型引申

?

.基本类型与引用类型的值

????????在计算机高级语言变量中包含两种不同数据类型:基本类型与引用类型.基本类型指那些保存在栈内存中的简单数据段,也就是说这些变量的值完全保存在栈内存中,而引用类型值指那些保存在堆中的对象,这就是说,引用类型变量在栈中保存的只是一个指向堆中指定对象的 指针而已,为什么要这么做呢,因为对象大小不能固定,而基础类型大小是固定的,如int型就占4个字节(不同语言,平台有所差异),我们可以将固定大小的放在一个数据结构中,如果是基础类型直接取值,如果是引用类型首先从栈中读取内存地址,然后顺藤摸瓜,根据地址找到在堆中的值,这样可以提高我们的查询速度,

????? ? JAVA中的基础类型有int,char,byte,long,short,boolean,特别注意String不是基础数据类型,但在javascript中ECMAScript放弃这一传统,将String作为基础数据类型.栈堆关系如下图,一目了然:


基础部类与引用类型引申

.复制变量值

???除了保存方式不同外,基础数据类型与引用同数据类型在复制变量时也不一样,如下例所示程序:

???????int?num1 = 5;

????????int?num2 = num1;

? ? ? ? num2 = 10;

? ? ? ? System.out.println(num1);???//5

? ? ? ? System.out.println(num2);???//10

????? ??初始变量num1的值等于5当将变量num1的值赋于变量num2,num2也保存了5的值,但这两个5的值是完全独立的,在num2中的5只是num1中的5的一个副本而已,相信这点大家很容易理解,下面配合图标将这次赋值过程展现出来:

?


基础部类与引用类型引申

?


基础部类与引用类型引申

????? ? 对于引用变量的复制,实质上,我们复制的是栈内存中的指针,也就是复制变量的指针的副本,复制后两个变量指向同一个对象,相信这一点也不难理解,惯例图表展现:

? ? ? ?Person p1 =?new?Person();

??????p1.setName("复制前所赋值");

??????Person p2 = p1;

??????p2.setName("复制后所赋值");

? ? ? ?System.out.println(p2.getName());//?复制后所赋值??????

?


基础部类与引用类型引申

?

.参数传递

???与变量复制一样,参数传递基础类型与引用类型也存在差异,在java这门计算机语言中,非常多的书籍都会写到基础数据类型是值传递,而引用类型是引用传递,其实我赞同前半句,不过对后半句有异议,后面再谈,首先先来看看基础类型的值传递.

????? ? 在向参数传递基本类型的值的时候,被传递的变量的值会复制给函数的一个局部变量,局部变量所对应的内存中会参数被传递变量值的副本,所以当我们修改局部变量时被传递变量不会发生改变:

? ??public?static?int?addNum(int?num) {

???????????num += 100;

???????????return?num;

????}

????int?num = 10;

????int?result =?addNum(num);

????System.out.println("操作后的num :"?+ num);?// 10

????System.out.println("结果result :"?+ result);?// 110

????? ?函数addNum()有一个参数num当我们使用变量num传入时,实际上是在addNum函数作用域内产生一个num局部变量,该局部变量的值是被传入参数值的副本,当我们修改局部变量时,外层变量不会发生改变,所以我们最后打印的时候外层变量仍然为10并没有受到函数参数自增100的影响。

? ??前面已经对引用类型参数传递的一些看法,下面我们先来看一个例子:

? ??public?static?void?setName(Person p) {

??p.setName("作为参数后的值");

? }

? Person p =?new?Person();

? p.setName("作为参数前的值");

? setName(p);

? System.out.println(p.getName());?//?作为参数后的值

? ? ?从上面例子可以看出,当我们创建一个对象后,调用函数对对象的属性进行修改,发现函数外层的对象也跟着修改了,可以看出参数p与外层对象p指向的是堆内存中的同一个对象,换句话说,这应该是一个值传递,因为前面我们已经说过,在栈内存中引用类型变量保存的是堆内存中对应对象的地址,所以参数获得了一个被传递变量的指针类型副本,下面我们再来看一个例子 :

? ?public?static?void?setName(Person p) {

????????p.setName("操作前名称");

????????p =?new?Person();?//?使参数指向新的堆地址

????????p.setName("操作后的名称");

????}

????Person p =?new?Person();

????setName(p);

????System.out.println(p.getName());?//?操作前名称

? ??与前一个例子相比,我们在setName函数中先对参数p赋值,然后让参数p指向一个新的对象,再赋值,结果打印出来的信息是我们在使得参数P指向一个新的对象之前所做的操作,也就是说并没有修改原被传递参数的指针信息,所以同样为值传递(javascript也是一样的)。

热点排行