In Java, a final variable is one whose value cannot be reassigned once it has been given a value. You can only use a final variable after it has been assigned a value – all final variables must be assigned values at some point in time before its first use, otherwise the compiler complains.
In Java:
1: // FinalTest.java 2: public class FinalTest{ 3: final int FINAL_VAR; 4: 5: public FinalTest(int newValue){ 6: FINAL_VAR = newValue; // compilation error if omitted. 7: } 8: 9: public static void main(String args[]){ 10: FinalTest f = new FinalTest(4); 11: } 12: }
If FINAL_VAR has been declared with the static modifier too on line 3, you will have to either:
initialize it in the same statement it is declared in (e.g. final static int FINAL_VAR = 3;); or
initialize it in a static initializer (e.g. static { FINAL_VAR = 3; } ) somewhere in the class.
This is because you cannot assign a value to a static variable from outside a static context, and the constructor coded above (lines 5 – 7) is an instance method.
In C#, instead of final variables, there are C# constants, and read-only fields. [4]
[4] C# constants are more similar to Java final variables than readonly fields. However both constants and read-only variables will be discussed here.
A C# constant is like a final variable which must be initialized in the same declaration statement. What this means is that you cannot declare a constant and initialize it in a separate statement. You use the C# const keyword to declare a constant.
Constants in C# are always implicitly static. However, you cannot declare a constant with both the const and static keywords.
The value assigned to a constant must be a literal, and cannot be decided on during runtime.
You must assign a constant a value during declaration. You cannot even declare a constant and assign a value to it in a static constructor. [5] The compiler will complain once it sees a constant variable being declared but not initialized in the same statement:
[5] A C# static constructor is similar to a Java static initializer.
class MyClass{ const int FinalVar; }
Compilation error:
test.cs(2,22): error CS0145: A const field requires a value to be provided
A constant is similar to a Java final static variable except that it must be initialized in the same statement as the one that it has been declared in.
1: using System; 2: class TestClass{ 3: const int FinalVar = 5; 4: 5: public static void Main(){ 6: Console.WriteLine(FinalVar); 7: } 8: }
In the code above, you can use TestClass.FinalVar instead of FinalVar within the class itself (on line 6), since all constants are implicitly static members of the class.
The main difference between a C# constant and a C# read-only field is that a read-only field can be initialized in a separate statement (in a constructor) from the one in which it is declared. [6] Hence, unlike a constant, a read-only field's value can be determined at runtime, as long as the read-only field is initialized before it is used.
[6] If you are wondering why C# differentiates constants from read-only fields, I believe it has to do with performance optimization. Theoretically, the CLR can optimize constants if it is known that their values are fixed even before runtime. For the same reason, it is good programming practice to declare a non-changing variable as a constant (or read-only variable) not only to prevent some code from accidentally altering that value (leading to mysterious bugs), but also because a clever compiler can take advantage of this fact to squeeze out a few more milliseconds.
Direct assignments to read-only fields can only occur:
in an instance constructor (for non-static read-only fields);
in a static constructor (for static read-only fields);
in the declaration statement itself. [7]
[7] The part of the declaration statement whereby a value is assigned to the declared field is known as a variable initializer. For example, in the statement int i = 3;, i = 3 is the variable initializer.
A read-only field can be reassigned a new value any number of times, as long as the condition above is satisfied. Read-only fields are generally used instead of constants if the value of that field cannot be determined before runtime.
Use the C# readonly keyword to declare a read-only variable:
1: class TestReadOnly{
2: readonly int FinalVar;
3:
4: TestReadOnly(int newValue){
5: // assignment in an instance constructor
6: FinalVar = newValue;
7: }
8:
9: public static void Main(){
10: TestReadOnly tro = new TestReadOnly(9);
11: System.Console.WriteLine(tro.FinalVar);
12: }
13: }
Output:
c:expt>test 9
The code below produces a compilation error because an attempt is made to assign FinalVar with a value outside a constructor.
1: class TestReadOnly{ 2: readonly int FinalVar; 3: 4: public static void Main(){ 5: TestReadOnly tro = new TestReadOnly(); 6: tro.FinalVar = 1; // illegal assignment 7: } 8: }
Compilation error:
test.cs(6,5): error CS0191: A readonly field cannot be assigned to (except in aconstructor or a variable initializer)
You can assign a value to a read-only variable when it is being declared (as part of the variable initializer). For example, you can replace line 2 with:
2: readonly int FinalVar = 9;
Read-only variables are somewhat similar to Java final variables in that once they have been assigned a value (in a constructor, or in the declaration statement) you cannot reassign a new value outside the constructor.
Read-only variables are not implicitly static. Compare this with C# constants – C# constants are implicitly static. Java final variables are also not implicitly static.
You can declare a read-only variable as static (e.g. static readonly int j;), and initialize it either:
- on the same statement as the declaration; or
- in a static constructor (see section 7.4).
18.117.230.81