On whether Java should declare variables outside the loop

Catalog

Preface

"Don't declare variables in the loop". You often see similar comments. Is it necessary to do so?

First of all, there are several disadvantages in declaring variables outside the circulation:

  • Larger scope, risk of unintentional reference
  • Prevent variable naming conflicts
  • Poor readability

To sum up, if "declare variables in cardiopulmonary bypass" can't bring optimization in other aspects (such as performance), then I really can't think of any reason to do so.

Performance and memory

In terms of syntax readability, "declaring variables out of loop" does not have an advantage. If there are other possible advantages, all I can think of is performance improvement and memory optimization.

performance testing

In the following test code, 10 million instances are built in the loop. After testing, the author has completed them in 5ms, with almost no difference in performance.

public class VariableLoopTest {
	public static void main(String[] args) {
		//inside();
		//outside();
	}

	static void inside() {
		long t1 = System.currentTimeMillis();
		for (int i = 0; i < 10000000; i++) {
			Object o = new Object();
		}
		long t2 = System.currentTimeMillis();
		System.out.println(t2 - t1);
	}

	static void outside(){
		long t1 = System.currentTimeMillis();
		Object o = null;
		for (int i = 0; i < 10000000; i++) {
			o = new Object();
		}
		long t2 = System.currentTimeMillis();
		System.out.println(t2 - t1);
	}
}

Memory test

The following test code is used to build three 10MB instances, trigger GC manually, and check the memory recovery.

public class MemoryTest {
	private static final int _1MB = 1024 * 1024;

	//Single instance occupies 10MB of memory
	static class MyClass {
		byte[] bytes = new byte[_1MB * 10];
	}

	/**
	 * VM Args: -XX:+PrintGCDetails Output GC log
	 */
	public static void main(String[] args) throws InterruptedException {
		//inside();
		outside();
	}

	static void inside(){
		for (int i = 0; i < 3; i++) {
			MyClass myClass = new MyClass();
		}
		System.gc();
	}

	static void outside(){
		MyClass myClass = null;
		for (int i = 0; i < 3; i++) {
			myClass = new MyClass();
		}
		System.gc();
	}
}



As a result of the above test, as long as the variables declared in the loop are finished, the object can be recycled well.
When variables are declared outside the loop, the last object is still referenced, which affects GC recycling.

It can be seen that "declare variables out of loop" is not superior in performance and memory.

Compiler optimization

In fact, after the code written by the developer is compiled by javac, the compiler will optimize and adjust the code.
As long as the variable is not accessed by the code outside the loop, the compiler will automatically put the declaration of the variable into the loop.

The following test code:

public class VariableLoop {
	void inside(){
		for (int i = 0; i < 1000; i++) {
			Object o = new Object();
		}
	}
	void outside(){
		Object o;
		for (int i = 0; i < 1000; i++) {
			o = new Object();
		}
	}
}

After compiling with javac:

public class VariableLoop {
    public VariableLoop() {
    }
    void inside() {
        for(int i = 0; i < 1000; ++i) {
            new Object();
        }
    }
    void outside() {
        for(int i = 0; i < 1000; ++i) {
            new Object();
        }
    }
}

The bytecode is disassembled with javap-c, and the generated instructions are the same, as follows:

void inside();
    Code:
       0: iconst_0
       1: istore_1
       2: iload_1
       3: sipush        1000
       6: if_icmpge     23
       9: new           #2                  // class java/lang/Object
      12: dup
      13: invokespecial #1                  // Method java/lang/Object."<init>":()V
      16: astore_2
      17: iinc          1, 1
      20: goto          2
      23: return

  void outside();
    Code:
       0: iconst_0
       1: istore_2
       2: iload_2
       3: sipush        1000
       6: if_icmpge     23
       9: new           #2                  // class java/lang/Object
      12: dup
      13: invokespecial #1                  // Method java/lang/Object."<init>":()V
      16: astore_1
      17: iinc          2, 1
      20: goto          2
      23: return

summary

To sum up, in addition to expanding the scope and poor readability of variables, declaring variables out of loop has no improvement in performance and memory, but will affect the GC recovery of objects.
So, if you really only need to use variables in the loop, then feel free to declare them in the loop. There is no problem!

105 original articles published, praised 26, visited 90000+
Private letter follow

Tags: Java

Posted on Sun, 15 Mar 2020 00:59:13 -0400 by tobimichigan