I was reading the question here : Java : in what order are static final fields initialized?
According to the answer
"except that final class variables and fields of interfaces whose
values are compile-time constants are initialized first ..."
I think this is not correct because the following will fail :
static {
String y = x;
}
public static final String x = "test";
In the static block, x is not recognized. Can anyone please comment if that answer is correct ?
The order of initialization doesn't change the fact that the JLS doesn't let you refer to variables before they're declared in various cases. This is described in JLS§8.3.3:
Use of class variables whose declarations appear textually after the use is sometimes restricted, even though these class variables are in scope (§6.3). Specifically, it is a compile-time error if all of the following are true:
The declaration of a class variable in a class or interface C appears textually after a use of the class variable;
The use is a simple name in either a class variable initializer of C or a static initializer of C;
The use is not on the left hand side of an assignment;
C is the innermost class or interface enclosing the use.
That's why your code gets this compilation erorr:
error: illegal forward reference
The statement that static fields that are constant variables are initialized first is indeed defined in JLS§12.4.2:
Otherwise, record the fact that initialization of the Class object for C is in progress by the current thread, and release LC.
Then, initialize the static fields of C which are constant variables (§4.12.4, §8.3.2, §9.3.1).
...
Next, execute either the class variable initializers and static initializers of the class, or the field initializers of the interface, in textual order, as though they were a single block.
As you can see, constant variables are initialized in step 6, but others in step 9.
This demonstrates the behavior:
public class Example {
static String y;
static {
y = foo();
}
static String foo() {
return x.toUpperCase();
}
public static final String x = "test";
public static void main(String[] args) throws Exception {
System.out.println(x);
System.out.println(y);
}
}
That compiles, and outputs:
test
TEST
In contast, if you change the x line so it's not constant anymore:
public static final String x = Math.random() < 0.5 ? "test" : "ing";
It compiles, but then fails because x is null as of y = foo();.
For the avoidance of doubt: I don't recommend using methods to initialize fields like that. :-)
As this answer states:
... they are initialized in the order in which they appear in the source.
You are absolutely right, your example fails, because you are trying to use a variable that is declared after the usage. Since static block are executed in order of the source code, you are absolutely correct and should suggest and edit for that answer, because this statement is invalid:
except that final class variables ... are initialized first.
Related
In Java, initialization of static variables is executed in textual order. As a result it's not possible to access a static variable e.g. in a static initializer block before it is decleared.
However, I noticed that there are certain possibilities to access a static variable before it is declared.
Given the following code:
static {
STATIC = true;
}
public static boolean STATIC = false;
public static void main (String[] args) {
System.out.println(STATIC);
}
One would expect that there is a compile error in the static initializer block (STATIC = true;), but it's actually compiling fine. Furthermore, the output of the program is false. I'd expect it to be true, since I'm assigning a value to it in the static initializer.
Why is this code snippet not a compile error and why is the variable not set to true after initialization?
In which cases (in general) is it possible to forward access a static variable in Java?
Why is this code snippet not a compile error and why is the variable not set to true after initialization?
Java allows forward references to static variables if it is used on the left hand side of an assignment statement. The reason why the value is false after initialization is, that when Java reaches the static initializer block, the variable STATIC is already declared (which happens before actual initialization of the class) and initially set to false (default value). After the static initializer, the assignment on the declaration line is still executed and the value will end up as false.
In which cases (in general) is it possible to forward access a static variable in Java?
The Java Language Specification (JLS) for Java 8 says in 12.4.1 When Initialization Occurs:
The static initializers and class variable initializers are
executed in textual order, and may not refer to class variables
declared in the class whose declarations appear
textually after the use, even though these class variables are in
scope (§8.3.3).
In general, as stated, forward references are not allowed. But there are certain exceptions described in 8.3.3 Forward References During Field Initialization:
8.3.3. Forward References During Field Initialization
Use of class variables whose declarations appear textually
after the use is sometimes restricted, even though these class
variables are in scope (§6.3). Specifically, it is a compile-time
error if all of the following are true:
The declaration of a class variable in a class or interface C
appears textually after a use of the class variable The use
is a simple name in either a class variable initializer of C or a
static initializer of C The use is not on the left hand side
of an assignment C is the innermost class or interface
enclosing the use
To illustrate these conditions, I created the class ThisClass with an example for each of the conditions. If only one of those four conditions is false, it's not a compile error!
1. The declaration of a class variable in a class or interface C appears textually after a use of the class variable
public static boolean STATIC1 = false;
static {
if (!STATIC1) {
System.out.println("Set STATIC1 to true");
STATIC1 = true;
}
}
The usage of STATIC1 occurs after it is defined. The most basic condition for a compiler error is violated. As you would expect, the value of STATIC1 after initialization is true.
2. The use is a simple name in either a class variable initializer of C or a static initializer of C
static {
if (!ThisClass.STATIC2) {
System.out.println("Set STATIC2 to true");
ThisClass.STATIC2 = true;
}
}
public static boolean STATIC2 = false;
The first condition is now met, but the second condition is violated. We are using the qualified name (and not the simple name) to access the variable STATIC2. The difference is described in the JLS in 6.2 Names and Identifiers:
There are two forms of names: simple names and qualified names. A
simple name is a single identifier. A qualified name
consists of a name, a "." token, and an identifier.
More interesting is, what actually happens during initialization. On the first line of the static initializer, the value of STATIC2 is read via the class qualifier. At this point (since the class is initialized in textual order) the variable STATIC2 has not been initialized yet. In this case, the default value is used, which for boolean is false. The if block is entered and the value of STATIC2 is set to true. Initialization is continued and STATIC2 is set to false again, which is the state the variable will be in after initialization.
Note: To prove that the assignment to true actually happens, you can try something like this:
static {
if (!ThisClass.STATIC2a) {
System.out.println("Set STATIC2a to true");
ThisClass.STATIC2a = true;
}
}
public static boolean STATIC2a;
This code compiles perfectly fine and the value of STATIC2a at the end of initialization will be true! The last line of code can even be replaced with the following curious statement, which clarifies even more what's happening:
public static boolean STATIC2a = ThisClass.STATIC2a;
3. The use is not on the left hand side of an assignment
static {
System.out.println("Set STATIC3 to true");
STATIC3 = true;
}
public static boolean STATIC3 = false;
Now we are using the class variable before declaration and are using it with a simple name. However, the third condition in the JLS is not met, since it appears on the left hand side of an assignment. What happens is more or less the same as if it was accessed qualified. The default value false of STATIC3 is overridden with true and then set back to false on the last line of code.
Note: The same as in example 2a holds true. If there is no assignment on the last line of code (or the STATIC3a = ThisClass.STATIC3a no-op), STATIC3a is initialized to true:
static {
System.out.println("Set STATIC3a to true");
STATIC3a = true;
}
public static boolean STATIC3a;
4. C is the innermost class or interface enclosing the use
static class OtherClass {
static {
if (!STATIC4) {
System.out.println("Set STATIC4 to true");
STATIC4 = true;
}
}
}
public static boolean STATIC4 = false;
STATIC4 is defined in the outer class ThisClass and therefor not defined in the innermost class from the perspective of use in OtherClass. The first line in the static block meets all three above conditions. Declaration appears textually after the use, it's referenced by a simple name and the use is also not on the left hand side of an assignment. But since outer classes are always initialized before any nested class, the STATIC4 = false assignment in ThisClass happens before the static initializer in OtherClass.
It is important to see, that initialization of OtherClass does not have to happen when the outer ThisClass is initialized (it might even be loaded, but loading != initialization). We need to make sure, that OtherClass is initialized by e.g. creating an instance of it (see 12.4.1 in the JLS).
The whole program can be studied here:
http://ideone.com/fl5Vet
I am new to enums in java and I am confused as to why this code compiles fine
enum Scale5 {
GOOD(), BETTER(), BEST();
static Scale5 s=GOOD;
}
But this code fails:
enum Scale5 {
GOOD(), BETTER(), BEST();
Scale5 s=GOOD;
}
And I get the error : illegal reference to static field from initializer.
I dont understand the reason.I am relatively inexperienced in enums so please dump it down for me.Thanks a lot!
The question asked here Cannot refer to the static enum field within an initializer? is the exact opposite of what I have asked.In my case declaring s as static compiles the code just fine.
From Java Language Specification:
It is a compile-time error to reference a static field of an enum type
that is not a constant variable (§4.12.4) from constructors, instance
initializer blocks, or instance variable initializer expressions of
that type.
Think of an enum like this:
public final class Scale5
{
public static final Scale5 GOOD = new Scale5();
public static final Scale5 BETTER = new Scale5();
public static final Scale5 BEST = new Scale5();
static Scale5 s = GOOD;//works because GOOD is initialized first;
Scale5 ss = GOOD;//doesn't work because in order to initialize GOOD,
//ss must be assigned an object that is not yet initialized;
}
It is very simple. The first case works because the compiler defines all the enum constants, then initializes static variables. Hence, GOOD at that point already exists and all is fine.
On the second case, the variable exists for all the enum constants, hence, when you are creating GOOD (or BETTER or BEST), GOOD must already be defined and bound. This is of course, illegal.
Consider following example:
class X {
public static final X GOOD = new X();
X y = GOOD;
static X z = GOOD;
public static void main(String[] args) {
System.out.println(GOOD);
System.out.println(GOOD.y);
System.out.println(X.z);
}
}
Output:
X#1db9742
null
X#1db9742
As you see value of GOOD.y is null. That is because at the moment of initializing value of
public static final X GOOD = new X();
when you invoked new X() you ware using current value of GOOD which is null until new X() will be finished. While in case of normal classes this behaviour is allowed, it was forbidden for enums probably because it was too often misunderstood.
In case of static fields they are executed problem dissipaters because they are executed in order of declaration, so
static X z = GOOD;
will be executed when we are sure that GOOD was initialized with proper value.
I have a program like this:
class Test {
final int x;
{
printX();
}
Test() {
System.out.println("const called");
}
void printX() {
System.out.println("Here x is " + x);
}
public static void main(String[] args) {
Test t = new Test();
}
}
If I try to execute it, i am getting compiler error as : variable x might not have been initialized based on java default values i should get the below output right??
"Here x is 0".
Will final variables have dafault values?
if I change my code like this,
class Test {
final int x;
{
printX();
x = 7;
printX();
}
Test() {
System.out.println("const called");
}
void printX() {
System.out.println("Here x is " + x);
}
public static void main(String[] args) {
Test t = new Test();
}
}
I am getting output as:
Here x is 0
Here x is 7
const called
Can anyone please explain this behavior..
http://docs.oracle.com/javase/tutorial/java/javaOO/initial.html, chapter "Initializing Instance Members":
The Java compiler copies initializer blocks into every constructor.
That is to say:
{
printX();
}
Test() {
System.out.println("const called");
}
behaves exactly like:
Test() {
printX();
System.out.println("const called");
}
As you can thus see, once an instance has been created, the final field has not been definitely assigned, while (from http://docs.oracle.com/javase/specs/jls/se7/html/jls-8.html#jls-8.3.1.2):
A blank final instance variable must be definitely assigned at
the end of every constructor of the class in which it is
declared; otherwise a compile-time error occurs.
While it does not seem to be stated explitely in the docs (at least I have not been able to find it), a final field must temporary take its default value before the end of the constructor, so that it has a predictable value if you read it before its assignment.
Default values: http://docs.oracle.com/javase/specs/jls/se7/html/jls-4.html#jls-4.12.5
On your second snippet, x is initialized on instance creation, so the compiler does not complain:
Test() {
printX();
x = 7;
printX();
System.out.println("const called");
}
Also note that the following approach doesn't work. Using default value of final variable is only allowed through a method.
Test() {
System.out.println("Here x is " + x); // Compile time error : variable 'x' might not be initialized
x = 7;
System.out.println("Here x is " + x);
System.out.println("const called");
}
JLS is saying that you must assign the default value to blank final instance variable in constructor (or in initialization block which is pretty the same). That is why you get the error in the first case. However it doesn't say that you can not access it in constructor before. Looks weird a little bit, but you can access it before assignment and see default value for int - 0.
UPD. As mentioned by #I4mpi, JLS defines the rule that each value should be definitely assigned before any access:
Each local variable (§14.4) and every blank final field (§4.12.4, §8.3.1.2) must have a definitely assigned value when any access of its value occurs.
However, it also has an interesting rule in regards to constructors and fields:
If C has at least one instance initializer or instance variable initializer then V is [un]assigned after an explicit or implicit superclass constructor invocation if V is [un]assigned after the rightmost instance initializer or instance variable initializer of C.
So in second case the value x is definitely assigned at the beginning of the constructor, because it contains the assignment at the end of it.
If you don't initialize x you'll get a compile-time error since x is never initialized.
Declaring x as final means that it can be initialized only in the constructor or in initializer-block (since this block will be copied by the compiler into every constructor).
The reason that you get 0 printed out before the variable is initialized is due to the behavior defined in the manual (see: "Default Values" section):
Default Values
It's not always necessary to assign a value when a field is declared.
Fields that are declared but not initialized will be set to a
reasonable default by the compiler. Generally speaking, this default
will be zero or null, depending on the data type. Relying on such
default values, however, is generally considered bad programming
style.
The following chart summarizes the default values for the above data
types.
Data Type Default Value (for fields)
--------------------------------------
byte 0
short 0
int 0
long 0L
float 0.0f
double 0.0d
char '\u0000'
String (or any object) null
boolean false
The first error is the compiler complaining that you have a final field, but no code to initialize it - simple enough.
In the second example, you have code to assign it a value, but the sequence of execution means you reference the field both before and after assigning it.
The pre-assigned value of any field is the default value.
All non-final fields of a class initialize to a default value (0 for nummeric data types, false for boolean and null for reference types, sometimes called complex objects). These fields initialize before a constructor (or instance initialization block) executes independent of whether or not the fields was declared before or after the constructor.
Final fields of a class has no default value and must be explicitly initialized just once before a class constructor has finished his job.
Local variables on the inside of an execution block (for example, a method) has no default value. These fields must be explicitly initialized before their first use and it doesn't matter whether or not the local variable is marked as final.
Let me put it in the simplest words I can.
final variables need to be initialized, this is mandated by the Language Specification.
Having said that, please note that it is not necessary to initialize it at the time of declaration.
It is required to initialize that before the object is initialized.
We can use initializer blocks to initialize the final variables. Now, initializer blocks are of two types
static and non-static
The block you used is a non-static initializer block. So, when you create an object, Runtime will invoke constructor and which in turn will invoke the constructor of the parent class.
After that, it will invoke all the initializers (in your case the non-static initializer).
In your question, case 1: Even after the completion of initializer block the final variable remains un-initialized, which is an error compiler will detect.
In case 2: The initializer will initialize the final variable, hence the compiler knows that before the object is initialized, the final is already initialized. Hence, it will not complain.
Now the question is, why does x takes a zero. The reason here is that compiler already knows that there is no error and so upon invocation of init method all the finals will be initialized to defaults, and a flag set that they can change upon actual assignment statement similar to x=7.
See the init invocation below:
As far as I'm aware, the compiler will always initialize class variables to default values (even final variables). For example, if you were to initialize an int to itself, the int would be set to its default of 0. See below:
class Test {
final int x;
{
printX();
x = this.x;
printX();
}
Test() {
System.out.println("const called");
}
void printX() {
System.out.println("Here x is " + x);
}
public static void main(String[] args) {
Test t = new Test();
}
}
The above would print the following:
Here x is 0
Here x is 0
const called
If I try to execute it, i am getting compiler error as : variable x might not have been initialized based on java default values i should get the below output right??
"Here x is 0".
No. You are not seeing that output because you are getting a compile-time error in the first place. Final variables do get a default value, but the Java Language Specification (JLS) requires you to initialize them by the end of the constructor (LE: I'm including initialization blocks here), otherwise you'll get a compile-time error which will prevent your code to be compiled and executed.
Your second example respects the requirement, that's why (1) your code compiles and (2) you get the expected behaviour.
In the future try to familiarize yourself with the JLS. There's no better source of information about the Java language.
I am getting confused with below code I expected that it will give an error or answer will be 10 but it is giving 20 how?
public class test {
public static void main(String[] args) {
System.out.println(x);
}
static{
x=10;
}
static int x=20;
}
It's specified in section 12.4.2 of the JLS, which gives details of class initialization:
Next, execute either the class variable initializers and static initializers of the class, or the field initializers of the interface, in textual order, as though they were a single block.
The variable initializer (x = 20) occurs after the static initializer (the block containing x = 10) in the program text. The value at the end of initialization is therefore 20.
If you swap the order round so that the variable initializer comes first, you'll see 10 instead.
I'd strongly advise you to avoid writing code which relies on textual ordering if possible though.
EDIT: The variable can still be used in the static initializer because it's in scope - just like you can use an instance variable in a method declared earlier than the variable. However, section 8.3.2.3 gives some restrictions on this:
The declaration of a member needs to appear textually before it is used only if the member is an instance (respectively static) field of a class or interface C and all of the following conditions hold:
The usage occurs in an instance (respectively static) variable initializer of C or in an instance (respectively static) initializer of C.
The usage is not on the left hand side of an assignment.
The usage is via a simple name.
C is the innermost class or interface enclosing the usage.
It is a compile-time error if any of the four requirements above are not met.
So if you change your static initializer to:
static {
System.out.println(x);
}
then you'll get an error.
Your existing static initializer uses x in a way which does comply with all of the restrictions, however.
in static if a value is changed once then it will be effected through out.
So you are getting 20.
if you write this way
public class test {
static int x=20;
public static void main(String[] args) {
System.out.println(x);
}
static{
x=10;
}
}
then it will print 10.
I'm always confused between static and final keywords in java.
How are they different ?
The static keyword can be used in 4 scenarios
static variables
static methods
static blocks of code
static nested class
Let's look at static variables and static methods first.
Static variable
It is a variable which belongs to the class and not to object (instance).
Static variables are initialized only once, at the start of the execution. These variables will be initialized first, before the initialization of any instance variables.
A single copy to be shared by all instances of the class.
A static variable can be accessed directly by the class name and doesn’t need any object.
Syntax: Class.variable
Static method
It is a method which belongs to the class and not to the object (instance).
A static method can access only static data. It can not access non-static data (instance variables) unless it has/creates an instance of the class.
A static method can call only other static methods and can not call a non-static method from it unless it has/creates an instance of the class.
A static method can be accessed directly by the class name and doesn’t need any object.
Syntax: Class.methodName()
A static method cannot refer to this or super keywords in anyway.
Static class
Java also has "static nested classes". A static nested class is just one which doesn't implicitly have a reference to an instance of the outer class.
Static nested classes can have instance methods and static methods.
There's no such thing as a top-level static class in Java.
Side note:
main method is static since it must be be accessible for an application to run before any instantiation takes place.
final keyword is used in several different contexts to define an entity which cannot later be changed.
A final class cannot be subclassed. This is done for reasons of security and efficiency. Accordingly, many of the Java standard library classes are final, for example java.lang.System and java.lang.String. All methods in a final class are implicitly final.
A final method can't be overridden by subclasses. This is used to prevent unexpected behavior from a subclass altering a method that may be crucial to the function or consistency of the class.
A final variable can only be initialized once, either via an initializer or an assignment statement. It does not need to be initialized at the point of declaration: this is called a blank final variable. A blank final instance variable of a class must be definitely assigned at the end of every constructor of the class in which it is declared; similarly, a blank final static variable must be definitely assigned in a static initializer of the class in which it is declared; otherwise, a compile-time error occurs in both cases.
Note: If the variable is a reference, this means that the variable cannot be re-bound to reference another object. But the object that it references is still mutable, if it was originally mutable.
When an anonymous inner class is defined within the body of a method, all variables declared final in the scope of that method are accessible from within the inner class. Once it has been assigned, the value of the final variable cannot change.
static means it belongs to the class not an instance, this means that there is only one copy of that variable/method shared between all instances of a particular Class.
public class MyClass {
public static int myVariable = 0;
}
//Now in some other code creating two instances of MyClass
//and altering the variable will affect all instances
MyClass instance1 = new MyClass();
MyClass instance2 = new MyClass();
MyClass.myVariable = 5; //This change is reflected in both instances
final is entirely unrelated, it is a way of defining a once only initialization. You can either initialize when defining the variable or within the constructor, nowhere else.
note A note on final methods and final classes, this is a way of explicitly stating that the method or class can not be overridden / extended respectively.
Extra Reading
So on the topic of static, we were talking about the other uses it may have, it is sometimes used in static blocks. When using static variables it is sometimes necessary to set these variables up before using the class, but unfortunately you do not get a constructor. This is where the static keyword comes in.
public class MyClass {
public static List<String> cars = new ArrayList<String>();
static {
cars.add("Ferrari");
cars.add("Scoda");
}
}
public class TestClass {
public static void main(String args[]) {
System.out.println(MyClass.cars.get(0)); //This will print Ferrari
}
}
You must not get this confused with instance initializer blocks which are called before the constructor per instance.
The two really aren't similar. static fields are fields that do not belong to any particular instance of a class.
class C {
public static int n = 42;
}
Here, the static field n isn't associated with any particular instance of C but with the entire class in general (which is why C.n can be used to access it). Can you still use an instance of C to access n? Yes - but it isn't considered particularly good practice.
final on the other hand indicates that a particular variable cannot change after it is initialized.
class C {
public final int n = 42;
}
Here, n cannot be re-assigned because it is final. One other difference is that any variable can be declared final, while not every variable can be declared static.
Also, classes can be declared final which indicates that they cannot be extended:
final class C {}
class B extends C {} // error!
Similarly, methods can be declared final to indicate that they cannot be overriden by an extending class:
class C {
public final void foo() {}
}
class B extends C {
public void foo() {} // error!
}
static means there is only one copy of the variable in memory shared by all instances of the class.
The final keyword just means the value can't be changed. Without final, any object can change the value of the variable.
final -
1)When we apply "final" keyword to a variable,the value of that variable remains constant.
(or)
Once we declare a variable as final.the value of that variable cannot be changed.
2)It is useful when a variable value does not change during the life time of a program
static -
1)when we apply "static" keyword to a variable ,it means it belongs to class.
2)When we apply "static" keyword to a method,it means the method can be accessed without creating any instance of the class
Think of an object like a Speaker. If Speaker is a class, It will have different variables such as volume, treble, bass, color etc. You define all these fields while defining the Speaker class. For example, you declared the color field with a static modifier, that means you're telling the compiler that there is exactly one copy of this variable in existence, regardless of how many times the class has been instantiated.
Declaring
static final String color = "Black";
will make sure that whenever this class is instantiated, the value of color field will be "Black" unless it is not changed.
public class Speaker {
static String color = "Black";
}
public class Sample {
public static void main(String args[]) {
System.out.println(Speaker.color); //will provide output as "Black"
Speaker.color = "white";
System.out.println(Speaker.color); //will provide output as "White"
}}
Note : Now once you change the color of the speaker as final this code wont execute, because final keyword makes sure that the value of the field never changes.
public class Speaker {
static final String color = "Black";
}
public class Sample {
public static void main(String args[]) {
System.out.println(Speaker.color); //should provide output as "Black"
Speaker.color = "white"; //Error because the value of color is fixed.
System.out.println(Speaker.color); //Code won't execute.
}}
You may copy/paste this code directly into your emulator and try.
Easy Difference,
Final : means that the Value of the variable is Final and it will not change anywhere. If you say that final x = 5 it means x can not be changed its value is final for everyone.
Static : means that it has only one object. lets suppose you have x = 5, in memory there is x = 5 and its present inside a class. if you create an object or instance of the class which means there a specific box that represents that class and its variables and methods. and if you create an other object or instance of that class it means there are two boxes of that same class which has different x inside them in the memory. and if you call both x in different positions and change their value then their value will be different. box 1 has x which has x =5 and box 2 has x = 6. but if you make the x static it means it can not be created again.
you can create object of class but that object will not have different x in them.
if x is static then box 1 and box 2 both will have the same x which has the value of 5. Yes i can change the value of static any where as its not final. so if i say box 1 has x and i change its value to x =5 and after that i make another box which is box2 and i change the value of box2 x to x=6. then as X is static both boxes has the same x. and both boxes will give the value of box as 6 because box2 overwrites the value of 5 to 6.
Both final and static are totally different. Final which is final can not be changed. static which will remain as one but can be changed.
"This is an example. remember static variable are always called by their class name. because they are only one for all of the objects of that class. so
Class A has x =5, i can call and change it by A.x=6; "
Static and final have some big differences:
Static variables or classes will always be available from (pretty much) anywhere. Final is just a keyword that means a variable cannot be changed. So if had:
public class Test{
public final int first = 10;
public static int second = 20;
public Test(){
second = second + 1
first = first + 1;
}
}
The program would run until it tried to change the "first" integer, which would cause an error. Outside of this class, you would only have access to the "first" variable if you had instantiated the class. This is in contrast to "second", which is available all the time.
Static is something that any object in a class can call, that inherently belongs to an object type.
A variable can be final for an entire class, and that simply means it cannot be changed anymore. It can only be set once, and trying to set it again will result in an error being thrown. It is useful for a number of reasons, perhaps you want to declare a constant, that can't be changed.
Some example code:
class someClass
{
public static int count=0;
public final String mName;
someClass(String name)
{
mname=name;
count=count+1;
}
public static void main(String args[])
{
someClass obj1=new someClass("obj1");
System.out.println("count="+count+" name="+obj1.mName);
someClass obj2=new someClass("obj2");
System.out.println("count="+count+" name="+obj2.mName);
}
}
Wikipedia contains the complete list of java keywords.
I won't try to give a complete answer here. My recommendation would be to focus on understanding what each one of them does and then it should be cleare to see that their effects are completely different and why sometimes they are used together.
static is for members of a class (attributes and methods) and it has to be understood in contrast to instance (non static) members. I'd recommend reading "Understanding Instance and Class Members" in The Java Tutorials. I can also be used in static blocks but I would not worry about it for a start.
final has different meanings according if its applied to variables, methods, classes or some other cases. Here I like Wikipedia explanations better.
Static variable values can get changed although one copy of the variable traverse through the application, whereas Final Variable values can be initialized once and cannot be changed throughout the application.