static
keyword.class Test1 { int var1 = 1; // instance fields (unique to each instance) static int var2 = 1; // class fields public Test1() { Integer localVar1; // Access fields localVar1 = var1; // OK localVar1 = var2; // OK // Access fields using an instance reference localVar1 = (new Test1()).var1; // OK localVar1 = (new Test1()).var2; // OK - Warning: The static field Test1.var2 should be accessed in a static way // Access fields using the class name localVar1 = Test1.var1; // compiler error: Cannot make a static reference to the non-static field Test1.var1 localVar1 = Test1.var2; // OK } public void doSomething() { Integer localVar1; // Access fields localVar1 = var1; // OK localVar1 = var2; // OK // Access fields using an instance reference localVar1 = (new Test1()).var1; // OK localVar1 = (new Test1()).var2; // OK - Warning: The static field Test1.var2 should be accessed in a static way // Access fields using the class name localVar1 = Test1.var1; // compiler error: Cannot make a static reference to the non-static field Test1.var1 localVar1 = Test1.var2; // OK } public static void doSomethingElse() { Integer localVar1; // Access fields localVar1 = var1; // compiler error: Cannot make a static reference to the non-static field var1 localVar1 = var2; // OK // Access fields using an instance reference localVar1 = (new Test1()).var1; // OK localVar1 = (new Test1()).var2; // OK - Warning: The static field Test1.var2 should be accessed in a static way // Access fields using the class name localVar1 = Test1.var1; // compiler error: Cannot make a static reference to the non-static field Test1.var1 localVar1 = Test1.var2; // OK } }
public
: Accessible from anywhere.private
: Accessible only within the same class.protected
: Accessible within the same package and by subclasses.final
fields cannot be reassigned after initialization.class Test2 { // Final field initialized at declaration final int CONSTANT = 1; // Final field to be initialized in constructor final int var1; // Static final field (compile-time constant) static final int var2 = 1; // Final object reference (object can be modified, reference cannot) final List<String> list1 = new ArrayList<>(); // Compiler error if var1 not initialized: The blank final field var3 may not have been initialized public Test2() { this.var1 = 1; // must initialize final field in constructor } public void doSomething() { CONSTANT = 200; // Compiler error: The final field Test2.CONSTANT cannot be assigned var1 = 1; // Compiler error: The final field Test2.var1 cannot be assigned list1 = new ArrayList<>(); // Compiler error: The final field Test2.list1 cannot be assigned // can modify the object that final reference points to list1.add("Item 1"); // OK list1.add("Item 2"); // OK } }
this
keyword to access instance fields when shadowed.class Test3 { int var1 = 1; static int var2 = 1; public void doSomething() { int var1 = 2; // local variable shadows the instance field System.out.println(var1); // prints local variable var1 (2) System.out.println(new Test3().var1); // prints instance field var1 (1) int var2 = 2; // local variable shadows the static field System.out.println(var2); // prints local variable var2 (2) System.out.println(Test3.var2); // prints static field var2 (1) } } class Test4 extends Test3 { int var1 = 10; // shadows parent field static int var2 = 10; // shadows parent field public void doSomethingElse() { System.out.println(var1); // prints child instance field var1 (10) System.out.println(super.var1); // prints parent instance field var1 (1) System.out.println(var2); // prints child static field var2 (10) System.out.println(super.var2); // prints parent static field var2 (1) } }