For my own review…

Nested classes are divided into two categories: static and non-static. Nested classes that are declared static are called static nested classes.

Static Nested Class

1
2
3
4
5
6
class TestOuter1 {    
    static int data = 30;    
    static class Inner {    
        void msg() { System.out.println("data is " + data); }
    }    
}

A static nested class is behaviorally a top-level class that has been nested in another top-level class for packaging convenience.

Inner Class

Non-static nested classes are called inner classes

As with instance methods and variables, an inner class is associated with an instance of its enclosing class and has direct access to that object’s methods and fields. Also, because an inner class is associated with an instance, it cannot define any static members itself.

Inner class example:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
class CPU {  
    double price;  
    class Processor{  
        double cores;  
        String manufacturer;  
        double getCache() {  
            return 4.3;  
        }  
    }  
    protected class RAM {  
        double memory;  
        String manufacturer;  
        double getClockSpeed() {  
            return 5.5;  
        }  
    }  
}

Local Class

Local classes are classes that are defined in a block, which is a group of zero or more statements between balanced braces. You typically find local classes defined in the body of a method.

Local class example:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
public class Outer {  

    public int data = 10;  

    public int getData() {  
        return data;  
    }  

    public static void main(String[] args) {  
        Outer outer = new Outer();  

        if (outer.getData() < 20) {  
            // Local inner class inside if clause   
            class Inner {  

                public int getValue() {  
                    System.out.println("Inside Inner class");  
                    return outer.data;  
                }  
            }  

            Inner inner = new Inner();  
            System.out.println(inner.getValue());  
        } else {  
            System.out.println("Inside Outer class");  
        }  
    }  
}

Anonymous Class

Anonymous classes: While local classes are class declarations, anonymous classes are expressions, which means that you define the class in another expression.

Anonymous class example (extending a class):

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
public class AnonymousExample {  

    public static void main(String[] args) {  
        //anonymous class inside method  
        Hello h = new Hello("abc") {  

            @Override  
            public void sayHello() {  
                System.out.println("Hello anonymous class " + s);  
            }  
        };  
        h.sayHello();  
    }  
}

In the above example, Hello looks like this:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
public class Hello {  

    protected String s;  

    public Hello(String str) {  
        this.s = str;  
    }  

    public void sayHello() {  
        System.out.println(s);  
    }  
}

But in my experience, it’s more common for an anonymous class to implement an interface, rather than extend a class.

Anonymous class example (implementing an interface):

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
class AnonymousDemo {  

    public void createClass() {  
        // anonymous class implementing interface  
        Polygon p1 = new Polygon() {  
            public void display() {  
                System.out.println("Inside an anonymous class.");  
            }  
        };  
        p1.display();  
    }  
}

And the interface is this:

1
2
3
4
interface Polygon {  
   public void display();  
}  

Lambdas

Anonymous classes can often be replaced by lambda functions.

Start with a functional interface, such as:

1
2
3
public interface OriginalInterface {  
    void show();  
}

A lambda looks like this:

1
2
3
4
5
6
public class LambdaExpressionExample {  
    public static void main(String[] args) {  
        OriginalInterface object = () -> System.out.println("Implements method functionality");  
        object.show();  
    }  
}