java基础整理:static关键字 静态代码块什么时候执行

1.介绍

static可以修饰变量、方法、代码块和类(内部类)

(1)修改变量:则这个属性是被这个类所有,并不是被对象所有,也就是说该类创建的所有对象共有同一个属性,可以通过类名.属性名,直接调用,不用先new一个对象。

public class Person {
    String name;
    int age;
    
    public String toString() {
        return "Name:" + name + ", Age:" + age;
    }
    
    public static void main(String[] args) {
        Person p1 = new Person();
        p1.name = "zhangsan";
        p1.age = 10;

        Person p2 = new Person();
        p2.name = "lisi";
        p2.age = 12;

        System.out.println(p1);
        System.out.println(p2);
    }
    /**输出结果
     * Name:zhangsan, Age:10
     * Name:lisi, Age:12
     *
}

两个Person对象中的属性是互不影响的,两个Person对象的方法实际上只是指向了同一个方法定义。这个方法定义是位于内存中的一块不变区域(由jvm划分),我们暂称它为静态存储区。这一块存储区不仅存放了方法的定义,实际上从更大的角度而言,它存放的是各种类的定义,当我们通过new来生成对象时,会根据这里定义的类的定义去创建对象。多个对象仅会对应同一个方法,这里有一个让我们充分信服的理由,那就是不管多少的对象,他们的方法总是相同的,尽管最后的输出会有所不同,但是方法总是会按照我们预想的结果去操作,即不同的对象去调用同一个方法,结果会不尽相同。

如果将Person类中的name改为static修饰

public class Person {
    static String name;
    int age;
    
    /* 其余代码不变... */

    /**输出
     * Name:lisi, Age:10
     * Name:lisi, Age:12
     *///~
}

结果我们发现p2对象的name属性被影响了,因为name属性已不在是对象所有而是类所有,一个对象如果对name做了改变,其他对象也收到了影响。

虽然我们看到static可以让对象共享属性,但是可能造成线程不安全,有并发的问题(用volatile关键字)。因为这样会让该属性变得难以控制,因为它在任何地方都有可能被改变。

public class Person {
    private static int count = 0;
    int id;
    String name;
    int age;
    
    public Person() {
        id = ++count;
    }
    
    public String toString() {
        return "Id:" + id + ", Name:" + name + ", Age:" + age;
    }
    
    public static void main(String[] args) {
        Person p1 = new Person();
        p1.name = "zhangsan";
        p1.age = 10;
        Person p2 = new Person();
        p2.name = "lisi";
        p2.age = 12;
        System.out.println(p1);
        System.out.println(p2);
    }
    /**输出
     * Id:1, Name:zhangsan, Age:10
     * Id:2, Name:lisi, Age:12
     *///~
}

Person的对象创建一个唯一id以及记录总数的作用,其中count由static修饰,是Person类的成员属性,每次创建一个Person对象,就会使该属性自加1然后赋给对象的id属性,这样,count属性记录了创建Person对象的总数,由于count使用了private修饰,所以从类外面无法随意改变。

(2)修饰方法:修饰成员方法对于数据的存储上面并没有多大的变化,因为我们从上面可以看出,方法本来就是存放在类的定义当中的。static修饰成员方法最大的作用,就是可以使用"类名.方法名"的方式操作方法,避免了先要new出对象的繁琐和资源消耗。工具类一般都是静态方法。

(3)修饰类:只能是内部类,属于整个外部类,而不是属于外部类的每个对象。不能访问外部类的非静态成员(变量或者方法),可以访问外部类的静态成员。

(4)静态代码块:当类被第一次使用时(可能是调用static属性(非final)和方法,或者创建其对象)执行静态代码块,且只被执行一次,主要作用是实现static属性的初始化。

2,静态代码块什么时候执行

误区:在jvm加载类的时候执行的

一个类加载的过程包括了加载、验证、准备、解析、初始化五个阶段,当类被第一次使用时(可能是调用static属性(非final)和方法,或者创建其对象)会初始化,

你可能感兴趣的:(java)