How to implement static in Java in kotlin

Time:2020-10-30

Static modifier is a very common thing in Java, and its usage is also very many. However, there is no such thing in kotlin! How to replace it? This paper summarizes several common uses of static in Java to replace kotlin.

Summary of Static usage in Java

There are many usages of static in Java, and the most commonly used ones are as follows:

  • Static variables and methods
  • initiate static
  • Static inner class

Let’s take a look at how these scenarios are implemented in kotlin.

Scenario 1: static variables and methods

Static variables and methods may be the places where we usually use static most. Let’s take a look at how to do it in Java.

Introduction to Java static variables and methods:

First, the definition of static variables and methods


public class StaticTest {
  public static int STATIC_VAR = 0;

  public static void staticMethod(String str){
    System.out.println(str);
  }
}

Then there is the use of static variables and methods


StaticTest.STATIC_VAR = 10;
StaticTest.staticMethod("hello");

We are very familiar with the implementation of Java. Let’s focus on how kotlin is implemented.

Scheme of kotlin replacing static variables and methods

Kotlin replaces static variables and methods in Java by introducing the concept of “associated object”.

The term “companion object” sounds odd, but it’s very simple: use company to mark an object in the content of a class. All variables and methods that need to be “staticized” are placed in this object.

Here is the code that defines the associated object:

class StaticTest {
  Company object {// the name of the associated object can be specified, but it is generally omitted.
    var STATIC_VAR = 0

    fun staticMethod(str: String?) {
      println(str)
    }
  }
}

Next, let’s see how to use the associated object. The associated object can only be accessed through the class name, and the method is similar to that of Java


StaticTest.STATIC_VAR = 100
StaticTest.staticMethod("hello")

What problems does kotlin’s companion object solve?

You may wonder why kotlin is trying to solve this problem in such a strange way?

My understanding is for two reasons

First of all, kotlin is the object of design! Accompanying objects are also objects! The static of Java obviously has nothing to do with objects.

Second, the associated object solves a common anti pattern of Java static variables and methods: static methods and variables can be accessed through object references.

Taking the above example, Java static variables and methods can be accessed through class reference and object reference

//Access through class reference
StaticTest.STATIC_VAR = 10; 
StaticTest.staticMethod("hello");

//Access through object reference
StaticTest obj = new StaticTest();
obj.STATIC_VAR = 10;
obj.staticMethod("hello");

It is obviously inappropriate to access static variables and methods through object reference. But in Java, there is no way to avoid this problem from the syntax level.

However, kotlin’s associated objects can only be accessed by class reference, which solves this problem from the syntax level

//Using class reference access
StaticTest.STATIC_VAR = 100
StaticTest.staticMethod("hello")
  
//Cannot use object reference access
val obj = StaticTest()
obj.STATIC_ Var = 100 // compilation error
obj.staticMethod ("hello") // compilation error

In short, every new language feature in kotlin is designed to fill a hole in Java.

Scenario 2: static initialization

Static initialization in Java can initialize some static variables during class loading, such as:


public class StaticTest {
  public static int STATIC_VAR = 0;
  
  static {
    STATIC_VAR = 100;
    System.out.println("in static init");
  }
  
  public static void main(String[] args) {
    System.out.println(StaticTest.STATIC_VAR);
  }
}

The above code execution results are as follows:

in static init
100

In kotlin, because Java static variables and methods are implemented in the associated object, and the associated object is also a common object, the init method of the associated object can be used to initialize the variable. The code is as follows:

class StaticTest {
  Company object {// the name of the associated object can be specified, but it is generally omitted.
    var STATIC_VAR = 0

    init {
      STATIC_VAR = 100
      println("in companion object init")
    }
  }
}

Execution code:


println(StaticTest.STATIC_VAR)

The results were as follows:

in companion object init
100

As you can see, the implementation of kotlin is more consistent than that of Java. Since everyone is an object, it is initialized through init. In Java, non static variables are initialized by constructors, while static variables are initialized by static code blocks, which are quite inconsistent.

Scenario 3: static inner class

There are two kinds of inner classes in Java, ordinary inner classes and static inner classes. The difference between the two is that the former can access variables of external classes, while the latter cannot. At the same time, the ordinary inner class will hold a reference of the outer class, while the static inner class will not.

public class StaticTest {
  
  private int out = 0;
  
  class InnerClass{
    public void InnerClassMethod(){
      Out = 100; // variables of external classes can be accessed
    }
  }

  static class StaticInnerClass{
    public void StaticInnerClassMethod(){
      Out = 100; // compilation error, unable to access variables of external classes
    }
  }
}

There are two kinds of inner classes in kotlin: inner classes and nested classes. Grammatically, the difference between two values is that the former has an inner modifier.

The following is a comparison with Java:

  • Kotlin’s inner class (using the inner modifier) is equivalent to the ordinary Java inner class, which can access external variables and hold references to external objects.
  • Kotlin’s nested classes (without inner modifier) are equivalent to Java’s static inner classes, and cannot access external variables

Examples of kotlin nested classes:

class StaticTest {
  var out = 0

  inner class InnerClass{
    fun InnerClassMethod(){
      Out = 100 // inner class can access external variables
    }
  }
}

Example of kotlin inner class:

class StaticTest {
  var out = 0

  class InnerClass{
    fun InnerClassMethod(){
      Out = 100 // compilation error, nested class cannot access external variables
    }
  }
}

By comparison, it should be easy to understand the difference between inner classes and nested classes in kotlin.

Summary:

The knowledge points of this paper are summarized as follows:

  • Java static variables and methods, in kotlin using the accompanying object replacement
  • Java static initialization, using the accompanying object init in kotlin instead
  • Java static inner class, using nested classes in kotlin instead

The above is the whole content of this article, I hope to help you in your study, and I hope you can support developeppaer more.