Java基础之static

static

        整理一下有关java关键字 static的用法。

        先来看一下《java编程思想》中有关static的说明:



        我们从以下几个角度来分析一下static:

1. static的作用是什么?

想一下我们一般调用其他类中的变量和方法是怎么操作的?是不是都要先new一个对象实例出来,接着才能操作对象中的变量和方法,static的目的正是为了不创建对象的情况下,也能使用变量和方法。

2. static可以用来修饰哪些东西?

(1) 修饰类的成员变量,常和final用来一起定义静态常量。

(2)修饰类的成员方法,静态方法不依赖于对象,所以直接通过类就可以进行访问。

扫描二维码关注公众号,回复: 1706286 查看本文章

(3)修饰代码块,用来优化程序性能。

3. 调用限制。

在静态方法内部不能访问非静态方法和非静态变量。但是非静态方法内部没有这个限制。

4. 用静态工厂代替公有构造器的优缺点。

除了抽象类和接口类意外,每个类都会有自己的和类同名的构造函数,我们的实例化new的过程,其实也就是调用了类的构造函数的过程。用静态工厂的方法完全可以代替公有构造器,相比较有以下三个优点(具体解释可以参考工厂模式博客):

(1)具名

(2)环保

(3)多子

举个例子看一下:

java基本数据类型中的布尔值,内部就有类似的实现,看下内部的源码:

Boolean的构造函数:       

public Boolean(boolean value) {
    this.value = value;
}

Boolean中的静态方法:

public static Boolean valueOf(boolean b) {
    return (b ? TRUE : FALSE);
}

测试类:

package com.ljw.StaticTest;

/**
 * Created by liujiawei on 2018/6/22.
 */
public class TestStatic {
    public static void main(String[] args) {
        Boolean b = new Boolean("true");
        Boolean.valueOf("true");
    }
}

可以看到两种方式最终都实现了一样的目的,获得了一个布尔类型的变量。通过静态方法的valueOf()声明的变量是不是更加直观些呢?

5. static代码块,构造函数以及成员变量的初始化顺序。
在一个类的加载过程中,不同部分的加载顺序不同的,通过代码实例,一起来看下这几个的加载顺序;
父类:

package com.ljw.StaticTest;

/**
 * Created by liujiawei on 2018/6/22.
 */
public class Father {
    A a = new A("FATHER");
    static {
        System.out.println("父类静态代码块");
    }

    public Father(){
        System.out.println("父类构造函数");
    }
}

        子类:

package com.ljw.StaticTest;

/**
 * Created by liujiawei on 2018/6/22.
 */
public class Son extends Father {
    public static String sonName = "son";
    A a =  new A("SON");
    static {
        System.out.println("子类静态代码块");
    }

    public Son(){
        System.out.println("子类构造函数");

    }
}

    第三方:

package com.ljw.StaticTest;

/**
 * Created by liujiawei on 2018/6/22.
 */
public class A {
    static {
        System.out.println("A的静态代码块");
    }

    public A(String str){
        System.out.println("A的构造函数" + "===" + str);
    }
}

    测试类:

package com.ljw.StaticTest;

/**
 * Created by liujiawei on 2018/6/22.
 */
public class TestStatic {
    public static void main(String[] args) {
        new Son();
    }
}

运行结果:


        结果和你想的是一样的么?不是的也没有关系,我们一起来分析下这个加载的过程。


首先,main是主函数的入口,加载Son类,发现Son是继承的Father类,转而加载Father类,发现Father类中静态代码块,优先加载父类的静态代码块,首先输出“父类静态代码块”,加载完父类的静态代码块以后,加载子类的静态代码块,输出“子类静态代码块”,接着继续加载父类中的非静态内容,加载A类,A类中的静态代码块被优先执行,输出“A的静态代码块”,接着A类执行的构造函数,输出“A的构造函数===FATHER”,父类的静态内容加载完毕,加载构造方法,输出“父类构造函数”,父类加载完毕,加载子类中的非静态内容,因为静态代码块中的内容只会被加载一次,保存在内存中,所以直接执行A类的构造函数,输出“A的构造函数===SON”,最后加在子类的构造函数,输出“子类构造函数”。
以上就是整个的分析过程,总结一下就是:
(1)静态内容》非静态内容》构造方法,
(2)父类的静态代码》子类静态代码》父类非静态内容》父类构造方法》子类非静态内容》子类构造方法。


理解不到位之处,还请指出一起学习。

参考博客: https://www.cnblogs.com/starhu/p/5150241.html


猜你喜欢

转载自blog.csdn.net/qq_23585245/article/details/80773144