当前位置:编程学习 > JAVA >>

局部变量声明而不赋值,和赋值为null,在内存分配上有什么区别?

在主方法中声明

String str;
栈内存中会开辟一块空间用来保存引用str

String str = null;
这句话同上,只会在内存的栈中开辟一块空间保存String引用str,并没有在堆中建立任何对象,或者令引用str指向堆中的某个位置

可是,为什么再后面的代码中,如果需要使用str的时候,第一句话会报错(未被初始化),第二句话却不会报错呢?
难道说,令str=null;意味着str会指向堆内存中的某个位置?
--------------------编程问答-------------------- null 空对象吧,也许正如你说的令str=null;意味着str会指向堆内存中的某个位置。
--------------------编程问答-------------------- 一个是在堆取分配了个地址,但是没有分配内存,而没有复制null的就连地址也没有分配!
(一个初始化了,一个没有!) --------------------编程问答-------------------- 初始化一个局域变量为null,是为了在非法使用此变量时报空指针异常,容易找到错误发生的地方,只是一个习惯,不是必须 --------------------编程问答--------------------
引用楼主 bigbro001 的回复:
String str = null;

在堆内存中为str分配了未指向任何有效内存的null值

String str;
中 str是个空引用 --------------------编程问答-------------------- String str; // 这是声明一个String变量,由系统分配堆中的一个地址
String str = null; // 这种方式,是声明一个String变量,但是你暂时不想给它分配对象,那么就用一个null来完成初始化,null是对空对象的一个标识

在第一种情况下,java不允许对没有初始化的对象进行操作,所以这个时候会报一个编译错误,说让你初始化这个对象。 --------------------编程问答--------------------
引用 5 楼 yanmushi 的回复:
String str; // 这是声明一个String变量,由系统分配堆中的一个地址
String str = null; // 这种方式,是声明一个String变量,但是你暂时不想给它分配对象,那么就用一个null来完成初始化,null是对空对象的一个标识

在第一种情况下,java不允许对没有初始化的对象进行操作,所以这个时候会报一个编译错误,说让你初始化这个对象。

String str; color=#FF0000]系统不会分配堆中的一个地址[/color]
--------------------编程问答-------------------- 用c++跟你解释一下

在main方法中声明的变量都是局部变量
String a;相当于String *a;//a里存的是地址,地址并没有初始化为0,还是原先那块内存的值(相当于指针指向了一块地址,而这块地址可能并不是你程序使用的地址),如果没有初始化就使用,后果是可怕的,所以java禁止使用未初始化局部变量

String a = null相当于String *a = 0;将指针不指向任何元素 --------------------编程问答-------------------- String s ="a";与String s = new String("a");
有本质的区别:前者是在字符串池里写入一个字符‘a’,然后用s指向它。
  后者是在堆上创建一个内容为“a”的字符串对象。
String s ="a"; //于栈上分配内存
String s = new String("a"); //于堆上分配内存
String a = null;赋予的值为null,是分配的空间中存储的值为null值。(是为a引用在栈中(字符串池里)分配的值为null值)
-------------------------------------------------------------------------------------
Object o; 这种写法只是分配一个引用而已。
Object o = null; 这么写则是给引用指向了一个空对象。具体差别如下:
class Test {

  public static void main(String[] args) {
  Object o1;
  o1.toString(); /*这里编译不能通过,编译器只认定o1是个引用,没指向任何对象,所以不能调用方法。*/
  Object o2 = null;
  o2.toString(); /*这里编译可以过,但是有空指针异常,编译器认定o2是一个对象,虽然是一个空对象。*/
  }
}
一个是给一个不存在的人取名字,一个是给死人取名字。你叫不存在的人吃饭这个是谬论,叫死人吃饭则是忽悠。  
null对象是一个特殊的对象,他可以是任何类型。他只是作为一个标记而已,只是为了标记不存在而存在的。也没必要去追究他在内存是什么样。null就是一个标记而已。容器可以接受一个空对象,但是一个空引用则是不接受的 --------------------编程问答-------------------- 其实就是一个未被初始化,一个被初始化! --------------------编程问答-------------------- 上面已有答案,楼主仔细看吧。 --------------------编程问答-------------------- --------------------编程问答-------------------- 楼上已有答案 --------------------编程问答-------------------- 楼上的答案已经很详细了,lz还可以在看一些java虚拟机分配的一写知识 --------------------编程问答-------------------- 不被初始化的内容是随机的 --------------------编程问答-------------------- 不清楚 --------------------编程问答-------------------- 在main方法中声明的变量都是局部变量
String a;相当于String *a;//a里存的是地址,地址并没有初始化为0,还是原先那块内存的值(相当于指针指向了一块地址,而这块地址可能并不是你程序使用的地址),如果没有初始化就使用,后果是可怕的,所以java禁止使用未初始化局部变量

