Java static关键字

public class StaticTest <T> {

    private final T t;

    private static final Integer st = 1;

    private String n = "1";

    public static Integer getSt(){
        return st;
    }

    public static Integer getStByStaticFuc(){
        return st;
    }

    public T getT() {
        return t;
    }

    public StaticTest(T t) {
        this.t = t;
    }

    public static <T> void main(String[] args) {

        StaticTest dyhtest = new StaticTest("sunning");

        //1-static成员变量可以被static或非static方法访问
        show(StaticTest.getStByStaticFuc());
        show(StaticTest.getSt());
        //2-static成员变量只能通过类名访问不能通过类实例访问
        show(StaticTest.st);
        //3-static成员方法只可访问static成员变量
        //4-static成员变量只可通过类名访问,不可通过类实例访问
        //4-static成员方法可通过类名访问,也可通过类实例访问,但建议通过类名访问
        show(StaticTest.getStByStaticFuc());
        //5-非static成员方法,仅可通过类实例访问,不可通过类名访问。
        show(dyhtest.getT());
        //6-static成员变量和static成员方法,没有this方法。即,不可以通过this.age或this.setAge()来访问。
    }

    public static <T> void show(T t) {
        System.out.println(t + "+打印的值");
    }
}

基于上述代码总结如下:
1、static关键字的基本作用就是方便在没有创建对象的情况下来对方法和变量进行调用
2、静态变量在内存中只有一个副本,他是被所有类对象共享的,当且仅当在类被初次加载时执行初始化,而且只执行一次。
3、非静态变量是类对象所拥有的,在对象被创建时初始化,有多个副本,各个副本之间不受影响。。

一段面试中常考的代码

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 static
myclass static
person static
person Test
test constructor
person MyClass
myclass constructor

解析:java中各部分的执行顺序为静态代码块(静态代码块按照声明顺序执行)>构造代码块>构造函数>普通代码块
先加载Test类,初始化Test中的静态代码块,再执行static修饰的main方法中的new MyClass(),由于MyClass没有加载,因此需要加载MyClass类。加载该类时发现其继承自Test类,实际上Test类已经被加载了,因此只需要加载MyClass,执行其静态代码块。在加载完之后,就通过构造器来生成对象。而在生成对象的时候,必须先初始化父类的成员变量,因此会执行Test中的Person person = new Person(),而Person类还没有被加载过,因此会先加载Person类并执行Person类中的static块,接着执行Person类的构造器,在执行Test类的构造器。然后就来初始化自身了,因此会接着执行MyClass中的Person person = new Person(),最后执行MyClass的构造器。

增加难度,加入构造代码块

public class Test {
    Person person = new Person("Test");
    static{
        System.out.println("test static block");
    }

    {
        System.out.println("test constructor block");
    }

    public Test() {
        System.out.println("test constructor fuc");
    }

    public static void main(String[] args) {
        new MyClass();
    }
}

class Person{
    static{
        System.out.println("person static block");
    }

    {
        System.out.println("person constructor block");
    }

    public Person(String str) {
        System.out.println("person "+str);
    }
}


class MyClass extends Test {
    Person person = new Person("MyClass");
    static{
        System.out.println("MyClass static block");
    }

    {
        System.out.println("MyClass constructor block");
    }

    public MyClass() {
        System.out.println("myclass constructor fuc");
    }
}

输出为:
test static block
MyClass static block
person static block
person constructor block
person Test
test constructor block
test constructor fuc
person constructor block
person MyClass
MyClass constructor block
MyClass constructor fuc

你可能感兴趣的:(Java)