void func(int n){
     int k=Math.sqrt(n);
     for(int i=0;i<k;i++){
     .....
     }-----------------------------  void func(int n){
     for(int i=0;i<Math.sqrt(n);i++){
     .....
     }上面两种代码,功能基本一样,哪个效率更高点呢?
类似的还有while循环。

解决方案 »

  1.   

    按照编译原理上的原理,循环不变运算应该外提,还以为java编译器会进行优化呢,测试了一下,没有优化。
    public class Test {    public static void main(String[] args) {
            for (int i = 0; i < get(); i++) {
                System.out.println("Hello world");
            }
            System.out.println("-----------");
            int k = get();
            for (int i = 0; i < k; i++) {
                System.out.println("test2");
            }
        }    public static int get() {
            return 5;
        }
    }看生成的class文件内容:Compiled from "Test.java"
    public class Test extends java.lang.Object{
    public Test();
      Code:
       0: aload_0
       1: invokespecial #1; //Method java/lang/Object."<init>":()V
       4: returnpublic static void main(java.lang.String[]);
      Code:
       0: iconst_0
       1: istore_1
       2: iload_1
       3: invokestatic #2; //Method get:()I
       6: if_icmpge 23
       9: getstatic #3; //Field java/lang/System.out:Ljava/io/PrintStream;
       12: ldc #4; //String Hello world
       14: invokevirtual #5; //Method java/io/PrintStream.println:(Ljava/lang/String;)V
       17: iinc 1, 1
       20: goto 2
       23: getstatic #3; //Field java/lang/System.out:Ljava/io/PrintStream;
       26: ldc #6; //String -----------
       28: invokevirtual #5; //Method java/io/PrintStream.println:(Ljava/lang/String;)V
       31: invokestatic #2; //Method get:()I
       34: istore_1
       35: iconst_0
       36: istore_2
       37: iload_2
       38: iload_1
       39: if_icmpge 56
       42: getstatic #3; //Field java/lang/System.out:Ljava/io/PrintStream;
       45: ldc #7; //String test2
       47: invokevirtual #5; //Method java/io/PrintStream.println:(Ljava/lang/String;)V
       50: iinc 2, 1
       53: goto 37
       56: returnpublic static int get();
      Code:
       0: iconst_5
       1: ireturn}看对应第一个循环最后的  20: goto 2,每次循环返回到标号2处,下面都要调用get()方法。
    也就是说编译器没有进行优化。
      

  2.   

    这根本不用假设,对于表达式变量根本就不能优化,不是编译器不去优化.
    因为表达式变量不能确定每次运算的结果是否相同,怎么可能为你优化呢?如果你写(long i = 0;i < System.currentTimeMillis();i++)
    优化明显违反你的本意,而编译时优化并不能确定哪人表达式的值是固定的.
    除非本身就是常量表达式.
      

  3.   

    ZangXT和axman都說清楚了,學習了
      

  4.   


    第一种效率高是很明显的第二种每次进入for循环时都要计算Math.sqrt(n)的值勤
      

  5.   

    我的建议是改成这样(第 08 行),我们应该局变量的作用范围尽可能地减小。01  public class Test {
    02 
    03      public static void main(String[] args) {
    04          for (int i = 0; i < get(); i++) {
    05              System.out.println("Hello world");
    06          }
    07          System.out.println("-----------");
    08          for (int i = 0, k = get(); i < k; i++) {
    09              System.out.println("test2");
    10          }
    11      }
    12
    13      public static int get() {
    14          return 5;
    15      }
    16  }
      

  6.   

    这个例子我认为很好啊,可以把 get() 看成是需要进行一系列运算才得出结果的。
      

  7.   

    第一种的方式效率高。
    不论是什么语言,不变的变量应该放在外面。
    因为,在FOR循环中,通过调用函数来得到不变的变量需要消耗资源。