Posts Java Inner Classes
Post
Cancel

Java Inner Classes

  • Inner classes

Method-local inner classes

Anonymous inner classes

Static nested classes

  • Regular Inner class

Regular means that the class is not static, anonymous or method-local.

1
2
3
4
5
class MainClass{
 class InnerClass{
 
 }
} 
  • regular inner class can’t have static declarations of any kind.

  • The only way you can access the inner class is through a live instance of the outer class!

1
2
3
4
5
6
7
8
9
10
class MainClass{
 private int temp=7;

 class InnerClass{
  public void accessOuterClassVariable(){
   System.out.println("accessing outer class variable "+temp);  
  } 
 }

}

As per above example since the inner class is also a member of the outer class, so inner class can access members of outer class.

Example Creating instance of inner class

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
class MainClass{
 private int temp=7;
 
 public void methodThatCreatesInnerClassInstance(){
  InnerClass ic = new InnerClass();
  ic.accessOuterClassVariable(); 
 }

 class InnerClass{
  public void accessOuterClassVariable(){
   System.out.println("accessing outer class variable "+temp);  
  } 
 }

}
  • Accessing inner class from some other class.
1
2
3
4
5
public static void main(String []args){
 MainClass mainClass = new MainClass();
 InnerClass ic = mainClass.new InnerClass();
 ic.accessOuterClassVariable();
}

or

1
2
3
4
public static void main(String []args){
 InnerClass ic = new MainClass().new InnerClass();
 ic.accessOuterClassVariable();
}

If inner class wants to pass reference of outer class to some other class, this can be done by using ‘this’ variable.

But as we know ‘this’ variable always reffers to the current executing object.

So inorder to get OuterClass reference we will use ‘.this'.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
class MainClass{
 private int temp=7;

 class InnerClass{
  public void accessOuterClassVariable(){
   System.out.println("accessing outer class variable "+temp); 
   Test test = new Test(MainClass.this); 
  } 
 }

}

class Test{
 private MainClass mainClass;

 public Test(MainClass mainClass){
  this.mainClass = mainClass;
 }

 ...........
 ... code...
 ...........
}
  • Method Local Inner Class
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
class MainClass{
 private int temp=7;
 
 public void methodThatCreatesInnerClassInstance(){
  InnerClass ic = new InnerClass();
  ic.accessOuterClassVariable(); 
 }

 class InnerClass{
  public void innerClassMethod(){
   int i=0;
   class MethodLocalClass {
    public void methodLocalInnerClassMethod(){
     System.out.println("accessing outer class variable "+temp);
    }  
   }
   MethodLocalClass methodLocalInnerClass = new MethodLocalClass();
   methodLocalInnerClass.methodLocalInnerClassMethod(); 
  }
 }

}

In the above example the MethodLocalClass cannot access innerClassMethod variable ‘i’.

Since the MethodLocalClass obect will be stored in heap, but the innerClassMethod variables will be stored on the stack.

So all the innerClassMethod variables will be destroyed as soon as the method completes.

But one can pass the MethodLocalClass reference and store it in an instance variable, by doing this the class will remain on the heap.

So the method local class cannot access the variables of method in which it is defined since method local class instance can stay on the heap even when the method in which it was declared is destroyed.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24

class MainClass{
 private int temp=7;
 
 public void methodThatCreatesInnerClassInstance(){
  InnerClass ic = new InnerClass();
  ic.accessOuterClassVariable(); 
 }

 class InnerClass{
  public void innerClassMethod(){
   int i=0;
   class MethodLocalClass {
    public void methodLocalInnerClassMethod(){
     System.out.println("accessing outer class variable "+temp);
     System.out.println("accessing method variable "+ i); // illegal code will not compile
    }  
   }
   MethodLocalClass methodLocalInnerClass = new MethodLocalClass();
   methodLocalInnerClass.methodLocalInnerClassMethod(); 
  }
 }

}

If we declare the method variable as ‘final’ then the method local class can access that variable.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
class MainClass{
 private int temp=7;
 
 public void methodThatCreatesInnerClassInstance(){
  InnerClass ic = new InnerClass();
  ic.accessOuterClassVariable(); 
 }

 class InnerClass{
  public void innerClassMethod(){
   final int i = 10;
   class MethodLocalClass {
    public void methodLocalInnerClassMethod(){
     System.out.println("accessing outer class variable "+temp);
     System.out.println("accessing method variable "+ i); // legal code will compile
    }  
   }
   MethodLocalClass methodLocalInnerClass = new MethodLocalClass();
   methodLocalInnerClass.methodLocalInnerClassMethod(); 
  }
 }

}

If local class was declared in a static method then it can only access static variables of the enclosing class.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
class MainClass{
 private int temp=7;
 private static int staticTemp=7;

 public void methodThatCreatesInnerClassInstance(){
  InnerClass ic = new InnerClass();
  ic.accessOuterClassVariable(); 
 }

 class InnerClass{
  public void innerClassMethod(){
   class MethodLocalClass {
    public static void methodLocalInnerClassMethod(){
     System.out.println("accessing outer class variable "+temp); //illegal code will not compile
     System.out.println("accessing outer class variable "+staticTemp); // legal code will compile
    }  
   }
   MethodLocalClass methodLocalInnerClass = new MethodLocalClass();
   methodLocalInnerClass.methodLocalInnerClassMethod(); 
  }
 }

}
  • Anonymous Inner Class
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
29
30
31
32
33
34
35
36
37
class LAN{

 public String getIpAddress(){
  return "10.0.0.5";
 }

 public String getMACAddress(){
  return "66:44:fd:cf:3b:h2";
 }

}

class TestClass{

 public void test(){
  LAN lan = new LAN(){  // anonymous class definition starts from here
   public String getIpAddress(){
    System.out.println(" anonymous class ip ");
    return "127.0.0.1";
   }

   public String getMACAddress(){
    return "66:44:fd:cf:3b:h2";
   }

   public String getState(){
    return "Active";
   }
  }; // this semicolon is mandatory else code will not compile

  System.out.println(" anonymous class  "+lan.getIpAddress());
  System.out.println(" anonymous class  "+lan.getMACAddress());
  System.out.println(" anonymous class  "+lan.getState()); // illegal this method does not exists in actual LAN class.  
  
 }

}

Anonymous inner classes can

  • implement only one interface.
  • it cannot extend and implement at same time.

  • Static Nested Classes

There’s no such thing as a static class. We will still have to create its object.

But by adding static to the class name we can access the class without having to create instance of the outer class.

Since static modifier is used the inner class cannot use non static or instance varaibles of outer class.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
class MainClass{
 private int temp=7;
 private static int staticTemp=7;
 
 public void methodThatCreatesInnerClassInstance(){
  InnerClass ic = new InnerClass();
  ic.accessOuterClassVariable(); 
 }

 static class InnerClass{
  public void accessOuterClassVariable(){
   System.out.println("accessing outer class variable "+temp); //illegal cannot access non static variables
   System.out.println("accessing outer class static variable "+staticTemp); //legal will complie
  } 
 }

}
  • Accessing static inner class from some other class.
1
2
3
4
public static void main(String []args){
 MainClass.InnerClass ic = new MainClass.InnerClass();
 ic.accessOuterClassVariable();
} 
This post is licensed under CC BY 4.0 by the author.