Интересно, как переменные, помеченные как final, интерпретируются Groovy (в 1.8.0, 1.8.1). Я знаю, что это имеет смысл на Java, и можно улучшить производительность и, конечно же, помочь избежать глупых ошибок. Я хотел бы узнать, может ли final помочь java-компилятору оптимизировать программу, написанную в Groovy. Интересно, сохраняют ли трансформаторы Groovy окончательные маркировки для переменных.
Имеет ли смысл отмечать переменную как final в groovy?
Ответ 1
Как Джастин сказал, если для вас важны оптимизация, которую компилятор выполняет для конечных переменных, то вы не должны использовать Groovy.
Однако, если производительность Groovy достаточно хороша, то по-прежнему полезно пометить переменные final по двум причинам:
-
Защита инвариантов вашего класса, то есть убедитесь, что значение значения не может быть изменено после построения объекта. Java применяет это во время компиляции, Groovy только применяет это во время выполнения, но это лучше, чем молчание, позволяющее изменить неизменяемое значение.
- Документация
. Пользователи вашего класса могут легко увидеть, какие значения они могут изменить.
Ответ 2
Не кажется, что groovyc
будет включать конечные переменные так, как это делает javac. Я создал два тестовых скрипта, один из которых использует final, а другой нет:
final String message = "Hello World"
println message
String message = "Hello World"
println message
javap -c
выдал тот же результат для обоих классов:
0: invokestatic #18; //Method $getCallSiteArray:()[Lorg/codehaus/groovy/runtime/callsite/CallSite; 3: astore_1 4: ldc #58; //String Hello World 6: astore_2 7: aload_1 8: ldc #59; //int 1 10: aaload 11: aload_0 12: aload_2 13: invokeinterface #63, 3; //InterfaceMethod org/codehaus/groovy/runtime/callsite/CallSite.callCurrent:(Lgroovy/lang/GroovyObject;Ljava/lang/Object;)Ljava/lang/Object; 18: areturn 19: nop
javac
оптимизировал astore
/aload
:
Без final
:
0: ldc #2; //String Hello World 2: astore_1 3: getstatic #3; //Field java/lang/System.out:Ljava/io/PrintStream; 6: aload_1 7: invokevirtual #4; //Method java/io/PrintStream.println:(Ljava/lang/String;)V 10: return
С final
:
0: getstatic #2; //Field java/lang/System.out:Ljava/io/PrintStream; 3: ldc #3; //String Hello World 5: invokevirtual #4; //Method java/io/PrintStream.println:(Ljava/lang/String;)V 8: return
Все сказанное, если производительность имеет первостепенное значение, Groovy - это плохой выбор для начала. Вложение конечных переменных не избавит вас от накладных расходов при использовании отражения для вызовов методов.
Ответ 3
пока нет. но это может произойти в будущем, поэтому я по-прежнему отмечаю их, если они соответствуют