Toward more extensive use of final

R

Roedy Green

I have been working with IntelliJ which keeps making suggestions to
improve you code. One thing it likes to do is add finals wherever it
can.

This presumably helps the compiler generate better code at it makes
clear to maintenance programmers what you can count on staying fixed.

There are two idioms you might not know that allow final:


private static final int x;

static {

x = complicated Expression involving other constants;
}

This is good when order of initialisation matters. If you put the
code inside a static init, the order can't be ruined by a
code-beautifier that alphabetises or otherwise reorders fields.

also

private final int x;

Constructor ( )
{
x = something;
}
 
S

Stefan Schulz

Be careful, though, in both cases the field may be exposed to external
viewers before being assigned, and this will have the most undesirable
effect of having the "final" value change.
 
J

Jacob

Roedy said:
private final int x;

Constructor ( )
{
x = something;
}

Sometimes this is not possible, for instance if "something" is
declared to throw an exception. The common pattern is then to
first assign to a temporary variable before assiging to the
class variable, as the final can be assigned just once inside
the ctor:

Constructor()
{
int tmp;
try {
tmp = something;
}
catch (Exception e) {
tmp = somethingElse;
}

x = tmp;
}
 
T

Thomas Hawtin

Roedy said:
This presumably helps the compiler generate better code at it makes
clear to maintenance programmers what you can count on staying fixed.

Slightly better code from the java source->byte code compiler for static
fields (constant expressions). From 1.5 byte code->machine code compiler
can make assumptions that final fields do not have to be reread after
synchronisation and volatile operations. Final local variables make no
difference from a performance perspective.
private static final int x;

static {

x = complicated Expression involving other constants;
}

Rather irritatingly you can't qualify the assignment for statics:

class MyClass {
private static final OtherClass thing;
static {
OtherClass thing = new OtherThing();
... configure thing ...
MyClass.thing = thing; // compile error
}
...
}

IIRC, in Effective Java, Josh Bloch recommends using static creation
methods instead:

class MyClass {
private static final OtherClass thing = descriptiveMethodName();
...
private static OtherClass descriptiveMethodName() {
OtherClass thing = new OtherThing();
... configure thing ...
return thing;
}
}
This is good when order of initialisation matters. If you put the
code inside a static init, the order can't be ruined by a
code-beautifier that alphabetises or otherwise reorders fields.

If you put all static initialisation in static initialisers. Code
reordering is still likely to make a mess if you go for static
initialisers next to declarations.
private final int x;

Constructor ( )
{
x = something;
}

I much prefer to always qualify instance field in constructors (and
setters) with this..

Tom Hawtin
 
J

jagonzal

Roedy said:
private static final int x;

static {

x = complicated Expression involving other constants;
}

Careful with that - if "complicated expression" throws an exception,
you'll get an ExceptionInInitializerError, and the class won't be
loaded - and if your app survived that, next time
you try to use that class withing the app you'll get a
NoClassDefFoundException.

(somebody please correct me if I'm wrong)
 
T

tom fredriksen

Careful with that - if "complicated expression" throws an exception,
you'll get an ExceptionInInitializerError, and the class won't be
loaded - and if your app survived that, next time
you try to use that class withing the app you'll get a
NoClassDefFoundException.

I think it wont compile if the static block can throw an exception.

/tom
 
T

tom fredriksen

Roedy said:
I have been working with IntelliJ which keeps making suggestions to
improve you code. One thing it likes to do is add finals wherever it
can.

This presumably helps the compiler generate better code at it makes
clear to maintenance programmers what you can count on staying fixed.

There are two idioms you might not know that allow final:


private static final int x;

static {

x = complicated Expression involving other constants;
}

This is good when order of initialisation matters. If you put the
code inside a static init, the order can't be ruined by a
code-beautifier that alphabetises or otherwise reorders fields.

also

private final int x;

Constructor ( )
{
x = something;
}

I am not sure I understand what you are getting in this post.
You are listing three points 1) intellij and finals, 2) musings on
finals in compilation and 3) idioms for using final.
AFAICT, you are not making a suggestion or conclusion, could you please
elaborate.

/tom
 
I

Ingo R. Homann

Hi,

tom said:
I think it wont compile if the static block can throw an exception.

It will compile and the static block can throw a RuntimeException.

Ciao,
Ingo
 
R

Roedy Green

I am not sure I understand what you are getting in this post.
You are listing three points 1) intellij and finals, 2) musings on
finals in compilation and 3) idioms for using final.
AFAICT, you are not making a suggestion or conclusion, could you please
elaborate.

There is nothing to explain. You understand perfectly.
 
N

