java static关键字

来源:互联网 发布:牛仔衬衫女淘宝 编辑:程序博客网 时间:2024/05/01 13:09

1、static变量
static 变量也称作静态变量,静态变量和非静态变量的区别是:静态变量被所有的对象所共享,存在于内存中,在内存中只有一个副本,它当且仅当在类初次被加载时会被初始化。
而非静态变量是对象所拥有的,在创建对象时被初始化,存在多个副本,各个对象所拥有的副本互不影响。

static是不允许用来修饰局部变量的。即使是在静态方法里面。

2、static方法
static方法也称为静态方法,静态方法不依赖于任何对象就可以访问,因为不依赖于任何对象,所以静态方法不可以访问非静态成员变量和非静态成员方法,因为非静态成员变量和非静态成员方法是依赖于对象的。

示例:

public class month {    private static String str="staticString";    private String str1="String";    public static void method(){        System.out.println(str);        System.out.println(str1);        method1();    }    public void method1(){        System.out.println(str);        System.out.println(str1);        method();    }}

这里写图片描述

总结:因为静态成员和静态方法在类刚被加载时就被初始化了,所以只要调用类,静态方法和静态成员变量就已经存在。而非静态方法和非静态成员变量,必需在类被实例化以后才会有。

非静态方法可以访问静态成员变量和静态方法。
静态方法不能访问非静态成员变量和非静态方法。

3、静态代码块
static还可以用来形成静态代码块来优化程序,static代码块可以置于类的任何位置,static代码块会在类被初次加载的时候,按照static代码块的顺序执行,并且只被执行一次。

示例:
判断某人生日是不是在生育高峰期。

public class Person{    private Date birthDate;    public Person(Date birthDate){        this.birthDate=birthDate;    }    boolean isBornBoomer(){        Date startDate =new Date(46,1,1);        Date endDate = new Date(64,11,30);        return birthDate.compareTo(startDate)>=0 && birthDate.compareTo(endDate)<0;    }}

如果换做如下代码,代码的效率会高很多。

public class Person{    private Date birthDate;    private static  Date startDate,endDate;    static {        Date startDate =new Date(46,1,1);        Date endDate = new Date(64,11,30);    }    public Person(Date birthDate){        this.birthDate=birthDate;    }    boolean isBornBoomer(){        return birthDate.compareTo(startDate)>=0 && birthDate.compareTo(endDate)<0;    }}

其中startDate和endDate作为静态变量被定义,而他们初始化是作为静态代码块实现的,也是在类被加载时运行一次。其实在定义startDate和endDate时可以直接进行初始化,这样写只是为了理解。

4、static面试题

看一下代码的执行结果

public class Test extends Base{    static{       //静态代码块        System.out.println("test static");    }    public Test(){        //构造函数        System.out.println("test constructor");    }    public static void main(String[] args) {        new Test();    }}class Base{    static{        //静态代码块        System.out.println("base static");    }    public Base(){           //构造函数        System.out.println("base constructor");    }}

执行结果为

base statictest staticbase constructortest constructor

分析:
代码在执行时,先找到main函数,但是执行main函数前,必需先加载Test类,在加载Test类时,发现Test类继承了Base类,所以先去加载Base类,在加载Base类时,发现有static代码块,所以就在加载Base类时,执行static代码块,输出base static,加载完Base类后,转去加载Test类,加载Test类时,也执行了static代码块,输出test static,在这两个类都加载完后,开始执行main函数,构造Test类,构造Test类先调用父类的构造器,然后再调用自身的构造器,所以输出以上结果。

5、static面试题

看一下代码的输出结果:

public class Test {    Person person = new Person("Test");    static{        System.out.println("test static");    }    public Test() {        System.out.println("test constructor");    }    public static void main(String[] args) {        new MyClass();    }}class Person{    static{        System.out.println("person static");    }    public Person(String str) {        System.out.println("person "+str);    }}class MyClass extends Test {    Person person = new Person("MyClass");    static{        System.out.println("myclass static");    }    public MyClass() {        System.out.println("myclass constructor");    }}

结果:

test staticmyclass staticperson staticperson Testtest constructorperson MyClassmyclass constructor

分析:
首先程序会加载Test类,然后执行static代码块,输出test static,然后开始执行main函数, new MyClass(),然而MyClass类还没有被加载,开始加载MyClass类,MyClass继承了Test类,而Test类已经被加载,就不再执行加载,开始加载MyClass,并执行static代码块,输出myclass static,加载完成后,通过构造器生成对象,而生成对象的时候,必须先初始化父类的成员变量,而成员变量中Person类还没有被加载,于是加载Person,并执行static代码块,输出person static,加载完成后,开始实例化Person,调用Person的构造函数,输出person test,然后调用Test构造函数,输出test constructor,然后开始初始化MyClass的成员变量,调用Person构造函数,输出person myclass,最后调用自身的构造函数,输出myclass constructor。

0 0