Is there any runtime benefit to using the java 'final' modifier in client code

16 views
Skip to first unread message

Davis Ford

unread,
Nov 5, 2009, 11:02:04 AM11/5/09
to google-we...@googlegroups.com
Aside from just declaring intent that a field's value isn't supposed to change and generating a compiler error if you assign a new value, some JDKs are known to optimize the bytecode when fields are final.

I'm wondering if there is any such value in the translation from Java to JavaScript (i.e. does it translate to const in JS)?

Regards,
Davis

Sripathi Krishnan

unread,
Nov 5, 2009, 12:52:21 PM11/5/09
to google-we...@googlegroups.com
Yes.

If you have something like this - public static final String HELLO = "Hello"; 
GWTC will get rid of the field in the compiled js, and just inline (i.e. "hard-code" ) the value everywhere it is used. 

--Sri


2009/11/5 Davis Ford <davi...@zenoconsulting.biz>

Davis Ford

unread,
Nov 5, 2009, 1:36:12 PM11/5/09
to google-we...@googlegroups.com
Ok, I can see that for string constants, but what about other scenarios?

classes?

public final class SomeClass { }  vs. public class SomeClass { }

object references?

public void doSomething( ) {
   final ArrayList<String> list = new ArrayList<String>();
}

vs. 

public void doSomething( ) {
  ArrayList<String> list = new ArrayList<String>();
}

method args?  similar to above:

public void doSomething(final ArrayList<String> list) {}  vs. public void doSomething(ArrayList<String> list) {}

methods?

public final void doSomething( ) {}  vs. public void doSomething( ) {}

Regards,
Davis

charlie

unread,
Nov 5, 2009, 1:46:25 PM11/5/09
to google-we...@googlegroups.com
Good question, does final act as an inline keyword ? That would be awesome .

Ian Petersen

unread,
Nov 5, 2009, 2:21:44 PM11/5/09
to google-we...@googlegroups.com
I don't know the answer to the question, but I can make some arguments
"from common sense".

In the real-Java world, the set of available types is completely open
at compile time--the compiler has no idea what classes might get
loaded at run time because classloaders can do just about anything.
Even at run time, the JVM doesn't know whether you'll be loading more
types "in the future". As a result, non-final types and methods are
always have the _potential_ to be sub-typed or overridden. In
contrast, final types and methods cannot be sub-typed or overridden.
This distinction makes it easier to JIT final things. (I think it's
possible to do some of the same optimizations in both cases, you just
have to keep enough information around to undo over-aggressive
optimizations in the case that you discover you've been too
aggressive, but that's sort of besides the point.)

GWT is a completely different world. The GWT compiler has a
"closed-world" perspective. By intentional design, classloaders are
not supported in GWT, and the set of types visible at compile time is
the complete universe of types that are supported by the application
at run time. As such, non-final methods that are not overridden are
"effectively final" and non-final classes that are not sub-typed are
"effectively final". The GWT compiler has complete freedom to treat
the "effectively final" methods and types as "actually final" because
the closed-world perspective guarantees that no new types will appear
after compilation and so the distinction between "effectively final"
and "actually final" is academic. There are lots of optimizations
that the GWT compiler makes because of the closed-world perspective.
One of the most beneficial is dead code elimination: methods that are
never called aren't even represented in the generated Javascript.

To summarize, using final might help the compiler better analyze your
code, so, in some complicated cases, you might get some benefit from
using it because the compiler might be able to prove that a
type/method/instance is final where without the final keyword the
proof might be elusive. The scenarios where this is true are becoming
rarer, though, because there's lots of active work going on to improve
the compiler's optimization abilities so it gets better and better at
analyzing your code and there are more and more cases where
"effectively final" can be determined.

Given all the above, my personal take is that final is most useful as
a declaration of intent. Mutability is difficult to reason about (or,
at least, more difficult than immutability). If you are building a
library of code to be shared with others, you need to design for
re-use. On the other hand, if you're building an application and it's
easy (both technically and organizationally) for any developer to make
a change to any piece of the application, it makes more sense to
design for maintainability. One key way to do that is to limit the
influence of system components to the tightest circle you can manage.
If, down the line, you discover the circle's too tight, you just
loosen it. The benefit from this approach is that it's easier to make
changes because it's easier to reason about the system's behaviour.
Because I take this perspective, I tend to use final quite a lot.

Ian

BobR

unread,
Nov 6, 2009, 10:42:51 AM11/6/09
to Google Web Toolkit
Unless I am missing something, I think it is a simple thing.

In declaring handlers/listeners MUCH of the GWT client code that I
have seen uses anonymous inner classes.

If you are using method variables in the enclosing method, or if you
are using an argument passed in to the enclosing method,
the only way an anonymous inner class can see them is if they are
declared 'final'. That much is just a basic rule
working with anonymous inner classes.

Bob
> >>> 2009/11/5 Davis Ford <davisf...@zenoconsulting.biz>

Davis Ford

unread,
Nov 6, 2009, 11:39:06 AM11/6/09
to google-we...@googlegroups.com
Hi Bob -- I tend not to go overboard with anonymous inner classes.   It sure is convenient but makes testing the logic of those classes that much harder.

Instead, I tend to do something like this following the MVP pattern:

public final class Presenter {

    public interface View {
             HasClickHandlers getSaveWidget( );
    }

   public Presenter(final View view) {
       view.getSaveWidget( ).addClickhandler(saveHandler);
   }

    /* package */ final ClickHandler saveHandler = new ClickHandler( ) {
            // logic here.
    }

    /* package */ final AsyncCallback<Void> saveCallback = new AsyncCallback<Void>( ) {
           // logic here
    }
}

This allows me to easily test most of the UI logic with just JUnit and EasyMock.  Note that I put the final modifier everywhere here that it could be applied.  This is just a coding preference I have been in the habit of with Java for a while -- but I have no real clue how this gets translated to JavaScript and if it ends up making any difference at all.  I'm guessing it doesn't adversely affect it -- unless you are one of those that hates seeing final everywhere for the purpose of readability, but I was just curious if it has any benefit at all in the generated code.

Regards,
Davis
Reply all
Reply to author
Forward
0 new messages