What is the difference between final and effectively final?

effectively final introduced in Java 8 with Lambda Expression. Technically there is no difference between final and effectively final.

What is final?
Any variable marked with final can't be modified.

What is effectively final?
Any variable outside of Lambda Expression, initialized only once in scope of variable(in method) then it is called effectively final variable and can be used in Lambda Expression. Its similar to final variable, the difference is you don't have to specify(use) final keyword in front of variable(initialized only once) when you want to use it in Lambda Expression.

Source code

import java.util.ArrayList;
import java.util.List;
public class EffectiveFinal {
public static void main(String[] args) {
/* String marked with `final` that you can't change once initialized */
final String Firstname = "Vicky";
/* Using `final` String in Runnable interface or any anonymous class */
Thread thread = new Thread(new Runnable() {
@Override
public void run() {
System.out.println("Thread: " + Firstname);
}
});
/* Start the thread to display value of Firstname */
thread.start();
/* Code for Lambda Expression */
/* Create List of Strings */
List>String> listStrings = new ArrayList>String>();
listStrings.add("Vicky");
listStrings.add("Chirag");
/**
* Any variable outside of Lambda Expression, initialized only once in scope of variable(in whole program) then its `effectively final` variable.
*
* In this program `Lastname` is effectively final variable as it is initialized only once and can be used in Lambda Expression.
* Note: You can also mark `Lastname` as final and then you can use it in Lambda Expression.
*/
String Lastname = "Thakor";
/**
* If you re-initialize or modify value of `Lastname` then you can't use it in Lambda Expression.
* Lastname = "Stark"; OR Lastname = ""; OR Lastname += " ";
*/
//Lastname += " ";
/* Lastname is used in following Lambda Expression */
listStrings.stream()
.forEach(str -> System.out.println("Lambda Expression: " + str + " " + Lastname));

Code ExplanationPart 1: We all used Runnable interface. And as you know the rule for anonymous class in Java, that variable declared outside the scope of Runnable interface should be final. If you try to use non-final variable declared outside the scope of Runnable then compiler will throw an error Cannot refer to a non-final variable Firstname inside an inner class defined in a different method

Part 2: To use Lambda Expression we created List of String. We've variable Lastname that is initialized only once in program so it is called effectively final variable and can be used inside Lambda Expression.
- If you uncomment the line Lastname += " "; then compiler will throw an error local variables referenced from a lambda expression must be final or effectively final