Java的Static使用介绍

来源:互联网 发布:tensorflow cuda 编辑:程序博客网 时间:2024/06/05 23:06

一、开篇

        首先用一个例子开始我们今天的介绍。

        定义一个TestStaticClass类如下:

public class TestStaticClass {private static int a;private int b = 0;public TestStaticClass() {a++;b++;}public static void testRun() {System.out.println("run TestStaticClass.testRun");}public String toString() {return "a = " + a + ", b = " + b;}}
定义MainClass类如下:

public class MainClass {/** * @param args */public static void main(String[] args) {// TODO Auto-generated method stubSystem.out.println(new TestStaticClass());System.out.println(new TestStaticClass());}}
运行的结果如下:

            a = 1, b = 1

            a = 2, b = 1

        为什么会这样呢?这就是Static的作用之一,如果使用static来修饰一个变量,那么该变量就属于该类所有,而不再属于该类的某一实例,被类的所有实例共享。因为Java在加载该类的时候为static变量在内存中分配了一个固定的内存空间来存储,只要TestStaticClass类存在,那么该变量a所代表的地址空间就不会消失。

        在上面的实例中,每一次新建一个TestStaticClass类,都会修改a所在的地址空间的内容,所以就会导致了a和b的值不一致的情况。

        除了在实例中用Static来修饰变量外,还可以用来修饰修饰函数和代码块。这些在本文中都会详细的介绍,但是在这之前,必须记得Static的特性:固定。这个不仅仅指固定的地址,还包括固定的大小。使用static修饰的变量等,在编译时就为这些变量分配了空间。

二、静态变量

       在java中,被static修饰的变量就叫作静态变量,或者叫类变量。

       为什么Java中要引入静态变量?到底静态变量有什么用?

        为了说明这些问题,下面来看一下静态变量和实例变量(没有被static修饰的变量)的区别。

        1)JVM只是在加载类的过程中就完成了静态变量的内存的分配,在内存中只有一份拷贝,并且地址是不可变的,所以可以直接使用类名访问,当然也可以使用对象来访问(不推荐);

        2)实例变量,JVM只有在一个类的实例化的时候才分配一次内存,它在内存中有多份拷贝,并且是相互独立的,所以只能通过对象来访问。

        根据静态变量和实例变量的区别,我们可以使用静态变量来实现一些功能,例如:

        1)当需要同时实例的实现个数时,例如在数据库连接类中,如果当前连接的个数为0时,就自动的释放掉;

        2)使用静态变量可以很方便的实现单例模式。

        单例模式的结构如下:


        很显然,如果将变量mInstance定义为静态变量,当其他对象需要使用该类时,只需要调用getInstance方法返回mInstance就可以了,这样子就可以保证类Singleton只有一个实例。

三、静态方法

        上面的例子中已经介绍了static修饰变量的情况。静态方法(使用static修饰的方法)也是我们常见的,例如,Java中的main函数。

public static void main(String[] args) {    ......}

        为什么main函数需要定义为静态方法呢?首先我们来看一下运行java程序的流程。

        在java中,函数main是应用程序的入口,JVM需要通过main找到将要执行的程序。在执行main函数时,JVM会检查该方法所在的类是否被加载,如果没有,就加载该类并且加载所有相关的其他类。

        相信大家都还没有忘记static的特性吧,没错,那就是固定。首先,在java中,方法不能脱离对象而存在,所以不管main是程序运行的第几个方法,它必须定义在一个类中。其次,由于在这之前还没有类被JVN加载进来,所以就不能通过“对象名.方法名()”的方式来运行。由此可以知道,必须将main方法声明为静态方法。

        进行到这里,大家应该明白静态方法的作用了。不过有一点需要注意:在静态方法中不能使用非静态的方法和变量。其实这一点和很容易理解,由于静态方法是类的方法,它不需要实例化类就可以使用,而非静态的方法和变量都是需要实例化后才能使用,这一点就发生了冲突。

四、静态代码块

        静态代码块是使用static修饰的代码块,一般使用JNI时就会碰到。

        例如java中的Object类:

public class Object {    private static native void registerNatives();    static {        registerNatives();    }        ......}

        那么我们就会有这么一个疑问,静态代码块在程序运行的顺序是怎样的呢?

        还是使用实例来说话吧。

public class StaticBlock {static {System.out.println("running StaticBlock static block!");}/** * @param args */public static void main(String[] args) {// TODO Auto-generated method stubSystem.out.println("running StaticBlock.main()");}}
        运行的结果如下:

             running StaticBlock static block!

             running StaticBlock.main()

五、总结

        1)使用static来修饰的变量等,不再属于某一个对象,而是属于一个类;

        2)静态方法和静态变量的引用可以使用"类名.方法"和"类名.变量";

        3)在静态方法中不能使用非静态的方法或成员变量,反之,则可以;

        4)使用static修饰的代码块的执行顺序在main函数之前。

原创粉丝点击