[java] about static keyword

1, Decorated member variable

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);
    }
    /**Output
     * Name:zhangsan, Age:10
     * Name:lisi, Age:12
     */
}

We are very familiar with the above code. Each object constructed according to Person exists independently and saves its own independent member variables, which will not affect each other. Their schematic diagram in memory is as follows:

As can be seen from the above figure, the objects referenced by p1 and p2 variables are stored in different addresses of the heap area in memory, so they will not interfere with each other. But in fact, we have omitted some important information. I believe everyone will think that the member properties of objects are here and saved by each object. What about their methods?

In fact, no matter how many objects a class creates, their methods are the same:

From the above figure, we can see that the methods of two Person objects actually call the same method definition. This method is defined as an invariant area (divided by the jvm) in memory, which we temporarily call static storage. This storage area not only stores the definitions of methods, but also stores various definitions. When we generate objects through new, we will create objects according to the definitions of the classes defined here.

Multiple objects only correspond to the same method. Here is a convincing reason for us, that is, no matter how many objects, their methods are always the same. Although the final output will be different, the methods will always operate according to our expected results, that is, different objects call the same method, and the results will be different.

We know that the static keyword can modify member variables and methods to make them belong to the class rather than the object. For example, if we modify the age attribute of Person with static, what will be the result? Take the following example:

public class Person {
    String name;
    static int age;
    /* The rest of the code remains unchanged */
    /**Output
     * Name:zhangsan, Age:12
     * Name:lisi, Age:12
     */
}

We found that the result changed a little. When assigning a value to the age attribute of p2, it interfered with the age attribute of p1. Why? Let's take a look at their schematic in memory:

We found that after adding the static keyword to the age attribute, the Person object no longer has the age attribute. The age attribute will be uniformly managed by the Person class, that is, multiple Person objects will only correspond to one age attribute. If an object changes the age attribute, other objects will be affected.

We can see that the age and toString() methods at this time are managed by the class.

Although we see that static allows objects to share attributes, we rarely use it in practice and do not recommend it. This makes the property difficult to control because it can be changed anywhere. If we want to share attributes, we will generally adopt other methods:

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);
    }
    /**Output
     * Id:1, Name:zhangsan, Age:10
     * Id:2, Name:lisi, Age:12
     */
}

The above code plays the role of creating a unique id for the Person object and recording the total number. Count is modified by static and is a member attribute of the Person class. Each time a Person object is created, the attribute will increase by 1 and then be assigned to the id attribute of the object. In this way, the count attribute records the total number of Person objects created. Because count uses the private modification, So you can't change it from outside the class.

2, Modify member method

Another function of static is to modify member methods. Compared with modifying member attributes, modifying Member methods does not have much change in data storage, because we can see from the above that methods are originally stored in the class definition.

The most important function of static modifying Member method is to use class name. Method name to operate the method, avoiding the tedious and resource consumption of trying to new out the object first. We may often see its use in the help class:

public class PrintHelper {
    public static void print(Object o){
        System.out.println(o);
    }
    public static void main(String[] args) {
        PrintHelper.print("Hello world");
    }
}

The above is an example, but we can see its role, which makes the static modified method become a class method. When used, it can be used conveniently through "class name. Method name", which is equivalent to defining a global function (just import the package in which the class is located).

