Inner or nested classes in java
Published: 2021-11-09 09:45:48

<b>An inner class</b> is a class that is declared inside a class or interface. Inner classes are used to logically group classes or interfaces in one place in order to improve readability and maintainability.
<b>Syntax of inner class</b>
```java
class X1{
// code
  class X2{
      // code
    }
}
```
<b>Advantages of using inner classes</b>
1. Because inner classes logically group classes and interfaces in one place only, they improve readability and maintainability.
2. minimises coding efforts since there is less code to write thus facilitating code optimisation.
3. Inner classes are a representation of a particular type of relationship in that an inner class can access all the members(data members and methods) of an outer class including one declared private.

<b>Why need an inner class?</b>
There might be a program where a class must not be accessed by other class so in that case, you include it in another class.

<b>Types of inner classes</b>
There are 4 types of nested/inner classes i.e member(nested inner class), static member(static nested class), anonymous inner class and local inner class.
<b>A) Static member inner classes</b>
A static member inner class is an inner class which is declared static. 
<b>Syntax for a static inner class</b>
```java
  class MainClass {
    // code
    static class StaticInnerClass{
     // code
    }
}
```
In the above code snippet, StaticInnerClass is a static inner class.
This class can't refer directly to their instance variables or methods defined in its enclosing class since they use them only by an object reference. They are accessed by the use of class name.
<b>Note: Syntax for creating an object of a static inner class</b>
```
MainClass.StaticInnerClass objectname 
= new MainClass.StaticInnerClass();
```
<b>Example:</b>
```java
 class A{
  static String parent_name = "A";
  static class B{
    void whoami(){
      System.out.print("I am static inner class B
          and my parent class is"+parent_name);
     }
  }
 public static void main(String[] args)  
      {  
        A.B obj = new A.B();  
        obj.whoami();  
      }
}
```
<b>Output</b>
```
I am static inner class B and my parent class is A
```
In the above example, B is a static inner class and an instance method like <b>whoami()</b> is accessed by using class name <b>B</b>.

<b>B. Member inner class</b>
A member inner class is a class created within a class and outside a method. A member inner class is non-static.
A member inner class refers directly to its instance variables or methods defined in its enclosing class. Also, because an inner class is associated with an instance, it cannot define any static members itself.
<b>Syntax for a member inner class</b>
```java
class MainClass
  {
    // code
    class InnerClass
      {
        // code
      }
  }
```
<b>Note: Syntax for creating an object of a non-static member inner class</b>
```
MainClass m = new MainClass();
MainClass.InnerClass innerObj = m.new InnerClass();
```
<b>Example</b>
```java
class X{
     static String parent_name ="X";
     class Y{
       void message(){
        System.out.println("Hey, I am an non-static inner 
             class Y and my parent class is "+parent_name);
     } 
    }
    
public static void main(String[] args)  
      {  
	    X x = new X();
	    X.Y innerObj = x.new Y();
	    innerObj.message();  
      }
}

```
<b>Output</b>
```
Hey, I am an non-static inner class Y and my parent class is X
```
<b>C. Anonymous inner class</b>
Anonymous inner class is one that is created for implementing an interface or extending a class. Thereafter, anonymous class must implement an interface or extend an abstract class but you don't use keywords <b>extend</b> or <b>implement</b> to create anonymous class.
<b>Syntax for creating anonymous class</b>
```
new interface-or-class-name{
  // code
}
```
<b>Example:</b>
```java
import java.util.Random;

public class AnonymousClassExample {
	
	interface Food{
		public void choose();
		public void whichFood();
	}
	
	public void eat() {
	
		// Anonymous class
  Food birdsFoodPreference = new Food() {
		public void choose() {
			whichFood();
		}
        public void whichFood() {
     String [] foodItems = {"Insects", "Maize", "G.nuts"};
      System.out.println("Birds like eating 
                         "+getRandomFoodChoice(foodItems));
	}
	};
	
	// Anonymous class
	Food MansFoodPreference = new Food() {
		public void choose() {
			whichFood();
		}
        public void whichFood() {
   String [] foodItems = {"Meat", "Posho", "Rice"};
    System.out.println("Man likes eating 
                   "+getRandomFoodChoice(foodItems));
		}
	};
	
	birdsFoodPreference.choose();
	MansFoodPreference.choose();
	
	}

	public static void main(String[] args) {
AnonymousClassExample app = new AnonymousClassExample();
app.eat();

	}
	
	public static String getRandomFoodChoice(String[] array) {
	    int rnd = new Random().nextInt(array.length);
	    return array[rnd];
	}

}
```
<b>Output</b>
```
Birds like eating Insects
Man likes eating Posho
```
<b>Key facts about anonymous inner classes</b>
1. Anonymous class cannot have a constructor. Thus, you cannot pass parameters to an anonymous class when you instantiate it.
2. Anonymous class can access any variables visible to the block within which anonymous class is declared, including local variables.
3. Anonymous class can also access methods of a class that contains it.

<b>D. Local inner class</b> 
A local class is a class that is 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.
<Example>
```java
import java.util.*;
public class Bank {
	
	public static void getTotalPayable(String bank, 
              double principal, int years) {
		
		// local class named Interest
		 class Interest{
		   double bank_interest_rate = 0.0;
			 
	           Interest(String bank){
	             switch (bank) {
	               case "Centenary":
	                  bank_interest_rate = 3.2;
	                  break;
	               case "Stanbic":
                         bank_interest_rate = 2.8;
	                 break;
	               case "Equity":
                         bank_interest_rate = 3.15;
	                 break;
                       default:
                         bank_interest_rate = 1.5;
	}
				 
	}
// method in local class that returns interest
	public double getInterestRate() {
	 return bank_interest_rate;
	}
			 
 }
		 
Interest obj = new Interest(bank);
double amount = Math.round(principal*
               (1 + (obj.getInterestRate()*years)));
		 
System.out.println("The total amount payable
 for principal "+principal+" after
 "+years+" years in "+bank+" bank
 whose interest is "+obj.getInterestRate()+"
 is "+amount);
			 
 }
		 
		
	public static void main(String[] args) {
		double amt = 100000;
		int years = 3;
		getTotalPayable("Centenary", amt, years);
		getTotalPayable("Stanbic", amt, years);
		getTotalPayable("Equity", amt, years);

	}

}
```
<b>Output</b>
```
The total amount payable for principal 100000.0 after 3 years in Centenary bank whose interest is 3.2 is 1060000.0
The total amount payable for principal 100000.0 after 3 years in Stanbic bank whose interest is 2.8 is 940000.0
The total amount payable for principal 100000.0 after 3 years in Equity bank whose interest is 3.15 is 1045000.0
```
So that's the concept of inner classes in java, thank you to taking time to read through this post. See you in the next one!