neuneudr

Hi Roedy,

first thanks a lot for mindprob.com!
I have been working with IntelliJ which keeps making
suggestions to improve you code. One thing it likes to
do is add finals wherever it can.

If you let him do it (which I certainly do). But you can customize
everything (like asking him to propose or not final for method
parameters, etc.): convenient for people who have their preferred
way of doing it (and who thinks that it's better than Jetbrain's
default config, but that is another topic ;)

This presumably helps the compiler generate better code at
it makes clear to maintenance programmers what you can
count on staying fixed.

And it surely helps IntelliJ's own (incredible IMHO) real-time
source code parser to make very relevant comments like
"condition xxx will always be true" or "code here will never
be executed" etc.

I'm not talking about the usual compiler messages, but
messages made possible by IDEA's own Java source
tree framework (available to anyone willing to write
plugins for IDEA btw).

I've had case where I'd just stop, think a little bit and
realize "oh my, IntelliJ is right!" just followed by
"how could he know that!?". Then I realize that it's
been analyzing the code quite extensively and used
all the infos it had (like that tiny little "final" modifier
here and there) to eventually make its correct statement.

What I'm saying is that I *know* what IDEA's parser
is capable of, but once it while it still surprises me.

IDEA's parser is good, very good. And any hint you give
hime just makes him better.

Bye and thanks again for mindprob,

Driss
 
N

neuneudr

Stefan said:
Be careful, though, in both cases the field may be exposed to external
viewers before being assigned, and this will have the most undesirable
effect of having the "final" value change.

Hi,

can you show me an example of how the following field could
be exposed to an external viewer before the object being
constructed ?

How could any external viewer access a private instance field
before having a reference to the object ?


Roedy's (second) example
 
N

neuneudr

public class A {
private final int x;
A() {
new B(this);
this.x = 42;
}
public int getX() {
return x;
}
}

public class B {
public B(A a) {
System.err.println(a.getX();
}
}

thanks!
 
N

neuneudr

Hello again,

I added to "System.out" to your example and
ran it from IntelliJ IDEA...

41 appears in the color black at the console.
0 appears in red
43 appears in black.

Can somebody explain me what is going on?
(I realize that 0 appears because it hasn't
been initialized, but how does the console
notice that?)

class B {
public B(A a) {
System.out.println("41");
System.err.println(a.getX());
System.out.println("43");
}
 
A

Andrew McDonagh

Hello again,

I added to "System.out" to your example and
ran it from IntelliJ IDEA...

41 appears in the color black at the console.
0 appears in red
43 appears in black.

Can somebody explain me what is going on?
(I realize that 0 appears because it hasn't
been initialized, but how does the console
notice that?)

class B {
public B(A a) {
System.out.println("41");
System.err.println(a.getX()); ^^^
System.out.println("43");
}
its more likely that the console is showing the output was to std Err
not std Out.
 
T

Thomas Hawtin

can you show me an example of how the following field could
be exposed to an external viewer before the object being
constructed ?

How could any external viewer access a private instance field
before having a reference to the object ?


public class A {
private final int x;
A() {
new B(this);
this.x = 42;
}
public int getX() {
return x;
}
}

public class B {
public B(A a) {
System.err.println(a.getX();
}
}

The this need not be explicit. Anonymous inner classes have an implicit
reference to the outer this, and are often created and released in
constructors.

Tom Hawtin
 
R

Roedy Green

41 appears in the color black at the console.
0 appears in red
43 appears in black.

Eclipse does the same thing.
System.err is red, System.out is black.
 
S

Stefan Schulz

Hi,

can you show me an example of how the following field could
be exposed to an external viewer before the object being
constructed ?

How could any external viewer access a private instance field
before having a reference to the object ?

static field:

class A1 {
private static final A1 instance;

static {
instance = new A1(new B1());
}

public static A1 getInstance(){
return instance;
}

/* ... */
}

class B1 {
public B1(){
A1 foo = A1.getInstance(); // <--- will return 0
/* ... */
}

/* ... */
}

non-static:

interface Priority {
int getPriority();
}

class A2 implements Priority {
private static PriorityList list = new PirorityList();

private final int priority;

public A2(int priority){
list.add(this);

this.priority = priority;
}

public int getPriority(){
return priority;
}
}

class PriorityList implements List<Priority> {
/* ... */

public boolean add(Priority a){ /* inserts at priority position */
int prio = a.getPriority(); // <--- will return 0

/* ... */
}
}
 

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

No members online now.

Forum statistics

Threads
473,755
Messages
2,569,536
Members
45,013
Latest member
KatriceSwa

Latest Threads

Top