堆栈和堆:堆栈存储速度仅次于寄存器,明显快于内存堆,存储对象的过称为:当需要开辟内存的时候指针下移,当需要释放空间的时候指针上移。然而这种方法要求明确对象大小和生命周期,所以缺乏灵活性。在Java中堆栈主要用于存储引用和基本数据类型的数据。
而堆采用的是动态开辟内存的方式,使用较为灵活,但是由于需要在程序运行期间存储对象所以会导致程序运行速度下降。在Java中堆主要用于存储new出来的对象。
1.基本数据类型
如果我们定义了一个int a=3;程序会在栈中开辟一块内存用于存储a和值3;如果这时又定义了int b=3;那么a和b此时会指向栈中同一个对象。
2.普通引用
如果我们定义了一个ArrayList list=new ArrayList();list引用就会存放在栈中,而list指向的对象就会存在于堆中。
3.字符串
当我们定义了一个String s="haha";s引用存在于栈中,s指向的对象却不在堆中而是存在与一个叫“常量池”的地方。同样的如果我们定义了一个final int MAX_VALUE=20;该变量也会被放入常量池。
而如果用String s2=new String("hehe")方法创建字符串对象;那么程序就会在堆中创造一个相应的对象,同时,它还会在常量池创建一个字符串(前提是常量池中并不存在该对象)。
下面是一个栗子:
- public class Test {
- public static void main(String[] args) {
- String str=new String("abc");//对象存在与堆中
- char[] ch={'z','w','q'};
- Test test=new Test();
- test.change(str, ch);//操作str和ch
- System.out.println(str+","+ch[0]);
- }
-
- public void change(String str,char[] ch){
- str="new value";
- ch[0]='y';
- }
- }
复制代码
输出的结果为abc,y;
问题:为什么在方法里面str指向的对象改成了“new value”,那么为什么输出的结果是“abc”呢?
分析:这里的str虽然是一个引用,然而它所指向的对象却是一个字符串(常量)。而在方法里面str指向的对象发生了改变,但是方法一旦调用结束引用就会消失,而原来的str引用所指向的对象"abc"并没有发生变化,所以打印出来的仍然是"abc";
这里有一个作用域的概念:一旦change()方法调用结束引用就被销毁了然而“new value”仍然存在于常量池中。
对比老师讲过的引用传递的例:
- public class Test {
- public static void main(String[] args) {
- ArrayList list=new ArrayList();
- list.add(0);
- list.add(1);
- list.add(2);
- change(list);//传递的引用的值
- System.out.println(list);
- }
-
- public static void change(ArrayList list){
- ArrayList list2=list;
- list2.remove(0);//list指向的对象已经发生改变了
- }
- }
复制代码 打印结果:【1,2】
这个例子和上面的例子的区别在于list指向的对象在方法中被改变,而上面的例子中引用str指向的对象根本没变化。
所以所谓引用传递和普通数值传递的区别在于能否改变所指向的对象。
欢迎拍砖,始终相信理越辩越明~~~~~~
|
|