闲来纠结
闲来无聊,想起了写博客。左思右想不知道写什么好,想了半天,还是把这个问题说说吧。想想自己在学习java的时候,在这个问题上,吃了很多的苦,现在想起来,那时也还真是的。为了让不懂java对象引用的朋友少走弯路,让大家彻底的懂的这是为什么?就有了这篇博文。本博文将从C++引用和Java引用的比较来剖析Java的引用特性和使用方法,还有一些易错点。
引用?
什么叫引用?因为学了Java,Java是面向对象的语言,此时,人们就难免会拿Java来和C++进行比较,是的C++是C的超级,但并不是完全的面向对象,还是有写少许的C的面向过程的东西。说道了引用,我在这里也就不得不把C++的引用和Java的对象引用拿来比较一番。
C++引用
现在就来详细的说说C++中的引用。
在C++中,使用引用的地方很多。如,引用参数。这是我们见得最多的,因为有了好处,我们才用的。引用引入了对象的一个同义词。定义引用的表示方法与定义指针相似,只是用&代替了*。
例如: Point pt1(10,10); Point &pt2=pt1; 定义了pt2为pt1的引用。通过这样的定义,pt1和pt2表示同一对象。需要特别强调的是引用并不产生对象的副本,仅仅是对象的同义词。因此,当下面的语句执行后:
pt1.offset(2,2);
pt1和pt2都具有(12,12)的值。引用必须在定义时马上被初始化,因为它必须是某个东西的同义词。你不能先定义一个引用后才初始化它。例如下面语句是非法的: Point &pt3; pt3=pt1;
在C++中,引用就是对象的一个别名,而在Java中是显然不同的。从C++程序员转干Java时,这个问题,是很困惑的。下面的这段代码更能说明问题:
#include <iostream> using namespace std; //class A class A { public: A(); ~A(); void setNum(); int getNum(); private: int num; }; A::A() { num = 10; } A::~A() { } int A::getNum() { return num; } void A::setNum() { num = 11; } //测试函数 void test1(A &a) { a.setNum(); cout<<a.getNum()<<endl; } void test2(A *&a) //引用指针,相当BT的东西,但是非常有用 { //会看到,如果delete了a,就输出出错了,这说明,这个就是对原对象的操作,如果不信,看test3 //delete a; //a = NULL; a->setNum(); cout<<a->getNum()<<endl; //在此处delete也会对外部的产生影响 delete a; a = NULL; } void test3(A *a) { a->setNum(); cout<<a->getNum()<<endl; //同样的,我也是delete了,但是不是对原对象的实际操作,只是对参数的操作 delete a; a = NULL; } int main() { A *a1 = new A(); //此时a1对象是在堆上开辟的 A a2; //此时a2是在堆栈上开辟的,而在Java中是不允许这样定义的(除了基本数据类型) cout<<"From a1: "<<a1->getNum()<<endl; cout<<"From a2: "<<a2.getNum()<<endl; cout<<"From a2 after setNum: "; test1(a2); //cout<<"From a1 after setNum: "; //test2(a1); cout<<"From a1 after setNum: "; test3(a1); //cout<<"From a1: "<<a1->getNum()<<endl; }
Java引用
现在是Java引用,这也是我很头疼的问题。Java中没有所谓的“指针”,但是也可以说“有”。这是一个纠结的问题。学习Java的人一直都是这么认为的。看如下代码,同时比较上面的代码,二者的区别是很明显的。
public class test { static int[] a = new int[10]; public static void main(String[] args) { Init(); //Print(); test(); //Print(); } static void Init() { for (int i = 0; i < a.length; ++i) { a[i] = i; } } static void Print() { for (int j = 0; j < a.length; ++j) { System.out.print(a[j] + " "); } } static void test() { for (int j = 0; j < a.length; ++j) { System.out.print(a[j] + " "); } a = null; //在java中是用引用操作对象的,会发现,同样是引用,但是对外部对象没有影响 } }
C++引用 VS Java引用
在C++中使用new在堆中开辟的空间,再栈中有一个指针指向该堆空间,使用该指针便可以操作该堆中的对象,Java亦是同理,但是在C++中的引用指针,和Java中的引用有的一比,在Java中的引用,还是有那么点指针的意思,如果把Java该处的引用理解成“指针”。那么直接就可以理解成C++的内部问题了,可以看成是C++的指针和引用的区别了。
但是,我们不能在Java中提到和C++中的一样的指针,那样的话就更无知了,就是你的内心把它当做指针来理解,但是,你也不能说那就是指针,因为“Java之父”会生气的。
在Java中的引用,引用和对象是两个事情,但是,如果你用引用名对对象的方法或者属性操作的话,那是会有效果的,那是必须有效果的,如果没有效果,那就没有任何用处了。而在C++中的引用和对象是就是同一个实体,只是名字不一样的而已,对引用的操作及对对象实体的操作,为什么有这样的区别呢?你应该知道,在Java中不能这样定义一个对象的。,A a;之后就直接使用a了,这样是错误的,但是在C++中是可以的。所以,在C++中的引用,我个人认为,更能称的上是引用,而Java中的引用,有点,徒有提名,而无其实的感觉。你认为呢?