Why must and must not be "final" ?

N

NeoGeoSNK

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
 
D

Daniel Pitts

NeoGeoSNK said:
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".
 
N

NeoGeoSNK

"Daniel Pitts дµÀ£º
"
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?
 
C

Chris Uppal

NeoGeoSNK said:
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
 
T

Thomas Hawtin

NeoGeoSNK said:
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
 
A

Andreas Leitgeb

Chris Uppal said:
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.
}
}
 
M

Mark Rafn

NeoGeoSNK said:
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.
 
T

Thomas Hawtin

Andreas said:
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
 
M

Mark Rafn

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 said:
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.
 
A

Andreas Leitgeb

Mark Rafn said:
Andreas Leitgeb said:
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...
 
C

Chris Smith

Mark Rafn said:
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.
 
T

Thomas Hawtin

Andreas said:
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
 
D

Daniel Pitts

Andreas said:
Mark Rafn said:
Andreas Leitgeb said:
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.
 
M

Mark Rafn

Chris Smith said:
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?
 
A

Andreas Leitgeb

Thomas Hawtin said:
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.
 
C

Chris Uppal

Mark said:
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
 
A

Andreas Leitgeb

Chris Uppal said:
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.
 
C

Chris Uppal

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
 
N

NeoGeoSNK

"Chris Uppal дµÀ£º
"
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:)
 
N

NeoGeoSNK

"Thomas Hawtin дµÀ£º
"
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".


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 :)
 

Ask a Question

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

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

Forum statistics

Threads
473,769
Messages
2,569,582
Members
45,065
Latest member
OrderGreenAcreCBD

Latest Threads

Top