Java的引用
总所周知,Java语言风格类似C和C++,继承学习了C++语言的面向对象技术的核心,同时去除了C++语言的指针,改用引用(refrence)取代。那为什么要去除指针呢,改用引用,引用与指针又有什么区别呢?
1、指针是什么?
指针是C语言的灵魂,指针(变量)是存储地址的变量,它实质是”间接寻址“的抽象,即通过一个变量查找所需要的地址。
下面是一个简单的C语言指针实例:
#include <stdio.h> #include <stdlib.h> int main() { int a = 3, b = 4; swap(&a, &b); printf("a = %d \n", a); printf("b = %d ", b); return 0; } void swap(int *a, int *b) { int temp = *a; *a = *b; *b = temp; }
通过指针能够方便并快速对变量进行底层操作,非常方便,使代码非常简洁,但是指针太灵活,太强大,很容易造成内存泄漏和产生off-the-end指针。利用指针编写的程序也更容易隐含各式各样的错误,同时程序的可读性也会大打折扣。所以Java去除了指针,而采用更加安全可靠的引用。
2、引用
那引用是什么?如果说指针是对地址的抽象,那引用(refrence)是对同一性(identity)的抽象。不是同一级别的概念。引用是封装了对象的地址,但它与指针还是有区别的,使用引用可以让使用Java程序员能够像操作基本数据类型一样操作对象,引用是受限的,不能对引用进行地址运算,只能进行赋值操作。
Object o; //这里是在堆栈中的创建的句柄(Handle) o = new Object(); //在堆中创建对象,并使句柄指向该对象
引用或句柄相当于电视机的遥控器,对遥控器操作,就能操作电视机,实际上,但我们按下”调小音量“,我们实际上操作的是遥控器,再有遥控器操作电视机,等价于直接操作电视机。当我们到处走走的话只需拿着遥控器即可,无需拿着电视机。引用是引用对象的遥控器,我们不能直接操作对象,只能通过引用进行操作。
个人感觉,Java中的引用是对对象的抽象,程序员使用引用就等价于使用对象,当然引用内部肯定包含了对象的地址。
3、引用与指针的区别
C与C++中的指针,方便用户快速对变量进行底层操作,指针能够运算,通过指针能够访问指针指向的变量。
Java中的引用是对对象的抽象,Java的设计者让用户类似操作基本数据类型的方法操作引用从而间接操作对象,程序员无法获得引用的值,无法对引用进行操作。只能进行赋值操作。
综上所述,Java中的引用可以看作受限的指针,该指针程序无法确定其值,也无法对指针进行运算。
4、Java的值传递
Java的变量类型有两种,基本类型和引用类型。
(1)基本类型的参数传递:基本类型的参数传递类似于C语言中的值传递。实例如下:
package com.cang.refrence; public class TestPrimitive { public static void main(String[] args) { int a = 3, b = 4; System. out.println( "Before swap the a and b: a = " + a + ",b = " + b); swap( a, b); System. out.println( "After swap the a and b: a = " + a + ",b = " + b ); } public static void swap( int a, int b) { int temp = a; a = b; b = temp; } }
运行结果:
内存抽象示意图:
(2)引用类型的参数传递
public class TestRefrence { public static void main(String[] args) { StringBuffer buffer= new StringBuffer( "colin"); SChange( buffer); System. out.println( buffer); } public static void SChange (StringBuffer str) { str= new StringBuffer( "huang"); } }
结果:colin
内存抽象示意图:
如上图所示,传递引用时,将引用的副本传递给方法的参数,但由于在方法里对该引用的拷贝进行赋值,所以该引用的拷贝指向其他对象,而不是原来的对象。
public class TestRefrence2 { public static void main(String[] args) { StringBuffer buffer= new StringBuffer( "colin"); SChange( buffer); System. out.println( buffer); } public static void SChange (StringBuffer str) { str.append( "huang"); } }
结果:colinhuang
内存抽象示意图:
综上所述,Java的方法传递只有值传递,基本数据类型传递是其值,而引用类型传递的是引用变量。