java constant folding

Posted by cheald on Thu, 01 Aug 2019 04:01:52 +0200

Original Link: https://www.cnblogs.com/zhenghengbin/p/9683990.html

Constant Folding in java

Why did I write a blog post because I read an analysis of the final keyword yesterday.But there was a problem that was never solved, so I asked the God of knowledge that was previously added to my qq.The first message he sent me back was Constant Fold.As a cinder ape, I immediately queried the concept.This is the first time you have known this concept.God told me a lot.Let me finally understand the concept of constant folding

Instance Resolution

Yesterday, the code that confused me was the following

    public static void main(String[] args) {

        String a = "hello2";
        final String b = "hello";
        String d = "hello";
        String c = b + 2;
        String e = d + 2;
        System.out.println((a == c));
        System.out.println((a == e));

    }

The result of this execution is

true
false

I just don't understand why I was the first to return to true?

With that in mind, let's first understand the concept of constant folding.To better understand the code above

constant folding

The concept of constant folding

  • Constant folding is a compiler optimization technique.
  • Constant collapse mainly means that the process of adding, subtracting, multiplying and dividing constants during compilation is collapsed

For String s1 = "1" + "2";
The compiler will optimize it to String s1 = "12";
"1" and "2" are not visible in the generated byte code at all.

We validate through idea

1. Source File

    public static void main(String[] args) {
        String s1 = "1"+"2";
    }

2. After running, idea has an out folder and finds the class file of the above file

    public static void main(String[] args) {
        String s1 = "12";
    }

Indeed, as mentioned above, the compiler will optimize for you

Conditions for Constant Folding to occur

  • Constant collapse requires an operation between compile-time constants.
  • Compile-time constants are constants whose values can be determined at compile time.
    • First: Literal quantities are compile-time constants.(Number literal, string literal, etc.)
    • Second, simple operations on compile-time constants result in compile-time constants, such as 1+2,'a'+'b'.
    • Finally, the basic types and string variables of final s assigned to compiler constants are also compile-time constants.

Raise a chestnut

1.First chestnut

    public static void main(String[] args) {
        String s1="a"+"bc";
        String s2="ab"+"c";
        System.out.println(s1 == s2);
    }

Trust everyone knows, output is true
And only one "abc" string object is created and is in the string constant pool.

2. Second chestnut

    public static void main(String[] args) {
        String a = "a";
        String bc = "bc";
        String s1 = "a" + "bc";
        String s2 = a + bc;
        System.out.println(s1 == s2);
    }

What about this result?false

s1 is the literal addition of strings, but s2 is the addition of two variables that are not final, so constant folding will not occur.

Instead, it overrides the String class's unique + operator to something like this (jdk1.8)

String s2 = new StringBuilder(a).append(b).toString(); 

Here toString() generates a new String variable, which obviously returns false when compared with the==operator.

3. Third chestnut

    public static void main(String[] args) {
        final String a = "a";
        final String bc = "bc";
        String s1 = "a" + "bc";
        String s2 = a + bc;
        System.out.println(s1 == s2);
    }

The result here is true

Because the basic type and string variables of final assigned by the compiler constant are also compile-time constants

4. Fourth chestnut

    public static void main(String[] args) {
        String x ="a";
        final String a = x;
        final String bc = "bc";
        String s1 = "a" + "bc";
        String s2 = a + bc;
        System.out.println(s1 == s2);
    }

The result here is false

Note here that final variables are neither initialized by compile-time constants nor compiler constants

A here is not a compiler constant

5. Fifth chestnut

    public static void main(String[] args) {
        String x ="a";
        final String a = x;
        final String bc = "bc";
        String s1 = "a" + "bc";
        String s2 = a + bc;
        System.out.println(s1 == s2.intern());
    }

The result here is true

In fact, if you want to understand the meaning of the intern method, you will understand it.

// A string pool, initially empty, is privately maintained by class strings.
1,A pool of strings, initially empty, is maintained privately by the class String. 

// If the string already exists in the constant pool, return its reference directly to the constant pool. If not, save its reference to the string constant pool and return it directly.
2,When the intern method is invoked, if the pool already contains a string equal to this String object as determined by the equals(Object) method, then the string from the pool is returned. Otherwise, this String object is added to the pool and a reference to this String object is returned. 

3,It follows that for any two strings s and t, s.intern() == t.intern() is true if and only if s.equals(t) is true.

summary

Now I'm done. Did you know why true printed above?
So.As long as you keep in mind that constant folding mainly means that the compilation-time operations of adding, subtracting, multiplying and dividing constants are collapsed

Follow-up Supplement

It starts with

Instead, overload the String class's unique + operator to something like this

String s2 = new StringBuffer(a).append(b).toString(); 

To correct this, I now use jdk1.8 to decompile StringBuilder instead of StringBuffer.This needs to be corrected.I also checked.StringBuilder was only available after jdk1.5.

Topics: Programming Java