static Keyword Explanation

Keywords: Java Programming jvm

Reprint address: http://www.cnblogs.com/heimianshusheng/p/5828844.html

Speaking of the static keyword, I believe that you will never be strange, but, want to fully explain, fierce thinking, find that they do not seem to understand... For example, when I was asked by a classmate yesterday... Of course, not everyone is as poor as I am, but there should be a lot of people with weak foundations like this, because they are commonly used, so everyone can use them, but when it comes to fine points, it is enough. This blog is collated from my original study notes and some blogs I read, for the reference of students whose basic knowledge is not very reliable.

1. Problems to be solved by static keyword

Here is an excerpt from the original paragraph about the static keyword in Java Programming Thought (4th Edition): (P29) Generally speaking, when creating a class, it describes the appearance and behavior of the object of that class. Unless you create that object with new, you don't actually get any objects. When new is executed to create objects, the data storage space is allocated and its methods are called by the outside world. There are two situations that cannot be solved by the above methods. In one case, you just want to allocate a single storage space for a particular domain, without considering how many objects you want to create, or even without creating any objects at all. Another scenario is to hope that a method is not associated with any object that contains its class. That is, a method can be invoked even if no object is created. Simply put, the main purpose of static is to create domain variables and methods independent of specific objects.

2. Loading timing of variables or methods or classes modified by static

Add the static modifier while loading the class. (Note: At this point, there is no specific object, and this process is only done once)

3. Look at the effects of static variables, static methods, and static classes through code examples.

3.1 Static Variables

public class StaticTest{

    public static int count =0;

    @SuppressWarnings("static-access")
    public static void main(String[] args) {
        // TODO Auto-generated method stub
        StaticTest test1 = new StaticTest();
        System.out.println(test1.count);
        StaticTest test2 = new StaticTest();
        test2.count++;
        System.out.println(test1.count+" "+test2.count+" "+StaticTest.count);
    }

}

Output results:

0
1    1    1

It can be seen that the static variable is not owned by a specific object of the class, but is common to all objects of the class. Static variables can be called either by the object or directly by the class.

In addition, static variables can not refer to non-static methods, because, as mentioned in the previous description of static loading timing, when loading static, non-static variables, methods and so on do not exist, of course, can not be cited. However, non-static methods or classes can normally refer to static variables or methods. Because non-static always appears after static state.

3.2 Static Method

Static methods, like static variables, belong to the class. They are executed at the same time as the class is loaded. They do not belong to a specific object, and all objects can be invoked. For static methods, the following points should be noted:

  • They can only call other static methods.
  • They can only access static data.
  • They cannot refer to this or super in any way.
class Simple {
    static void go() {
       System.out.println("Welcome");
    }
}

public class Cal {
    public static void main(String[] args) {
       Simple.go();
    }
}

Static methods are generally used in tool classes and can be used directly by calling tool methods with class names.

3.3 Static Classes

Generally speaking, a common class is not allowed to be declared as static, but it can be declared as static in the internal class. At this time, the external class can call the internal class directly, because the internal class of static is loaded at the same time as the external class, so that is to say, the static internal class can be called directly without instantiating the external class. Look at examples:

public class BaseStatic {
  static {
        System.out.println("Load base static");
    }

    public BaseStatic(){
        System.out.println("BaseStatic constructor");
    }

    static class BaseInnerClass{
        static{
            System.out.println("Base inner class static");
        }

        public BaseInnerClass(){
            System.out.println("BaseInnerClass constructor");
        }
    }

}


public class StaticLoadOrderTest{

    public static void main(String[] args) {
        // TODO Auto-generated method stub
        new BaseStatic.BaseInnerClass();
    }

}

Before looking at the answer, think about the output.

First, before entering the main method of StaticLoadOrderTest, load the StaticLoadOrderTest class, and then execute the new BaseStatic.BaseInnerClass(); note that because BaseInnerClass is static, there is no need to load external classes and instantiate external classes, so you can load BaseInnerClass directly. And it is instantiated. So output:

Base inner class static
 BaseInnerClass constructor

Here's a pit: When you instantiate a static inner class directly with the name of an external class class, if the external class is not loaded (actually not loaded), then what is the existence of BaseStatic in the statement:BaseStatic.BaseInnerClass??? Is it just a simple name association with static inner classes? If so, why design static internal classes? I don't think java designers are going to make this mistake, are they? Maybe it's because I'm not familiar with JVM, and I don't know much about the bottom. If the passing God can help solve it, I'm grateful!!!

3.4 Examples of Static Loading Sequence

What is the output of the following code?

public class BaseStatic {
    static {
        System.out.println("Load base static");
    }

    public BaseStatic(){
        System.out.println("BaseStatic constructor");
    }

    static class BaseInnerClass{
        static{
            System.out.println("Base inner class static");
        }

        public BaseInnerClass(){
            System.out.println("BaseInnerClass constructor");
        }
    }

}

public class StaticLoadOrderTest {

    static {
        System.out.println("Load test");
    }

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

    public static void main(String[] args) {
        // TODO Auto-generated method stub
        new BaseStatic();
        new StaticLoadOrderTest();
        new BaseStatic.BaseInnerClass();
    }

}

As above, analyze the process: before entering the main method, you need to load the StaticLoadOrderTest class. At this time, you find that there is a static code block. First, you load the static code block, and then enter the main method, new BaseStatic(), at this time you need to load the BaseStatic class, at the same time, you need to load the static code block, and then call the constructor. Note: BaseInnerClass is not loaded here, because it is an internal class that will only be loaded when it is really used. Do smart readers think of another way to implement the singleton design pattern when they see this? Study for yourself. Back in the main method, it's time to execute the new StaticLoadOrderTest(), because the StaticLoadOrderTest class has been loaded once before, and the class has only been loaded once, so it's constructed directly here; then the last sentence, new BaseStatic.BaseInnerClass(), is the same as the previous example, and I won't go into details here. So the output is:

Load test
Load base static
BaseStatic constructor
Test constructor
Base inner class static
BaseInnerClass constructor

Consider again, if I change the example above to the following, what will the output be?

public class BaseStatic {
    static {
        System.out.println("Load base static");
    }

    public BaseStatic(){
        System.out.println("BaseStatic constructor");
    }

    static class BaseInnerClass{
        static{
            System.out.println("Base inner class static");
        }

        public BaseInnerClass(){
            System.out.println("BaseInnerClass constructor");
        }
    }

}



public class StaticLoadOrderTest extends BaseStatic{

    static {
        System.out.println("Load test");
    }

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

    public static void main(String[] args) {
        // TODO Auto-generated method stub
        new BaseStatic.BaseInnerClass();new StaticLoadOrderTest(); 
        new BaseStatic();
    }

}

This is some knowledge about the static keyword in java.

Posted by NeoSsjin on Thu, 27 Jun 2019 14:22:14 -0700