However, it also has limitations. In a static modified class, non static modified member variables and methods cannot be used, and static modified local variables cannot appear in any method. This is easy to understand because the static modified method belongs to a class. If you directly use the member variable of an object, it will be at a loss (I don't know which object attribute to use).

3, Static block

When explaining the third usage of static keyword, it is necessary to re sort out the initialization process of an object. Take the following code as an example:

package com.dotgua.study;
class Book{
    public Book(String msg) {
        System.out.println(msg);
    }
}
public class Person {
    Book book1 = new Book("book1 Member variable initialization");
    static Book book2 = new Book("static member book2 Member variable initialization");
    public Person(String msg) {
        System.out.println(msg);
    }
    Book book3 = new Book("book3 Member variable initialization");
    static Book book4 = new Book("static member book4 Member variable initialization");
    public static void main(String[] args) {
        Person p1 = new Person("p1 initialization");
    }
    /**Output
     * static Member book2 member variable initialization
     * static Member book4 member variable initialization
     * book1 Member variable initialization
     * book3 Member variable initialization
     * p1 initialization
     */
}

In the above example, four Book member variables are combined in the person class, two are ordinary members and two are static modified class members. We can see that when we new a Person object, the static modified member variable is initialized first, followed by an ordinary member, and finally calls the Person class construction method to complete the initialization.

In other words, when creating an object, members decorated with static will be initialized first, and we can also see that if there are multiple members decorated with static, they will be initialized according to their sequence.

In fact, members decorated with static can be initialized earlier. See the following example:

class Book{
    public Book(String msg) {
        System.out.println(msg);
    }
}
public class Person {
    Book book1 = new Book("book1 Member variable initialization");
    static Book book2 = new Book("static member book2 Member variable initialization");
    public Person(String msg) {
        System.out.println(msg);
    }
    Book book3 = new Book("book3 Member variable initialization");
    static Book book4 = new Book("static member book4 Member variable initialization");
    public static void funStatic() {
        System.out.println("static Embellished funStatic method");
    }
    public static void main(String[] args) {
        Person.funStatic();
        System.out.println("****************");
        Person p1 = new Person("p1 initialization");
    }
    /**Output
     * static Member book2 member variable initialization
     * static Member book4 member variable initialization
     * static Modified funStatic method
     * ***************
     * book1 Member variable initialization
     * book3 Member variable initialization
     * p1 initialization
     */
}

In the above example, we can find two interesting places,
The first is that when we call a class method through a class without creating an object, although the method does not use any class members, the class members are initialized before the method call, which shows that when we use a class for the first time, the class member initialization will be triggered.

The second is that when we use class methods to initialize class members and then new the objects of the class, the static modified class members are not initialized again, which shows that the static modified class members only need to be initialized once during the running process of the program and will not be initialized many times.

After reviewing the initialization of objects, the third function of static is very simple, that is, when we initialize the members decorated with static, we can put them in a block statement starting with static and wrapped in curly braces:

class Book{
    public Book(String msg) {
        System.out.println(msg);
    }
}
public class Person {

    Book book1 = new Book("book1 Member variable initialization");
    static Book book2;
    static {
        book2 = new Book("static member book2 Member variable initialization");
        book4 = new Book("static member book4 Member variable initialization");
    }
    public Person(String msg) {
        System.out.println(msg);
    }
    Book book3 = new Book("book3 Member variable initialization");
    static Book book4;
    
    public static void funStatic() {
        System.out.println("static Embellished funStatic method");
    }
    public static void main(String[] args) {
        Person.funStatic();
        System.out.println("****************");
        Person p1 = new Person("p1 initialization");
    }
    /**Output
     * static Member book2 member variable initialization
     * static Member book4 member variable initialization
     * static Modified funStatic method
     * ***************
     * book1 Member variable initialization
     * book3 Member variable initialization
     * p1 initialization
     */
}

We have slightly modified the previous example. We can see that there is no difference in the results

4, Static guide package

Compared with the above three uses, the fourth use may be understood by fewer people, but in fact, it is very simple and more convenient to call class methods.
Take the example of "PrintHelper" above as an example. Make a slight change to make it convenient for us to use the static guide package:

/* PrintHelper.java file */package com.dotgua.study;
public class PrintHelper {
    public static void print(Object o){
        System.out.println(o);
    }
}
/* App.java file */

import static com.dotgua.study.PrintHelper.*;
public class App 
{
    public static void main( String[] args )
    {
        print("Hello World!");
    }
    /**Output
     * Hello World!
     */
}

The above code comes from two java files. The PrintHelper is very simple and contains a static method for printing.

In the App.java file, we first import the PrintHelper class. Here, when importing, we use the static keyword, and add ". *" at the end of the imported class. Its function is to directly import all class methods in the PrintHelper class.

Unlike non static import, static import package does not need to use the method of "class name. Method name" to call class methods without conflicting with the method name of the current class. You can directly use "method name" to call class methods, just like the class's own methods.

summary

  1. It is used to modify the member variable and change it into a member of the class, so as to realize the sharing of all objects for the member
  2. It is used to modify member methods and turn them into class methods, which can be called directly by "class name. Method name". It is often used in tool classes;
  3. Static block usage, which initializes multiple class members together, makes the program more regular. It is very important to understand the initialization process of objects;
  4. Static guided package usage, which imports class methods directly into the current class, so that class methods can be called directly using "method name", which is more convenient.

Tags: Java Back-end

Posted on Sun, 21 Nov 2021 21:19:52 -0500 by Kryptix