Why must and must not be "final" ?

Discussion in 'Java' started by NeoGeoSNK, Nov 14, 2006.

  1. NeoGeoSNK

    NeoGeoSNK Guest

    Hello,
    I have two questions, why inner class can only access "final" argument
    outside the inner class?
    and why Java applet's init() method can't access any "final" fields?
    example:
    public class AppletGui extends JApplet {
    .........

    final JTextField textvalue;

    ..........

    public void init(){
    ..........

    textvalue = new JTextField(25); //this will
    encounter a compiled time error "the final field AppletGui.textvalue
    can not be assigned
    }
    }

    any suggestions are appreciated. ^ ^
    Thanks
    NeoGeoSnk
    NeoGeoSNK, Nov 14, 2006
    #1
    1. Advertising

  2. NeoGeoSNK

    Daniel Pitts Guest

    NeoGeoSNK wrote:
    > Hello,
    > I have two questions, why inner class can only access "final" argument
    > outside the inner class?
    > and why Java applet's init() method can't access any "final" fields?
    > example:
    > public class AppletGui extends JApplet {
    > .........
    >
    > final JTextField textvalue;
    >
    > ..........
    >
    > public void init(){
    > ..........
    >
    > textvalue = new JTextField(25); //this will
    > encounter a compiled time error "the final field AppletGui.textvalue
    > can not be assigned
    > }
    > }
    >
    > any suggestions are appreciated. ^ ^
    > Thanks
    > NeoGeoSnk


    Its purely to reenforce to the programmer what really is happening.

    The value of your parameters/variables which are used in your
    anonymouse class are copied at the time that the object is created
    (they are actually hidden final fields, I believe). If you were to
    change the value later, that would be more confusing than having to
    know that they are just "final".
    Daniel Pitts, Nov 14, 2006
    #2
    1. Advertising

  3. NeoGeoSNK

    NeoGeoSNK Guest

    "Daniel Pitts дµÀ£º
    "
    > NeoGeoSNK wrote:
    > > Hello,
    > > I have two questions, why inner class can only access "final" argument
    > > outside the inner class?
    > > and why Java applet's init() method can't access any "final" fields?
    > > example:
    > > public class AppletGui extends JApplet {
    > > .........
    > >
    > > final JTextField textvalue;
    > >
    > > ..........
    > >
    > > public void init(){
    > > ..........
    > >
    > > textvalue = new JTextField(25); //this will
    > > encounter a compiled time error "the final field AppletGui.textvalue
    > > can not be assigned
    > > }
    > > }
    > >
    > > any suggestions are appreciated. ^ ^
    > > Thanks
    > > NeoGeoSnk

    >
    > Its purely to reenforce to the programmer what really is happening.
    >
    > The value of your parameters/variables which are used in your
    > anonymouse class are copied at the time that the object is created
    > (they are actually hidden final fields, I believe). If you were to
    > change the value later, that would be more confusing than having to
    > know that they are just "final".


    Thanks a lot,
    and you mean this restriction only effective when a inner class is
    anonymouse? and not for all inner class?
    NeoGeoSNK, Nov 14, 2006
    #3
  4. NeoGeoSNK

    Chris Uppal Guest

    NeoGeoSNK wrote:

    > and you mean this restriction only effective when a inner class is
    > anonymouse? and not for all inner class?


    it applies to all inner classes whether anonymous or not. You cannot /really/
    access a variable in method from any other code, so the Java compiler fakes it
    by copying the value into the instance of the inner class -- which, as Daniel
    says -- is why the compiler insists that you have declared that variable
    "final", to ensure that you know what you are doing.

    -- chris
    Chris Uppal, Nov 14, 2006
    #4
  5. NeoGeoSNK wrote:
    > I have two questions, why inner class can only access "final" argument
    > outside the inner class?


    Similar to Daniel's comment, it's because the implementation is easier.
    I believe C#2.0 takes the point of view that when you create an
    anonymous delegate (like an anonymous inner class only a single method
    and a more complicated type system) the variable should split in to -
    with updates from the enclosing method not interacting with the
    anonymous delegate code. However, the semantics of least surprise are
    for the local variable to remain coherent. There are proposals that Java
    SE 7 will allow this, possibly having to declare the local variable as
    "public".

    > and why Java applet's init() method can't access any "final" fields?


    It cannot assign final fields as it is not a constructor. That being the
    point of final.

    A better approach to organising applets (and indeed GUI code in general)
    is to move the bulk of the code out from subclasses of components. You
    can use constructors and final as you like in such code, without having
    to conform to AWT/Swing implementation peculiarities. You can also use
    the same code in JFrame, JInternalFrame, JScrollPane, etc.

    Tom Hawtin
    Thomas Hawtin, Nov 14, 2006
    #5
  6. Chris Uppal <-THIS.org> wrote:
    > NeoGeoSNK wrote:
    >> and you mean this restriction only effective when a inner class is
    >> anonymouse? and not for all inner class?

    > it applies to all inner classes whether anonymous or not. You cannot /really/
    > access a variable in method from any other code, so the Java compiler fakes it
    > by copying the value into the instance of the inner class -- which, as Daniel
    > says -- is why the compiler insists that you have declared that variable
    > "final", to ensure that you know what you are doing.


    An extra note:
    This doesn't mean that you couldn't share non-final
    references between the outer and inner class! Just
    wrap it up into some container-class.

    Simple example:

    class Outer {
    final TextField[] tf = new TextField[1];
    class Inner
    {
    // use and modify tf[0] at will.
    }
    void init()
    {
    // use and modify tf[0] at will.
    }
    }
    Andreas Leitgeb, Nov 14, 2006
    #6
  7. NeoGeoSNK

    Mark Rafn Guest

    NeoGeoSNK <> wrote:
    >I have two questions, why inner class can only access "final" argument
    >outside the inner class?


    There is a distinction between member variables, local variables, and
    formal parameter variables (though the last two are darned similar).

    There is also a distinction between anonymous inner classes, named
    inner classes, and static inner classes.

    An anonymous inner class is defined inside a method, and has access to all
    member variables of the enclosing class, final or not (which isn't your
    question), and to all final variables and parameters of the method in which
    it's declared (which is what you're asking about). The reason they have
    to be final is because they're locally scoped and will disappear as
    soon as the method returns, which would be very bad for the anonymous class
    that tries to reference them later. The final modifier means it's safe for
    the anonymous class to keep a copy of the value when it's created, as it's
    guranteed not to change.

    Named inner classes (those that are members of a class, not declared inside a
    method) have no access to any method's parameters or variables at all, so
    nothing needs to be declared final. It has access to member variables of the
    enclosing class through an implicit OuterClassName.this reference.

    Named static inner classes are exactly like top-level classes (which are
    implicitly static). They have no access to any outside variables, except
    through an explicit reference just like any other class would.

    >and why Java applet's init() method can't access any "final" fields?
    > public class AppletGui extends JApplet {
    > .........
    > final JTextField textvalue;
    > ..........
    > public void init(){
    > ..........
    > textvalue = new JTextField(25); //this will
    >encounter a compiled time error "the final field AppletGui.textvalue
    >can not be assigned


    This is unrelated to your first question. Final member variables must be
    assigned at class construction time (through an initializer in the
    declaration, an initializer block, or inside a constructor. Any attempt to
    assign to a final member after this is illegal. That's what final means - it
    can't be assigned after construction.
    --
    Mark Rafn <http://www.dagon.net/>
    Mark Rafn, Nov 14, 2006
    #7
  8. Andreas Leitgeb wrote:
    >
    > An extra note:
    > This doesn't mean that you couldn't share non-final
    > references between the outer and inner class! Just
    > wrap it up into some container-class.
    >
    > Simple example:
    >
    > class Outer {
    > final TextField[] tf = new TextField[1];
    > class Inner
    > {
    > // use and modify tf[0] at will.
    > }
    > void init()
    > {
    > // use and modify tf[0] at will.
    > }
    > }


    I'm not sure how useful an example that is. IIRC, it does mean (from
    1.5) that you can guarantee that tf[0] is non-null, even with unsafe
    publishing. For local classes you can do much the same (but use
    AtomicReference):

    String foo(String arg) {
    final AtomicReference<String> argRef =
    new AtomicReference<String>(arg);

    new Object() {
    void bar() {
    argRef.set('<'+argRef.get()+'>');
    }
    }.bar();

    return argRef.get();
    }

    But please don't. :)

    Tom Hawtin
    Thomas Hawtin, Nov 14, 2006
    #8
  9. NeoGeoSNK

    Mark Rafn Guest


    >> NeoGeoSNK wrote:
    >>> and you mean this restriction only effective when a inner class is
    >>> anonymouse? and not for all inner class?


    >Chris Uppal <-THIS.org> wrote:
    >> it applies to all inner classes whether anonymous or not.


    Not true. Non-anonymous classes aren't declared inside a method, so have no
    access to local variables, final or not. Class members don't need to be
    final to be accessed from an inner class.

    Andreas Leitgeb <> wrote:
    >An extra note: This doesn't mean that you couldn't share non-final
    >references between the outer and inner class! Just wrap it up into some
    >container-class.


    >Simple example:
    >class Outer {
    > final TextField[] tf = new TextField[1];
    > class Inner
    > {
    > // use and modify tf[0] at will.
    > }
    > void init()
    > {
    > // use and modify tf[0] at will.
    > }
    >}


    This isn't necessary for member variables. Just make them non-final and all
    is well. It's an ugly but effective workaround when an anonymous inner class
    needs access to local variables or parameters that you want to change.
    --
    Mark Rafn <http://www.dagon.net/>
    Mark Rafn, Nov 14, 2006
    #9
  10. Mark Rafn <> wrote:
    > Andreas Leitgeb <> wrote:
    >>class Outer {
    >> final TextField[] tf = new TextField[1];
    >> ...
    >>}


    > This isn't necessary for member variables. Just make them non-final and all
    > is well. It's an ugly but effective workaround when an anonymous inner class
    > needs access to local variables or parameters that you want to change.


    trapped.
    I mixed up the context while writing the followup.

    I meant:
    void myFunc() {
    final TextField[] tf = new TextField[1];
    new Object() { void foo() { tf[0]=<whatever>; } }.foo();
    // now tf[0] is <whatever>.
    }

    AtomicReference appears to me like overkill in this respect,
    since we're talking about local variables, that are "rarely"
    (that is: never ever) shared among threads...
    Andreas Leitgeb, Nov 14, 2006
    #10
  11. NeoGeoSNK

    Chris Smith Guest

    Mark Rafn <> wrote:
    > >Chris Uppal <-THIS.org> wrote:
    > >> it applies to all inner classes whether anonymous or not.

    >
    > Not true. Non-anonymous classes aren't declared inside a method, so have no
    > access to local variables, final or not. Class members don't need to be
    > final to be accessed from an inner class.


    You can declare a named local class if you like. In that case, the
    final restriction for local variables does apply to it. So yeah, it's
    true. You can, of course, also declare non-local inner classes
    (anonymous or otherwise) for which there are no local variables in
    scope, in which case this doesn't apply.

    --
    Chris Smith
    Chris Smith, Nov 14, 2006
    #11
  12. Andreas Leitgeb wrote:
    >
    > AtomicReference appears to me like overkill in this respect,
    > since we're talking about local variables, that are "rarely"
    > (that is: never ever) shared among threads...


    The intent is clearer than using an array of length one.

    Who cares that they are thread-safe? It isn't going to make much
    difference to performance. They don't need to do bounds checking, for
    instance. Compiler optimisation can eliminate overheads of either.

    Why can't you share objects that are referred to by local variables
    between threads? java.awt.EventQueue.invokeLater, for instance.

    Tom Hawtin
    Thomas Hawtin, Nov 14, 2006
    #12
  13. NeoGeoSNK

    Daniel Pitts Guest

    Andreas Leitgeb wrote:
    > Mark Rafn <> wrote:
    > > Andreas Leitgeb <> wrote:
    > >>class Outer {
    > >> final TextField[] tf = new TextField[1];
    > >> ...
    > >>}

    >
    > > This isn't necessary for member variables. Just make them non-final and all
    > > is well. It's an ugly but effective workaround when an anonymous inner class
    > > needs access to local variables or parameters that you want to change.

    >
    > trapped.
    > I mixed up the context while writing the followup.
    >
    > I meant:
    > void myFunc() {
    > final TextField[] tf = new TextField[1];
    > new Object() { void foo() { tf[0]=<whatever>; } }.foo();
    > // now tf[0] is <whatever>.
    > }
    >
    > AtomicReference appears to me like overkill in this respect,
    > since we're talking about local variables, that are "rarely"
    > (that is: never ever) shared among threads...

    This method seems bad. If an anonymouse-inner class has to modify some
    state somewhere, have it call a method to do so, or make it
    non-anonymouse, and have it have its own state.

    void myFunc() {
    new Object() {void foo() {setTextField(<whatever>); } }.foo()
    }

    or
    class Outter {
    static class MyFooable {
    TextField textField;
    void foo() {
    textField = <whatever>;
    }
    }
    void myFunc() {
    MyFooable mf = new MyFooable();
    mf.foo();
    TextField textField = mf.textField;
    }
    }

    ------------------------
    In any case, I consider it best practice to have all variables final if
    possible, and parameters final only if necessary (although there is an
    argument to having them all final).
    If you can't make a variable final, make sure that you couldn't just
    use different final variables instead of one variable repeatedly. It
    makes code less confusing, and there really isn't a benefit to re-using
    the same variable over and over, unless it is an accumulator of some
    sort.
    (sum += value, for instance)

    Hope this makes sense.
    - Daniel.
    Daniel Pitts, Nov 14, 2006
    #13
  14. NeoGeoSNK

    Mark Rafn Guest

    >> >Chris Uppal <-THIS.org> wrote:
    >> >> it applies to all inner classes whether anonymous or not.


    >Mark Rafn <> wrote:
    >> Not true. Non-anonymous classes aren't declared inside a method, so have no
    >> access to local variables, final or not. Class members don't need to be
    >> final to be accessed from an inner class.


    Chris Smith <> wrote:
    >You can declare a named local class if you like. In that case, the
    >final restriction for local variables does apply to it.


    I didn't know that. What's the syntax look like? If it has a class name (as opposed to just a variable name pointing to an instance of an anonymous class),
    can it be referenced outside of the declaring method somehow?
    --
    Mark Rafn <http://www.dagon.net/>
    Mark Rafn, Nov 15, 2006
    #14
  15. Thomas Hawtin <> wrote:
    > Andreas Leitgeb wrote:
    >> AtomicReference appears to me like overkill in this respect,
    >> since we're talking about local variables, that are "rarely"
    >> (that is: never ever) shared among threads...

    > The intent is clearer than using an array of length one.


    Most probably it's up to programmer's taste.

    > Why can't you share objects that are referred to by local variables
    > between threads? java.awt.EventQueue.invokeLater, for instance.


    Ok, I had the reference itself in mind. Surely, the AtomicReference
    or the array both could be shared, but they entered the scene as
    a replacement for a must-be-final local reference, so it's not likely
    that the existing program logic passes them anywhere else.
    Andreas Leitgeb, Nov 15, 2006
    #15
  16. NeoGeoSNK

    Chris Uppal Guest

    Mark Rafn wrote:

    > I didn't know that. What's the syntax look like?


    aMethod()
    {
    class Local
    extends Whatever
    implements WhateverElse
    {
    ... stuff ...
    }

    Local aLocal = new Local();
    ... stuff...
    }


    > If it has a class
    > name (as opposed to just a variable name pointing to an instance of an
    > anonymous class), can it be referenced outside of the declaring method
    > somehow?


    No. What would be the point to making a class local to a method if you want to
    refer to it from outside the method ?

    Note, named local classes (like anonymous local classes) are just syntactic
    sugar. Personally I prefer to use the named form, since (a) it is less
    restricted, and (b) it is /much/ easier to read than the terrifyingly
    obfuscatory define-an-entire-class-inside-the-body-of-a-new-statement syntax.

    -- chris
    Chris Uppal, Nov 15, 2006
    #16
  17. Chris Uppal <-THIS.org> wrote:
    > Note, named local classes (like anonymous local classes) are just syntactic
    > sugar. Personally I prefer to use the named form, since (a) it is less
    > restricted, and (b) it is /much/ easier to read than the terrifyingly
    > obfuscatory define-an-entire-class-inside-the-body-of-a-new-statement syntax.


    While I agree to the possibility of producing "terrifyingly obfuscated"
    code through anonymous classes, they are "needed" to compensate for the
    lack of C-like function pointers.

    For someone, to whom finding appropriate names for stuff feels like
    the hardest part of programming, anonymous classes are just one way
    to remain sane.
    Andreas Leitgeb, Nov 15, 2006
    #17
  18. NeoGeoSNK

    Chris Uppal Guest

    Andreas Leitgeb wrote:

    [me:]
    > > Note, named local classes (like anonymous local classes) are just
    > > syntactic sugar. Personally I prefer to use the named form, since [...]


    > For someone, to whom finding appropriate names for stuff feels like
    > the hardest part of programming, anonymous classes are just one way
    > to remain sane.


    <grin/>

    Yes, I take your point, and I agree that finding good names (for anything) is
    hard. But, since the local classes /are/ local, there is not much hinging on
    the choice of name (in fact there is nothing, or the anonymous syntax wouldn't
    be usuable at all), so you can choose something bland like "Action" or
    "Handler" without making the code hard to read.

    -- chris
    Chris Uppal, Nov 15, 2006
    #18
  19. NeoGeoSNK

    NeoGeoSNK Guest

    "Chris Uppal дµÀ£º
    "
    > NeoGeoSNK wrote:
    >
    > > and you mean this restriction only effective when a inner class is
    > > anonymouse? and not for all inner class?

    >
    > it applies to all inner classes whether anonymous or not. You cannot /really/
    > access a variable in method from any other code, so the Java compiler fakes it
    > by copying the value into the instance of the inner class -- which, as Daniel
    > says -- is why the compiler insists that you have declared that variable
    > "final", to ensure that you know what you are doing.
    >
    > -- chris


    Thanks a lot
    And just as Mark Rafn says this restriction doesn't effect named inner
    class thant not defined in a method:)
    NeoGeoSNK, Nov 23, 2006
    #19
  20. NeoGeoSNK

    NeoGeoSNK Guest

    "Thomas Hawtin дµÀ£º
    "
    > NeoGeoSNK wrote:
    > > I have two questions, why inner class can only access "final" argument
    > > outside the inner class?

    >
    > Similar to Daniel's comment, it's because the implementation is easier.
    > I believe C#2.0 takes the point of view that when you create an
    > anonymous delegate (like an anonymous inner class only a single method
    > and a more complicated type system) the variable should split in to -
    > with updates from the enclosing method not interacting with the
    > anonymous delegate code. However, the semantics of least surprise are
    > for the local variable to remain coherent. There are proposals that Java
    > SE 7 will allow this, possibly having to declare the local variable as
    > "public".
    >
    > > and why Java applet's init() method can't access any "final" fields?

    >
    > It cannot assign final fields as it is not a constructor. That being the
    > point of final.
    >
    > A better approach to organising applets (and indeed GUI code in general)
    > is to move the bulk of the code out from subclasses of components. You
    > can use constructors and final as you like in such code, without having
    > to conform to AWT/Swing implementation peculiarities. You can also use
    > the same code in JFrame, JInternalFrame, JScrollPane, etc.
    >
    > Tom Hawtin


    Thanks
    And I think the problem is because that inner class can't access
    non-final local variables?and I really can't understand what does
    "semantics of least surprise " means :)
    NeoGeoSNK, Nov 23, 2006
    #20
    1. Advertising

Want to reply to this thread or ask your own question?

It takes just 2 minutes to sign up (and it's free!). Just click the sign up button to choose a username and then you can ask your own questions on the forum.
Similar Threads
  1. JFCM
    Replies:
    4
    Views:
    5,734
  2. Mr. SweatyFinger

    why why why why why

    Mr. SweatyFinger, Nov 28, 2006, in forum: ASP .Net
    Replies:
    4
    Views:
    878
    Mark Rae
    Dec 21, 2006
  3. Mr. SweatyFinger
    Replies:
    2
    Views:
    1,840
    Smokey Grindel
    Dec 2, 2006
  4. Replies:
    5
    Views:
    513
    Chris Uppal
    Nov 17, 2006
  5. Philipp
    Replies:
    3
    Views:
    1,130
    Roedy Green
    Nov 26, 2008
Loading...

Share This Page