分享

深入Java关键字null

 燮羽 2010-12-05
一、null是代表不确定的对象
 
Java中,null是一个关键字,用来标识一个不确定的对象。因此可以将null赋给引用类型变量,但不可以将null赋给基本类型变量。
 
比如:int a = null;是错误的。Ojbect o = null是正确的。
 
Java中,变量的适用都遵循一个原则,先定义,并且初始化后,才可以使用。我们不能int a后,不给a指定值,就去打印a的值。这条对对于引用类型变量也是适用的。
 
有时候,我们定义一个引用类型变量,在刚开始的时候,无法给出一个确定的值,但是不指定值,程序可能会在try语句块中初始化值。这时候,我们下面使用变量的时候就会报错。这时候,可以先给变量指定一个null值,问题就解决了。例如:
 
        Connection conn = null;
        try {
            conn = DriverManager.getConnection("url", "user", "password");
        } catch (SQLException e) {
            e.printStackTrace();
        }
 
        String catalog = conn.getCatalog();
 
如果刚开始的时候不指定conn = null,则最后一句就会报错。
 
二、null本身不是对象,也不是Objcet的实例
 
null本身虽然能代表一个不确定的对象,但就null本身来说,它不是对象,也不知道什么类型,也不是java.lang.Object的实例。
可以做一个简单的例子:
 
        //null是对象吗? 属于Object类型吗?
        if (null instanceof java.lang.Object) {
            System.out.println("null属于java.lang.Object类型");
        } else {
            System.out.println("null不属于java.lang.Object类型");
        }
 
结果会输出:null不属于java.lang.Object类型
 
三、Java默认给变量赋值
 
在定义变量的时候,如果定义后没有给变量赋值,则Java在运行时会自动给变量赋值。赋值原则是整数类型int、byte、short、long的自动赋值为0,带小数点的float、double自动赋值为0.0,boolean的自动赋值为false,其他各供引用类型变量自动赋值为null。
这个具体可以通过调试来看。
 
四、容器类型与null
 
List:允许重复元素,可以加入任意多个null。
Set:不允许重复元素,最多可以加入一个null。
Map:Map的key最多可以加入一个null,value字段没有限制。
数组:基本类型数组,定义后,如果不给定初始值,则java运行时会自动给定值。引用类型数组,不给定初始值,则所有的元素值为null。
 
五、null的其他作用
 
1、判断一个引用类型数据是否null。 用==来判断。
2、释放内存,让一个非null的引用类型变量指向null。这样这个对象就不再被任何对象应用了。等待JVM垃圾回收机制去回收。

java语言规范中是这么规定的: 

A literal is the source code representation of a value of a primitive type , the String type , or the null type : 

 Literal:     IntegerLiteral     FloatingPointLiteral     BooleanLiteral     CharacterLiteral     StringLiteral     NullLiteral 

While true and false might appear to be keywords, they are technically Boolean literals (§3.10.3). Similarly, while null might appear to be a keyword, 
it is technically the null literal (§3.10.7). 
The null type has one value, the null reference, represented by the literal null,which is formed from ASCII characters. A null literal is always of the null type. 
 
以下是我的一些想法:
package com.zac.expe1;
public class NullInDepth {
 public static void helloThere(){
  System.out.println("Hello from null?!");
 }
 
 public static void main(String[] args) {
  //((NullInDepth)null).helloThere();
  NullInDepth nullIn = null;
  nullIn.helloThere();
  Object nullStr = null;
  NullInDepth nullOut = (NullInDepth) nullStr;
  System.out.println(nullIn);
 }
 
}
这里Hello from null?!会被打印出来,而后边一句会打印出null,我们知道println一般是调用对象的toString来进行打印,但是null明显不是对象,作为一个不确定引用它只是把自己的literal给打印了出来,因此我猜测null是预先存储在内存中的一个引用,它是有值的,可能根据不同的jvm有不同的实现,但是jvm中会一致地将这个值打印为null。
 
另外按照我的猜测,null应该是栈里边的一个引用,null type是可以转换为所有其他type的引用,所以我也猜测null type应该是所有其他引用类型的子类型。
静态方法(也许需要是public的)应该是由类名来调用,但是也可以使用 类名(null).静态方法名 的方式调用,具体细节没太弄懂。
 
Since Java and C# run on virtual machines, it does not matter what is used physically to represent null, and it is not necessarily the same across implementations.
What matters is the behaviour of null, as defined in the language specification (see Dan's and MRFerocius' answers for details). Basically, it is a special value that variables of reference type can hold, and which cannot be dereferenced.
BTW, as a reference point, the Java serialization spec use a single byte value 0x70 to represent a null reference.
"null" has the interesting property that "instanceof" used with null always returns false.
When putting a cast before a literal null, remember this is only a syntax to help the compiler choose between overloaded methods. The cast doesn't actually "do anything" to the null reference. Casting doesn't do anything anyway. If it survives in bytecode at all, it only performs a check. Static types only really matter to the compiler (blah blah reflection blah blah bytecode contains some static types blah blah).
 
再引用另外一篇文章,虽然根本上就错了,但还是有些内容的:
 
作为关键字true,false,null都分别代表不同的含义。
 
"
"位"是内存中作为存储数据的基本单位,而我们又通常说,一个字节是8位,也就是 1byte = 8bit。
 
因为内存中,"位"是使用0和1来表示的,所以作为关键字,true的值在内存中就表示1,false在内存中就是表示0。
 
但是这里不要和整数(int)中的0和1相比,他们占用的内存空间是不一样的。一个int型的变量,占用的内存空间是4个字节,也就是4 * 8 = 32位,与true和false占用的内存空间是不同的。
 
而作为关键字null,解释起来就更是麻烦了。
 
当一个对象被声明时(Object o;),这个对象会以一个整数的字节数,只在内存堆栈(stack)中开辟一个内存指针。例如,我们使用Object o = new Object();实例化一个对象,那么在内存中的运行则是:在内存堆栈(stack)中开辟一个4个字节的指针,然后在内存堆区(heap)开辟这个对象所要存储的数据并初始化,然后在将之前在stack中的内存指针中赋上在heap中开辟的空间的首地址。
 
而如果Object o;没有进行实例化,则不可能使用o的引用。这时为了方便使用,则出现了null关键字。null关键字的意义也就是一个用来初始化对象的空引用。

    本站是提供个人知识管理的网络存储空间,所有内容均由用户发布,不代表本站观点。请注意甄别内容中的联系方式、诱导购买等信息,谨防诈骗。如发现有害或侵权内容,请点击一键举报。
    转藏 分享 献花(0

    0条评论

    发表

    请遵守用户 评论公约

    类似文章 更多