String a = null相当于String *a = 0;将指针不指向任何元素 --------------------编程问答-------------------- 多谢楼上各位前辈的热心解答,还是JavaSE版人气高啊。。。可惜老紫竹,ZangXT大侠,火龙果,猴子等前辈不见了。。。 --------------------编程问答-------------------- 打个比方
String str;就像你准备生产一个盒子,在盒子生产出来之前你给它了名字叫str,但盒子到底是什么却没有实体
而String str=null;就像你已经生产了盒子,给这个盒子起名叫str
换做内存就是:String str;就是给出了堆栈空间的名字,却没有给出堆栈的实际空间
而String str=null,就是给出了堆栈的空间名字,并且给出了堆栈的空间,虽然这个空间什么都没有

                                                   ----初学者的一点浅薄理解,有不对的地方请大侠指正 --------------------编程问答-------------------- 学到了  谢谢各位大虾   楼主给分 --------------------编程问答-------------------- 多谢各位的热心分享,试着总结:

1) String str;
栈内存开辟一块空间,存储str引用

2) String str = null;
栈内存开辟一块空间,储存str引用,
栈内存中(或者堆内存中?)开辟一块空间,
str指向那块空的内存的地址

3)String str = new String("String");
栈内存开辟一块空间,储存str引用,
堆内存中开辟一块空间,储存新建的String对象“String”,
str指向堆内存中新String对象的地址
--------------------编程问答--------------------
引用 20 楼 bigbro001 的回复:
多谢各位的热心分享,试着总结:
2) String str = null;
栈内存开辟一块空间,储存str引用,
栈内存中(或者堆内存中?)开辟一块空间,
str指向那块空的内存的地址
3)String str = new String("String");
栈内存开辟一块空间,储存str引用,
堆内存……

2)是在堆内存中
3)String str = new String("hello"); 先在内存的常量池中查询是否存在“hello”,如存在,则将该块空间复制一份到内存的堆区间上,并将str指向该块区域,如不存在,则先在常量池中创建 一个“hello”,然后将其复制到堆,再令str指向它。就是说无论如何都必然会创建一个新的Hello字符串对象,不管你字符串池有没有

结贴 啦啦啦~~~  其实我也不懂 抄来的 呼呼 --------------------编程问答-------------------- --------------------编程问答-------------------- 敢问楼上的大侠,如果是:
String str = null;
str = "String";

这种情况,第一句话还是在堆内存中开辟空间吗?
--------------------编程问答--------------------
引用 23 楼 bigbro001 的回复:
敢问楼上的大侠,如果是:
String str = null;
str = "String";

这种情况,第一句话还是在堆内存中开辟空间吗?


