Author Topic:   final variable
shikhar
ranch hand
posted July 17, 2000 04:27 PM         
Hi,
on compilation of the undergiven code the error comes as
"Compilation Error at Line 03: Blank final variable 'MAX_SIZE' may not have been initialized. It must be assigned a value in an initializer, OR IN EVERY CONSTRUCTOR ."
WHAT IS THE SIGNIFICANCE OF "OR IN EVERY CONSTRUCTOR "?


class Base
{
static final int MAX_SIZE;
Base(){
}
void test() {
System.out.println("Base.test()");
}

sat
greenhorn
posted July 17, 2000 04:48 PM             
Declaration of a final field must include initiaizer. Final field cannot be initialized at any place other than where it is declared.

satish

Vivek Shrivastava
ranch hand
posted July 17, 2000 04:57 PM         
Hi to all,

Let me give a chance to explain it.

Final field can be initialized(only once) at any place other than where it is declared.

Final Static field cannot be initialized at any place other than where it is declared.

small examples :

class Test{

final int xx;
{
xx= 0;
}
}

above code will compile fine.

class Test{

static final int xx;
{
xx= 0;
}
}

Code above will give a compile time error.

Hope this will help u.

vivek

[This message has been edited by Vivek Shrivastava (edited July 17, 2000).]

shikhar
ranch hand
posted July 17, 2000 05:10 PM         
Hi vivek
You said:
"Final field can be initialized(only once) at any place other than where it is declared".
But this code is not compiling, where I have initialized the MAX_SIZE in constructor.

class Base
{
static final int MAX_SIZE;
Base(){
MAX_SIZE=1;
}
void test() {
System.out.println("Base.test()");
}

Deepak M
greenhorn
posted July 17, 2000 05:20 PM             
quote:
Originally posted by shikhar:
Hi,
It must be assigned a value in an initializer, OR IN EVERY CONSTRUCTOR ."
WHAT IS THE SIGNIFICANCE OF "OR IN EVERY CONSTRUCTOR "?

class Base
{
static final int MAX_SIZE; // a blank final variable
Base(){
}
void test() {
System.out.println("Base.test()");
}


A blank final variable must be initialized in a static initializer block. Not in a constructor.
javac compiler has many bugs and does not even go as per the JLS - use jikes instead.
Heres the URL for jikes compiler

Ankur
ranch hand
posted July 17, 2000 05:27 PM             
As per the JLS -

A field can be declared final (§4.5.4). Both class and instance variables (static and non-static fields) may be declared
final.

It is a compile-time error if a blank final (§4.5.4) class variable is not definitely assigned (§16.7) by a static initializer (§8.7) of the class in which it is declared.

A blank final instance variable must be definitely assigned (§16.8) at the end of every constructor (§8.8) of the class in which it is declared; otherwise a compile-time error occurs.

Ankur

Vivek Shrivastava
ranch hand
posted July 17, 2000 05:41 PM         
Hi shikhar

Forget about my Explanation. Whatever ankur said is 100% correct.

Thanks ankur.

vivek

Deepak M
greenhorn
posted July 17, 2000 05:44 PM             
quote:
Originally posted by Ankur:
As per the JLS -

It is a compile-time error if a blank final (§4.5.4) class variable is not definitely assigned (§16.7) by a static initializer (§8.7) of the class in which it is declared.

Ankur


Thats right Ankur, we are talking about blank final "class variable" and NOT instance variable !
Therefore javac comiler should not give this error as saying "in every constructor"
Therefore use jikes compiler - which gives the right error message !
:-)

sdev
ranch hand
posted July 17, 2000 06:08 PM         
I am getting confused with , can anyone please explain me little more about this.

Thanks in advance
sdev.

maha anna
bartender
posted July 17, 2000 07:02 PM             
sdev,
Please go through the following information carefully. A final var means what ? It HAS TO HAVE a final value which CAN NOT BE CHANGED , ONCE IT IS ASSIGNED A VALUE.

So having said that, there are 2 types of final vars. 1. instance final vars. 2. class level (static) final vars. instance final var like in case 1 in the foll. example given, "final int instFinalVar1=100" means the var instFinalVar1 has a final value as 100 throughout the instance's lifetime and we CAN NOT change its value once we create an instance as "new Test(...)" statement.

We can maximum USE this assigned final value. In this context of this final var discussion , I assume you know the initialization sequence of any class. It is

1.static initialization
All static vars and static floating blocks are run first AS IN THE SAME ORDER AS WRITTEN in the source java program.

2.instance initialization
All instance vars and instance floating blocks are run next AS IN THE SAME ORDER AS WRITTEN in the source java program.

3.constructor is run

Let us take the instance final var case. We know that it has to have a value and that value has to be explicitly given by the programmer. The default values are NOT given for a final var. Even if it is a 0(zero) value for an 'instance final int' type var, it has to be explicitly given as "final int var1=0;" like that. So the bottomline is instance final var has to have a value when an instance of the class is constructed .

In the previous version of Java1.0 (I think) all instance final vars HAVE TO BE INITIALIZED when thay are DECLARED ITLSEF. In other words we have to write like this. "final int var1=10;". But latter in Java 2 ,the designers allowed little flexiblity. What if the final var has to have different values ACCORDING TO THE CONSTRUCTOR of the class used to construct the instance of the class?. To allow this, they changed the specification of the language as, "the final var has to have an explicit value by the programmer, but it can be given either in the declaration statement itself OR in a FOLLOWING instance floating block (also called as instance initializers) OR in ALL CONSTRUCTORS of the given class".

Which also means before the constructed instance is used the final vars HAVE TO HAVE A VALUE. So we can go UPTO the constructors to init them. Also note that if we choose to initialize an instance final var through constructors, we have to init the var in ALL constructors. If we think logically also, another programmer may call ANY ONE OF the available constructors of this class to create an instance of the class right? We can't rescrict them. So we HAVE to provide the initializaion in ALL constructors. But the values can be anything, need not be same.

This is story of 'instance final var' initialization and why and when should we init them.

Simillarly for the 2nd case 'static final ' vars, the story is little different. 'static var' means what? It is nothing to do with any particular instance right? So , this static final vars also HAVE TO HAVE a value explicitly assigned by the programmer and this init has to happen either in the declaration statement itself like 'static final int var1=100;' OR in one of FOLLOWING static floating blocks (also called as static initializers). Also note that in both cases instance final var and static final vars, once we assigned a value means we CAN'T CHANGE them again. That the meaning of 'final' keyword right?. Since static final vars are common for the class as a whole, the init of static final vars has to happen only in the 2 cases explained in this paragraph. They can't be assigned a value in constructors as we have seen in the case of instance final vars.

Also please go through the following example code carefully. This code explains what I have written here. Also feel free to ask anything at all.

regds
maha anna



class Test {

//case 1

final int instFinalVar1 = 100; //This is ok


//case 2
final int instFinalVar2;

{
//init in instance floating block
instFinalVar2 = 200; //This is ok

}

//case 3
final int instFinalVar3;

Test(){

/*
We MUST init the instance final var in
ALL constructors of this class ,since
instFinalVar3 is NOT INITIALIZED either in
declaration or in any instance floating
blocks. (also called as instance initializers)
*/

instFinalVar3=10;
//instFinalVar3=100;
//THis is NOT ok . Once we assign a value to a final var we CAN NOT
//chnage it afterwards
}

//constructor 2
Test(String s) {
/*
We MUST init the instance final var in
ALL constructors of this class ,since
instFinalVar3 is NOT INITIALIZED either in
declaration or in any instance floating
blocks. (also called as instance initializers)
*/

instFinalVar3=20;

}

//constructor 3
Test(int i) {
/*
We MUST init the instance final var in
ALL constructors of this class ,since
instFinalVar3 is NOT INITIALIZED either in
declaration or in any instance floating
blocks. (also called as instance initializers)
*/
instFinalVar3=30;

}

//case 4
static final int staticFinalVar1 = 10; //this is ok

//case 5
static final int staticFinalVar2;

static{
/*init in static floating block and this
has to be written AFTER this
"static final int staticFinalVar2;" declaration
statement in the source java program file. Otherwise
forward reference problem occur. This holds true
for case2 also. Check the foll case6.
*/
staticFinalVar2 = 200; //This is ok

}


//case 6
static{
/*init in static floating block and this
has to be written AFTER this
"static final int staticFinalVar3;" declaration
statement in the source java program file. Otherwise
forward reference problem occur. This holds true
for case2 also.
*/

staticFinalVar3 = 300; //This is NOT ok

}

static final int staticFinalVar3; //THis is NOT ok
//This declaration has to be written before the above
//static floating block (also called as static
//initializing block)
}


[This message has been edited by maha anna (edited July 17, 2000).]

Surya K
unregistered
posted July 17, 2000 08:16 PM           
Hi Maha,

Wow!!!. That is a very, very, . . . good explanation. Thanks for all your time and patience to prepare such a big explanation.

Nirmala
ranch hand
posted July 17, 2000 08:36 PM         
Maha anna,
What a great Explanation?,This so great and excellent.
Thanks
Nirmala

Helen Yu
greenhorn
posted July 17, 2000 09:48 PM             
Hi, Maha:
How great you are!

kevin jia
greenhorn
posted July 17, 2000 10:58 PM             
Hi,
But I have a question. We'll never need to use instance final variable. Because instance final variable's value is fixed, why we keep the same value in all the instances of the class, it will waste the memory, we should use static final variable instead of instance final variable.
By the way, we don't discuss local final variable. For local final variable , delay initialization is permitted.
I wait your response.

sdev
ranch hand
posted July 18, 2000 06:32 AM         
Hi maha anna,

Thank you very much for your such a good explanation.

Thank you very much once again,
sdev.

Ajith Kallambella
bartender
posted July 18, 2000 07:36 AM             
Kevin,
Not always class-level final variables can substitute instance final variables. You will have to use instance final variables in situations where you need to store some computed or inferred values based on the state of the object.

To make things clear, I came up with a small example. Look at the Employee class here. The attribute Initials is computed based on the values of lastName and firstName. Since it is unlikely to change( or if the design dectates that it shouldnot change ) after the object is constructed I have used a final instance variable to store the initial. This way the code gets optimized and you don't have to construct the Initials string every time you want to print it.

code:

class Employee
{
String firstName, lastName ;
final String Initials ;

Employee() { Initials = "" ;}

Employee( String f, String l)
{
firstName = f ; lastName = l ;
Initials = f.charAt(0) + "." + l.charAt(0);
}

Employee( String f, String m, String l)
{
firstName = f ; lastName = l ;
Initials = f.charAt(0) + "." + m.charAt(0) + "." + l.charAt(0) ;
}


public String toString() { return Initials ;}

public static void main( String[] s)
{
Employee e = new Employee("John", "F", "Kennedy");
System.out.println( e ) ;
}
}


Another example of final instance variable is used by Java ( internally ) in Arrays. Remember the .length attribute which gives you the number of items in the array? Actually it is declared as final instance variable and gets initialized soon after the array is constructed. This way length of array is not computed by iterating through the array items every time, but is simply retrieved using the final computed variable. Also, this is the reason why the size of an array, once created, cannot be changed and arrays become immutable.

Hope this helps.

Ajith

kevin jia
greenhorn
posted July 18, 2000 08:27 AM             
Hi, Ajith
Thank you so much. Now I'm clear, each instance of the class can keep its own final instance variable, sometimes we have this need. Thanks again!

John Fairbairn
greenhorn
posted July 18, 2000 08:33 AM             
Thanks Ajith and Maha for giving us such good explanations about this.

|