我们都知道Java是一个面向对象的编程语言,那么java对象究竟是如何创建和操作的呢?
Demo demo=new Demo();
首先我们看上面这一段代码,虽然很简单却有着其内部的一些机理。前面的Demo demo
是一个引用的创建,而后面new Demo();
则是一个对象的创建。如果把对象当作一个电视的话,引用实际上相当于一个遥控器。
为了弄清楚其中发生了什么,我们首先要知道两者存储位置的一些差别。对象存储在堆中,因为其内存和生命周期都是不确定的,需要动态分配并且不能确定其占用内存需要回收的时间。而引用实际上是一小段指向对象所在堆地址的确切的地址数值,其大小是确定的,并且拥有可以确定的生命周期,所以引用在栈中。知道了这些我们再看第一句代码,new在堆中创建了一个Demo对象,然后在栈中创建了一个Demo引用,最后用等号给引用赋值,让引用指向Demo对象的地址,这句话就完整的执行完了。
class Demo{
public void hello() {
System.out.println("hello!");
}
}
public class test {
public static void main(String[] args) {
// TODO Auto-generated method stub
Demo demo=new Demo();
}
}
我们看上面这段代码,当程序运行完时,demo这个引用变量由于其生命周期结束,分配的栈内存会立即被会回收,但是在堆中的对象却不会,而是等待虚拟机在一个不确定的时间对它进行回收,这是两者在生命周期上的差别。
Demo demo=new Demo();
Demo demo2=demo;
我们再看上面这段代码,这样执行的结果是demo和demo2实际表示的是同一个对象,他们都记载着同一个Demo对象所在堆地址,所以如果使用其中一个更改,整个对象都会被更改。
class Demo{
int a;
public void add() {
a++;
}
}
public class test {
public static void main(String[] args) {
// TODO Auto-generated method stub
Demo demo=new Demo();
Demo demo2=demo;
demo2.add();
System.out.print(demo.a);
}
}
上面这段代码最终输出的结果就是1。由于堆中的数值会自动初始化,所以a的初值会自动设为0,对demo2引用的对象进行a++,实际上也就是对demo所引用的对象进行a++,从中我们就很好看出两者的关系。一个对象可以被多个引用指向,而一个引用只能指向一个对象。
在c++中我们同样学过对象相关的内容,对比来看,c++中的对象和Java中有什么不同呢?
首先,在c++中,Demo demo;
就意味着创建了一个Demo的对象,而Java中这么做则是创建了一个引用。其次,Java中没有指针这个概念,使用引用来操作对象,而c++中则需要通过指针来操作对象。
//c++
Demo *demo=new Demo();
demo->add();
demo->say();
对比Java来说指针的使用很容易出错,而且难度也很大,所以Java取消指针而采用引用可以说方便了不少。当然引用和指针有诸多区别,比如指针可以计算而引用并不能。指针可以计算直接的问题就在于指针可能会指向一些奇怪的地方,一些不应该由本程序操作的地方,这是非常危险的,对于我们程序员来说也是不好控制的。而引用则永远不会作用在程序意外的地方。所以对比来看引用安全,没有大小且不可计算。但是使用指针也有指针的好处,因为指针的使用更加灵活高效,直接在地址上进行运算使得c++的数组存取效率高于Java。综合来说两者各有优略,虽然本质上都是想指向要操作的东西,但使用时要注意区分,不能混为一谈。