1. Access Specifiers
An access specifier determines how accessible fields, methods and classes are to code in other classes.
Types of Access Specifiers
public
Public classes, methods and fields can be accessed from everywhere.
protected
Protected methods and fields can be accessed within the same class, within subclasses and within classes of the same package.
default
If no access level is specified, the member is accessible from inside the same package, but not from outside the package.
private
Private members are accessible within the same class only.
default access).2. Access Modifiers
Access modifiers control what information or data can be accessed by other classes and provide additional definitions to classes, methods, data members or blocks.
Modifiers Covered in the Notes
Where the Modifiers Can Be Applied
| Modifier | Block | Member Function | Data Member | Class |
|---|---|---|---|---|
| final | ✗ | ✓ | ✓ | ✓ |
| static | ✓ | ✓ | ✓ | Exceptional |
| abstract | ✗ | ✓ | ✗ | ✓ |
| synchronized | ✓ | ✓ | ✗ | ✗ |
| native | ✗ | ✓ | ✗ | ✗ |
| transient | ✗ | ✗ | ✓ | ✗ |
| volatile | ✗ | ✗ | ✓ | ✗ |
Overloading and Overriding
| Modifier | Overload | Override |
|---|---|---|
| final | Yes | No |
| static | Yes | No |
| abstract | Yes | Yes |
| synchronized | Yes | Yes |
| native | Yes | Yes |
3. final
The final modifier can be applied to data members, member functions and classes.
- A
finalvariable cannot be changed during program execution after it has been assigned. - A
finalmethod cannot be overridden. - A
finalclass cannot be inherited.
How do you prevent inheritance in Java?
- Place
finalon the class. - Use a private constructor where appropriate.
Final Example
public final class FinalExample1 {
final int MAX_COUNT = 10;
int b;
FinalExample1() {
}
public FinalExample1(int b) {
this.b = b;
}
void display() {
int a = this.MAX_COUNT + 10;
System.out.println(a);
b = b * b;
System.out.println(b);
}
public void display(int c) {
int b = this.a; // as illustrated in the source notes
System.out.println(b);
}
public static void main(String[] args) {
FinalExample1 obj = new FinalExample1(14);
obj.b = 21;
System.out.println(obj.b);
obj.display();
obj.display(5);
}
}
final on a variable prevents reassignment, on a method prevents overriding, and on a class prevents inheritance.4. static
static can be applied to data members, member functions and blocks.
- Static data members are not duplicated for every object like normal instance data members.
- A static variable is stored in a common class-level location and is shared by objects of the class.
- Static data members are also called class variables.
- Static methods belong to the class and can be called using the class name without creating an object.
- A static method cannot directly use instance data members or instance methods.
- Static methods cannot use
thisorsuper. - Static methods are resolved at compile time and therefore cannot be overridden; a same-signature static method in a subclass is method hiding.
- Abstract methods cannot be static.
Access Rules
| Member Type | What it can directly access |
|---|---|
| Instance methods | Instance methods and instance variables. |
| Static methods | Static variables and other static methods. |
| Static methods | Cannot directly access instance variables or instance methods; an object reference is required. |
5. Static Initialization Blocks
A static block is a set of statements inside { } declared as static. It is executed when the class is loaded.
Static Initialization Block Example
public class Mainclass {
static int[] values = new int[10];
static {
System.out.println("Running initialization block:");
for (int i = 0; i < values.length; i++) {
values[i] = (int) (100.0 * Math.random());
}
}
void listValues() {
for (int value : values) {
System.out.println(value);
}
}
public static void main(String[] args) {
Mainclass example = new Mainclass();
System.out.println("\nFirst object:");
example.listValues();
example = new Mainclass();
System.out.println("\nSecond object:");
example.listValues();
}
}
Explicit Static Initialization
public class MyClass {
MyClass(int marker) {
System.out.println("Cup(" + marker + ")");
}
void f(int marker) {
System.out.println("f(" + marker + ")");
}
}
class MyStatic {
static MyClass c1;
static MyClass c2;
static {
c1 = new MyClass(1);
c2 = new MyClass(2);
}
MyStatic() {
System.out.println("Cups()");
}
}
Static Initialization Order
The source includes an example demonstrating the pitfalls of depending on the order of static initializers. Static initialization can trigger initialization of referenced classes and their static members.
public class StaticOrderDemo {
static {
Class<?> cl = Values.class;
System.out.println("Class " + cl.getName() + " Loaded");
}
public static final void main(final String[] args) {
}
public static class Ranges {
public static final String[] RANGE_BLUE = {"Sky", "Navy"};
public static final String[] RANGE_RED = {"Light", "Dark"};
static {
System.out.println("static{} method for Ranges");
System.out.println(Arrays.asList(RANGE_BLUE));
System.out.println(Values.VALUE_SPECIFIER);
System.out.println(Arrays.asList(RANGE_RED));
}
}
public static class Values {
public static final String VALUE = "Blue";
public static final String VALUE_SPECIFIER;
static {
System.out.println("static{} method for Values");
System.out.println(VALUE);
System.out.println(Ranges.RANGE_BLUE);
VALUE_SPECIFIER = Ranges.RANGE_BLUE[1];
}
}
}
6. abstract
The abstract modifier can be applied to methods and classes.
- A function that is declared without a definition is an abstract method.
- If a class contains at least one abstract method, the class must be declared abstract.
- An abstract class cannot be instantiated directly.
- Abstract methods are intended to be implemented by subclasses.
Abstract Example
public abstract class AbstractDemo {
public AbstractDemo() {
}
public abstract void disp();
public abstract void disp(int a);
public static void main(String[] args) {
// AbstractDemo cannot be instantiated directly.
}
}
Implementation
public class AbstractDemoImpl extends AbstractDemo {
@Override
public void disp() {
System.out.println("This is definition of Abstract method disp");
}
@Override
public void disp(int a) {
int b = a;
System.out.println("b value is " + b);
}
public static void main(String[] args) {
AbstractDemoImpl obj = new AbstractDemoImpl();
obj.disp();
obj.disp(5);
AbstractDemo obj1 = new AbstractDemoImpl();
}
}
7. native
The native keyword is used with methods as a modifier when the implementation is written in another language.
- A native method allows Java code to interact with native/platform-specific code.
- When a method is native, the Java program is no longer completely platform-independent.
- The source notes describe native code being converted into a DLL that can be linked dynamically at runtime.
- The source states that if a superclass method is native, the overriding method must also be native.
public abstract class AbstractDemo {
public AbstractDemo() {
}
public native void sup();
}
8. transient
transient is a Java modifier used mainly with fields that should not participate in normal Java serialization.
The source notes discuss its use in distributed environments such as EJB, RMI and CORBA, where a variable may be excluded from transport through remote objects.
public class UMSAdobeUsagePart {
private static final long serialVersionUID = 1L;
private transient BusinessKey businessKey;
private UMSAdobeUsagePartPK id;
@Transient
private Boolean isDefault;
@Transient
private String selectedPeakMonthYear;
}
9. volatile
volatile is a Java modifier used with variables that may be accessed or changed by multiple threads.
- A volatile variable may change unexpectedly as different threads access shared state.
- Without appropriate visibility guarantees, threads may maintain their own copies of a shared value.
volatiletells the JVM that reads should observe the current shared value rather than relying on a stale thread-local view.
volatile vs synchronized
- A primitive variable may be declared volatile, whereas you cannot synchronize on a primitive.
- Access to a volatile variable does not acquire a lock and therefore does not block in the way a synchronized block can.
- Volatile is not sufficient for compound read-update-write operations that must be atomic.
- A volatile object reference may be null; attempting to synchronize on a null object causes
NullPointerException.
volatile Example
public class snippet1 implements Runnable {
volatile int num = 0;
public void run() {
Thread t = Thread.currentThread();
String name = t.getName();
if (name.equals("Thread1")) {
num = 10;
} else {
System.out.println("value of num is :" + num);
}
}
public static void main(String args[])
throws InterruptedException {
Runnable r = new snippet1();
Thread t1 = new Thread(r);
t1.setName("Thread1");
t1.start();
Thread.sleep(1000);
Thread t2 = new Thread(r);
t2.setName("Thread2");
t2.start();
}
}
10. synchronized
Synchronization is the capability to control access by multiple threads to a shared resource.
The source notes summarize the goal as preventing two threads from executing the synchronized critical section concurrently.
synchronized is used for thread coordination and mutual exclusion, while volatile is primarily about visibility of shared variable updates.11. Quick Revision
| Topic | Key Point |
|---|---|
| public | Accessible from everywhere, subject to Java's class/package rules. |
| protected | Accessible within the package and through subclasses. |
| default | Accessible within the same package when no access modifier is specified. |
| private | Accessible within the declaring class only. |
| final | Prevents reassignment, overriding or inheritance depending on where it is applied. |
| static | Belongs to the class rather than an individual object. |
| abstract | Used for incomplete method definitions and abstract classes. |
| synchronized | Controls concurrent access to shared resources. |
| native | Declares a method implemented in native code. |
| transient | Excludes a field from normal Java serialization. |
| volatile | Provides visibility semantics for shared variables across threads. |