应该是开辟的,null 和  什么都不写是有区别的
你可以理解:一个平台,String str;表示平台上什么都没有,及没有开辟空间,String str=null;表示平台上有一个空箱子,虽然箱子里什么都没有,但仍然是开辟了空间的 --------------------编程问答-------------------- 恩。。。俺的意思是,
String str = null;
str = "String";
最后的"String"对象是建立在栈里的,而不是堆里的,这样一来,第一句话,仍然还是在堆中开辟空间么?因为最后的对象其实是在栈中,如果一开始声明null的时候,在堆中开辟空间,岂不是有点奇怪? --------------------编程问答-------------------- 肯请各位热心前辈分享? --------------------编程问答-------------------- 我感觉看过 Thinking in Java 的人就喜欢研究这种问题! --------------------编程问答-------------------- 终于再次看到久违的火龙果大侠了。。。3年前还是3星,现在变成了5星。。。另一个厉害人物ZangXT貌似很久没来过了。。。 --------------------编程问答-------------------- 我还是不懂啊,没有一个专业的内存解释。 --------------------编程问答--------------------
引用 23 楼  的回复:
敢问楼上的大侠,如果是:
String str = null;
str = "String";

这种情况,第一句话还是在堆内存中开辟空间吗?


String这种可以当做基本类型类使用的特殊关键字。不太适合来研究对象。个人见解。 --------------------编程问答--------------------
引用 25 楼  的回复:
恩。。。俺的意思是,
String str = null;
str = "String";
最后的"String"对象是建立在栈里的,而不是堆里的,这样一来,第一句话,仍然还是在堆中开辟空间么?因为最后的对象其实是在栈中,如果一开始声明null的时候,在堆中开辟空间,岂不是有点奇怪?

1. null不是一个对象,JLS 3.10.7 中提及的是The Null Literal,况且它是ASCII中值为0的一个字符
2. null instanceof Object 是false 也证明了它不是Object
3. null在JVM全局内存中只存在一个,因为它无需存在多个,造成不必要浪费,因此挺符合String interned的初衷。All literal strings and string-valued constant expressions are interned. 我觉得null勉强能算是literal string,因为它是基于字符的。

综上,既不是Object又够格interned,所以认为null是在栈中开辟。 --------------------编程问答-------------------- 赋值为null的最后都会被JVM回收机制所回收,并不会去占用内存! --------------------编程问答--------------------
引用 25 楼  的回复:
恩。。。俺的意思是,
String str = null;
str = "String";
最后的"String"对象是建立在栈里的,而不是堆里的,这样一来,第一句话,仍然还是在堆中开辟空间么?因为最后的对象其实是在栈中,如果一开始声明null的时候,在堆中开辟空间,岂不是有点奇怪?

看看下面的字节码,LZ就明白了

  Code:
   0:   aconst_null
   1:   astore_1
   2:   ldc     #19; //String String
   4:   astore_1
   5:   return

  LineNumberTable:
   line 12: 0
   line 13: 2
   line 16: 5

  LocalVariableTable:
   Start  Length  Slot  Name   Signature
   0      6      0    args       [Ljava/lang/String;
   2      4      1    str       Ljava/lang/String;

--------------------编程问答-------------------- 来个总结吧:

int test(){
String str = null;
str = "String";
}
像这种String str = xxx;
不管xxx是null还是其他字符串,str这个东西都是在栈里有块空间,可以理解为c的指针,=null的时候,里面存的是0,非null的时候存的是实际字符串的地址(堆中或者常量池中)。

而String str;
这种情况,jvm同样也为其分配了一块空间,但是不知道值是多少
java语法要求引用之前必须初始化,所以你直接这么写,str根本不能引用,所以无所谓。
其实jvm也完全可以不为它分配空间。

这个问题,说到底,其实就是java的语法要求,必须初始化的问题。

如果有C语言经验的话,可能有这样的问题,
int i;
int j = i; //使用了未初始化的i
因为i没有初始化,所以i是个“随机的值”,比如i可能是5,可能是8,可能是……
java为了避免这种问题,语法上规定,局部变量在使用之前,必须初始化!如果不初始化就报错。
--------------------编程问答-------------------- 不知ZangXT大侠,火龙果,老紫竹等前辈有什么高见。。。 --------------------编程问答-------------------- 给你块地,地里现在有啥谁都不知道。
给你块地,同时把地清空了,啥都没有了。 --------------------编程问答-------------------- 恳请各位前辈提供思路。。。
补充:Java ,  Java SE
CopyRight © 2012 站长网 编程知识问答 www.zzzyk.com All Rights Reserved
部份技术文章来自网络,