LINUX.ORG.RU

for for-each в Java


0

0

вот тут: http://www.ibm.com/developerworks/ru/library/j-jtp02277/index.html 
написано "Цикл for-each  : При итерации по массиву компилятор генерирует
индукционную переменную и стандартный код для итерации по массиву."

Но если сделать простые тесты:

class For {
    public static void main(String[] args) {
        for(int i = 0; i < args.length; i++) {
            System.out.println(args[i] + " ");
        }
    }
}

class Foreach {
    public static void main(String[] args) {
        for(String s: args) {
            System.out.println(s + " ");
        }
    }
}

видно что class файлы отличаются. Я не силен в чтении байт-кода. 
Может кто-нибудь прояснит ситуацию? Будет ли во втором случае 
исходная строка копироваться во временную переменную s?

Вариант с For:

  Code:
   0:	iconst_0
   1:	istore_1
   2:	iload_1
   3:	aload_0
   4:	arraylength
   5:	if_icmpge	41
   8:	getstatic	#2; //Field java/lang/System.out:Ljava/io/PrintStream;
   11:	new	#3; //class java/lang/StringBuilder
   14:	dup
   15:	invokespecial	#4; //Method java/lang/StringBuilder."<init>":()V
   18:	aload_0
   19:	iload_1
   20:	aaload
   21:	invokevirtual	#5; //Method java/lang/StringBuilder.append:(Ljava/lang/String;)Ljava/lang/StringBuilder;
   24:	ldc	#6; //String  
   26:	invokevirtual	#5; //Method java/lang/StringBuilder.append:(Ljava/lang/String;)Ljava/lang/StringBuilder;
   29:	invokevirtual	#7; //Method java/lang/StringBuilder.toString:()Ljava/lang/String;
   32:	invokevirtual	#8; //Method java/io/PrintStream.println:(Ljava/lang/String;)V
   35:	iinc	1, 1
   38:	goto	2
   41:	return

С Foreach:

 Code:
   0:	aload_0
   1:	astore_1
   2:	aload_1
   3:	arraylength
   4:	istore_2
   5:	iconst_0
   6:	istore_3
   7:	iload_3
   8:	iload_2
   9:	if_icmpge	49
   12:	aload_1
   13:	iload_3
   14:	aaload
   15:	astore	4
   17:	getstatic	#2; //Field java/lang/System.out:Ljava/io/PrintStream;
   20:	new	#3; //class java/lang/StringBuilder
   23:	dup
   24:	invokespecial	#4; //Method java/lang/StringBuilder."<init>":()V
   27:	aload	4
   29:	invokevirtual	#5; //Method java/lang/StringBuilder.append:(Ljava/lang/String;)Ljava/lang/StringBuilder;
   32:	ldc	#6; //String  
   34:	invokevirtual	#5; //Method java/lang/StringBuilder.append:(Ljava/lang/String;)Ljava/lang/StringBuilder;
   37:	invokevirtual	#7; //Method java/lang/StringBuilder.toString:()Ljava/lang/String;
   40:	invokevirtual	#8; //Method java/io/PrintStream.println:(Ljava/lang/String;)V
   43:	iinc	3, 1
   46:	goto	7
   49:	return

Видно, что случай с foreach менее эффективен. Мало того, что по-прежнему
заводится переменная индекса цикла (3), так ещё используется и
переменная со значением (4).

KRoN73 ★★★★★
()

странный вопорос... там просто нечему копироваться. объекты сидят в куче, а примитивные типы и так примитивны...

Pi ★★★★★
()
Ответ на: комментарий от KRoN73

> Видно, что случай с foreach менее эффективен.

Ничего не видно. JIT-компилятор не позволяет так просто оценивать эффективность.

Legioner ★★★★★
()
Ответ на: комментарий от KRoN73

он еще офигенно эффективен для генерации ошибок

Pi ★★★★★
()
Ответ на: комментарий от shumer

>А чем и как можно вот так красиво распарсить байт-код?

# eix dev-java/java-config
[U] dev-java/java-config
     Available versions:  
	(0)	1.2.6[1] 1.2.9[1] 1.2.10[1] 1.2.11[1] 1.2.11-r1 1.2.11-r1[1] 1.3.7 2.0.19[1]
	(2)	2.0.33-r1 ~2.1.3 2.1.4 ~2.1.5 ~2.1.9999[2]
     Installed versions:  1.3.7(11:08:41 25.01.2008) 2.1.4(2)(13:32:50 01.02.2008)
     Homepage:            http://www.gentoo.org/proj/en/java/
     Description:         Java environment configuration tool

KRoN73 ★★★★★
()
Ответ на: комментарий от Legioner

>Ничего не видно. JIT-компилятор не позволяет так просто оценивать эффективность.

Ну, нужно просто замерить скорость :) Вполне может быть, что JIT что-то и улучшит. Хотя я полагаю, что в лучшем случае то же самое получится.

KRoN73 ★★★★★
()
Ответ на: комментарий от KRoN73

Тьфу, это забыл оттуда:

$ javap -help
Usage: javap <options> <classes>...

where options include:
   -c                        Disassemble the code
   -classpath <pathlist>     Specify where to find user class files
   -extdirs <dirs>           Override location of installed extensions
   -help                     Print this usage message
   -J<flag>                  Pass <flag> directly to the runtime system
   -l                        Print line number and local variable tables
   -public                   Show only public classes and members
   -protected                Show protected/public classes and members
   -package                  Show package/protected/public classes
                             and members (default)
   -private                  Show all classes and members
   -s                        Print internal type signatures
   -bootclasspath <pathlist> Override location of class files loaded
                             by the bootstrap class loader
   -verbose                  Print stack size, number of locals and args for methods
                             If verifying, print reasons for failure

KRoN73 ★★★★★
()
Ответ на: комментарий от Pi

> странный вопорос... там просто нечему копироваться.

Осознал :). Тяжкое наследие С++, иногда забываю что String s - это просто ссылка.

shumer
() автор топика
Вы не можете добавлять комментарии в эту тему. Тема перемещена в архив.