# Understanding final in Java

Compile-time initialization:

1. Final variables initialized at declaration:
    

```java
public class Example {
    final int COMPILE_TIME_CONSTANT = 10;
}
```

This is resolved at compile-time and the value is embedded directly in the bytecode.

2. Static final variables with constant expressions:
    

```java
public class Example {
    static final int DAYS_IN_WEEK = 7;
    static final String PREFIX = "user_";
}
```

These are also resolved at compile-time and treated as compile-time constants.

Runtime initialization:

1. Final instance variables in constructors:
    

```java
public class Example {
    final int runtimeValue;
    
    public Example(int value) {
        this.runtimeValue = value;
    }
}
```

The value is set when an object is created, allowing different instances to have different values.

2. Final variables in instance initializer blocks:
    

```java
public class Example {
    final int runtimeValue;
    
    {
        runtimeValue = someMethod();
    }
    
    private int someMethod() {
        return 42;
    }
}
```

This allows for more complex initialization logic at runtime.

3. Static final variables with non-constant expressions:
    

```java
public class Example {
    static final int RANDOM_NUMBER = new Random().nextInt(100);
}
```

This is initialized when the class is loaded, but the value is determined at runtime.

Remember, once a final variable is initialized, whether at compile-time or runtime, its value cannot be changed. The key difference is that runtime initialization allows for more flexibility in determining the initial value, while compile-time constants are fixed and known at compile-time.

Good luck and happy coding 🐦
