You are on page 1of 22

Inner Class

1. Sometimes we declare a class in another class. Such type of classes are


called inner classes.
2. Inner classes concept introduced in java 1.1 version to fix GUI bugs as
the part of event handling. But because of powerful features and
benefits of inner classes slowly programmers started using in regular
coding also.
3. Without existing one type of object, if there is no chance of existing
another type of object then we should go for inner classes.

Exapmple:

1. University consists of several departments. Without existing


university, there is no chance of existing department. Hence we have to
declare department class inside university class.

package innerClass;

public class University {

class Departement{

2. Without existing car object, there is no chance of existing


engine object. Hence we have to declare engine class inside car
class.

package innerClass;

public class Car {

class Engine{

}
3. Map is a group of key value pairs and each key value pair is
called an entry. Without existing map object, there is no chance
of existing entry object. Hence interface entry is defined inside
map interface.

package innerClass;

public interface Map {

interface Entry{

Note:
1. Without existing outer class object, there is no chance of
existing inner class object.
2. The relation between outer class and inner class is not IS-A
relation but it is HAS-A (composition or aggregation)
relationship.

Types of inner class:


Based on position of declaration and behavior, all inner classes are
divided into four types.
 Normal or regular inner classes
 Method local inner classes
 Anonymous inner classes
 Static nested classes

1. Normal or regular inner classes:


 If we are declaring any named class directly inside a class
without static modifier. Such type of inner class is called
normal/regular inner class.

Example1:

package innerClass;

public class Outer {

class Inner {
}}
Java.outer-----------RE: Main method not found in class
innerClass.Outer

Example2:

package innerClass;

public class Outer {

class Inner {

public static void main(String[] args) {

Output:
main method of outer class

 Inside inner class we can’t declare any static members. Hence we


can’t declare main method and we can’t run inner class directly
from command prompt.

package innerClass;

public class Outer {

class Inner {
public static void main(String[] args) {---Error
System.out.println("main method of outer class");
}
}

Compile time error: inner class can not have static declaration

Case1:
Accessing inner class code from static area of outer class:

package innerClass;

public class Outer {

class Inner {
public void m1() {
System.out.println("inner class instance method");
}
}

public static void main(String[] args) {


Outer o = new Outer();
Outer.Inner i = o.new Inner();
i.m1();
}

Output:
inner class instance method

We can combine the lines:

 public static void main(String[] args) {

Outer.Inner i = new Outer().new Inner();


i.m1();
}

 package innerClass;

public class Outer {

class Inner {
public Inner m1() {
System.out.println("inner class instance method");
return null;
}
}

public static void main(String[] args) {

Outer.Inner i = new Outer().new Inner().m1();


}

}
Case2:

Accessing inner class code from instance area of outer class:

package innerClass;

public class Outer {

class Inner {
public void m1() {
System.out.println("inner class instance method");
}
}

public void m2() {


Inner i = new Inner();
i.m1();
}

public static void main(String[] args) {


Outer o = new Outer();
o.m2();
}

}
Output:
inner class instance method

case3:

Accessing inner class code outside of outer class:

package innerClass;

public class Outer {

class Inner {
public void m1() {
System.out.println("inner class instance method");
}
}

}
package innerClass;

public class Test {


public static void main(String[] args) {
Outer o = new Outer();
Outer.Inner i = o.new Inner();
i.m1();
}
}
Output:
inner class instance method

case4:

 From normal regular inner class we can access both static and
non-static members from outer class directly.

package innerClass;

import innerClass.Outer.Inner;

public class Outer {


int x = 10;
static int y = 20;
class Inner {
public void m1() {
System.out.println(x);
System.out.println(y);

public static void main(String[] args) {


Outer o = new Outer();
Inner i = o.new Inner();
i.m1();
}

 Within the class “this” always refers current inner class object.
If we want to refer current outer class object. We have to use
outer class name.this.
package innerClass;

public class Outer {


int x = 10;

class Inner {
int x = 100;
public void m1() {
int x = 1000;
System.out.println(x);
System.out.println(this.x);
System.out.println(Inner.this.x);
System.out.println(Outer.this.x);

public static void main(String[] args) {


new Outer().new Inner().m1();
}

Output:

1000
100
100
10

 The only applicable modifiers for outer classes are public,


default, final, abstract, strictfp.
 But for inner classes applicable modifiers are public, default,
final, abstract, strictfp, private, protected, static.

Nesting of Inner classes:


1. Inside inner class we can declare another inner class i.e
nesting of inner classes is possible.
package innerClass;

public class Outer {


int x = 10;

class Inner {

class Innermost{
public void m1() {
System.out.println("Innermost class method");
}
}

public static void main(String[] args) {


new Outer().new Inner().new Innermost().m1();
}

Method local Inner classes:


1. Sometimes we can declare a class inside a method. Such types of
inner classes are method local inner classes.
2. The main purpose method local inner class is to define method
specific repeatedly required functionality.
3. Method local inner classes are best suitable to meet nested
method requirements.
4. We can access method local inner classes only within the method
where we declared. Outside of the method we can’t access. Because
of its less scope method local inner classes are most rarely used
type of inner classes.

package innerClass;

public class Outer {

public void m1() {

class Inner {
public void sum(int x, int y) {
System.out.println(x+y);
}

}
Inner i = new Inner();
i.sum(10,20);
i.sum(100, 200);
i.sum(1, 20);

public static void main(String[] args) {


Outer o = new Outer();
o.m1();
}

5. We can declare method local inner class inside both static and
instance methods.
6. If we declare inner class inside instance method then from that
method local inner class we can access both static and non-static
members of outer class directly.
7. If we declare inner class inside static method then from we can
access only static members of outer class directly from that
method local inner class.
package innerClass;

public class Outer {

int x = 10;
static int y = 20;

public void m1() {

class Inner {
public void m2() {
System.out.println(x);-------1
System.out.println(y);
}

}
Inner i = new Inner();
i.m2();

}
public static void main(String[] args) {
Outer o = new Outer();
o.m1();
}
}

If we declare m1() method as static then at line 1 we will get compile time
error saying non static variable x cannot be referenced from a static
context.

From method local inner class we can’t access local variables of the method
in which we declare inner class. If the local variable declared as final then
we can access.

package innerClass;

public class Outer {

public void m1() {


int x = 10;
class Inner {
public void m2() {
System.out.println(x);
}

}
Inner i = new Inner();
i.m2();

}
public static void main(String[] args) {
Outer o = new Outer();
o.m1();
}
}

Compile time error: local variable x is accessed from within inner class;
needs to be declared final.

If we declare x as final then we won’t get any compile time error.

Consider the following code;

package innerClass;

public class Outer {


int x = 10;
static int y = 20;
public void m1() {
int z = 30;
final int a = 40;
class Inner {
public void m2() {
System.out.println(x);
System.out.println(y);
System.out.println(z);
System.out.println(a);
}

}
Inner i = new Inner();
i.m2();

}
public static void main(String[] args) {
Outer o = new Outer();
o.m1();
}
}

 If we declare m1() method as static then at line 1 which variables we


can access directly.

package innerClass;

public class Outer {


int x = 10;
static int y = 20;
public static void m1() {
int z = 30;
final int a = 40;
class Inner {
public void m2() {
System.out.println(x);----------error
System.out.println(y);
System.out.println(z);
System.out.println(a);
}

}
Inner i = new Inner();
i.m2();

}
public static void main(String[] args) {
Outer o = new Outer();
o.m1();
}
}
We can access only static members inside static methods.

 If we declare m2() method as static then at line 1 which variables we


can access directly.
package innerClass;

public class Outer {


int x = 10;
static int y = 20;
public void m1() {
int z = 30;
final int a = 40;
class Inner {
public static void m2() {
System.out.println(x);
System.out.println(y);
System.out.println(z);
System.out.println(a);
}

}
Inner i = new Inner();
i.m2();

}
public static void main(String[] args) {
Outer o = new Outer();
o.m1();
}
}

We will get compile time error because we can’t declare static members inside
inner classes.
8. The only applicable modifiers for method local inner classes are
final, abstract and strictfp.

Anonymous inner classes:


1. Sometimes we can declare inner class without name. Such types of
inner classes are called anonymous inner classes.
2. The main purpose of anonymous inner classes is just for instant
use (one time usage).
3. Based on declaration and behavior there are three types of
anonymous classes:
 Anonymous inner class that extends a class.
 Anonymous inner class that implements an interface.
 Anonymous inner class that define inside arguments.

 Anonymous inner class that extends a class:


package innerClass;

public class PopCorn {

public void taste() {


System.out.println("salty");
//100 more methods
}

package innerClass;

public class Test {


public static void main(String[] args) {

PopCorn p = new PopCorn() {


public void taste() {
System.out.println("spicy");
}
};
p.taste();

PopCorn p1 = new PopCorn();


p1.taste();

PopCorn p2 = new PopCorn() {


public void taste() {
System.out.println("sweet");
}
};
p2.taste();

System.out.println(p.getClass().getName());
System.out.println(p1.getClass().getName());
System.out.println(p2.getClass().getName());

}
}
Output:

spicy
salty
sweet
innerClass.Test$1
innerClass.PopCorn
innerClass.Test$2

analysis:
 PopCorn p = new PopCorn();----just we are creating PopCorn object.
 PopCorn p = new PopCorn{};----we are declaring a class that extends
PopCorn without name (anonymous inner class). For that child class we
are creating an object with parent reference.
 PopCorn p2 = new PopCorn() {
public void taste() {
System.out.println("sweet");
}
};
We are declaring a class that extends PopCorn without name (anonymous
inner class). For that child class we are creating an object with
parent reference.
In that child class we are overriding taste() method.

Defining a Thread by extending Thread class:


Anonymous inner class approach:
package innerClass;
public class Test {
public static void main(String[] args) {
Thread t = new Thread() {
public void run() {
for(int i = 0; i < 5; i++) {
System.out.println("child thread");
}
}
};

t.start();

for(int i = 0; i < 5; i++) {


System.out.println("main thread");
}
}
}
Defining a Thread by implementing Runnable
Interface:
Anonymous inner class approach:
package innerClass;

public class Test {


public static void main(String[] args) {
Runnable r = new Runnable() {
@Override
public void run() {
for(int i = 0; i < 5; i++) {
System.out.println("child thread");
}
}
};
Thread t = new Thread(r);
t.start();

for(int i = 0; i < 5; i++) {


System.out.println("main thread");
}
}
}

Normal java class VS anonymous inner class:


Normal java class Anonymous inner class
 A normal java class can  Anonymous inner class also
extend only one class at a can extend only one class at
time. a time.
 A normal java class can  But anonymous inner class
implement any number of can implement only one
interfaces simultaneously. interface at a time.
 A normal java class can  But anonymous inner class
extend a class and can can extend a class or can
implement any number of implement an interface but
interfaces simultaneously. not both simultaneously.
 In normal java class we can  But in anonymous inner
write any number of classes we can’t write any
constructors. constructor explicitly
(because the name of the
class and the name of the
constructor must be same but
anonymous inner classes not
having any name).
 If the requirement is  If the requirement is
standard and required temporary and required only
several times then we should once (instant use) then we
go for normal top level should go for anonymous
class. inner class.

Q: Where anonymous inner classes are best suitable?

Static nested class:


1. Sometime we can declare inner class with static modifier. Such
types of inner classes are called static nested classes.
2. In the case of normal or regular inner class without existing
outer class object there is no chance of existing inner class
object i.e inner class object strong associated with outer class
object.
3. But in the case static nested classes without existing outer
class object, there may be a chance of existing nested class
object. Hence static nested class object is not strongly
associated with outer class object.

package innerClass;

public class Outer {

static class Nested{


public void m1() {
System.out.println("static nested class method");
}
}
public static void main(String[] args) {
Nested n = new Nested();
n.m1();
}
}

4. If we want to create nested class object from outside of outer


class then we can create as follows:

Outer.nested n = new Outer.nested():

5. In normal/regular inner classes we can’t declare any static


members.
But in static nested classes we can declare static members
including main method. Hence we can invoke static nested class
directly from command prompt.
package innerClass;

public class Outer {

static class Nested{

public static void main(String[] args) {


System.out.println("static nested class main method");
}
}
public static void main(String[] args) {
System.out.println("outer class main method");
}
}
6. From normal/regular inner classes we can access both static and
non-static members of outer class directly but from static nested
classes we can access only static members of outer class directly
and we can’t non-static members.

package innerClass;

public class Outer {


int x = 10;
static int y = 20;
static class Nested{
public void m1() {
System.out.println(x);------error
System.out.println(y);
}

}
public static void main(String[] args) {
Nested n = new Nested();
n.m1();
}
}

Compile time error: non-static variables cannot be referenced from


static context.

Various combinations of nested classes and interfaces:

Case1: class inside a class

Without existing one type of object, if there is no chance of existing


another type of object then we can declare a class inside a class.

Example:

1. University consists of several departments. Without existing


university, there is no chance of existing department. Hence we have to
declare department class inside university class.

package innerClass;

public class University {


class Departement{

Case2: Interface inside a class:

Inside a class if we require multiple implementation of an interface


and all these implementation are related a particular class then we
can define interface inside a class.

package innerClass;

public class VehicleTypes {

interface Vehicle{
public int getNoWheels();
}

class Car implements Vehicle{


@Override
public int getNoWheels() {
// TODO Auto-generated method stub
return 5;
}
}

class Auto implements Vehicle{


@Override
public int getNoWheels() {
// TODO Auto-generated method stub
return 4;
}
}

public static void main(String[] args) {

Case3: Interface inside an interface:

 We can define interface inside an interface.


Example:

Map is a group of key value pairs and each key value pair is called
an entry. Without existing map object, there is no chance of
existing entry object. Hence interface entry is defined inside map
interface.
package innerClass;

public interface Map {

interface Entry{

 Every interface present inside interface is always public and static


whether we are declaring or not. Hence we can implement inner interface
directly without implementing outer interface.
 Similarly whenever we are implementing outer interface we are not
require to implement inner interface, i.e we can implement outer and
inner interfaces independently.

package innerClass;

interface Outer {

public void m1();

interface inner{
public void m2();
}

class Test1 implements Outer{


@Override
public void m1() {
System.out.println("outer interface method
implementation");
}
}

class Test2 implements Outer.inner{


@Override
public void m2() {
System.out.println("inner interface method
implementation");
}
}

package innerClass;

import innerClass.Outer.Test1;
import innerClass.Outer.Test2;

public class Test {


public static void main(String[] args) {
Test1 t1 = new Test1();
Test2 t2 = new Test2();
t1.m1();
t2.m2();
}
}

Case4: class inside interface:

If functionality of a class is closely associated with interface then it is


highly recommended to declare class inside interface.

package innerClass;

interface EmailService {

public void sendMail(EmailDetails e);

class EmailDetails {
String toDoList;
String cCList;
String subject;
String body;
}

}
In the above EmailDetails is required only for EmailService and we are not
using anywhere else. Hence EmailDetails class is recommended to declare
EmailService interface.
We can also define a class inside interface to provide default implementation
for that interface.

package innerClass;
interface Vehicle {

public int getNoWheels();

class DefaultVehicle implements Vehicle{


@Override
public int getNoWheels() {
// TODO Auto-generated method stub
return 2;
}
}

class Bus implements Vehicle{


@Override
public int getNoWheels() {
// TODO Auto-generated method stub
return 4;
}
}

package innerClass;

import innerClass.Vehicle.Bus;

public class Test{


public static void main(String[] args) {
Vehicle.DefaultVehicle d = new Vehicle.DefaultVehicle();
System.out.println(d.getNoWheels());

Bus b = new Bus();


System.out.println(b.getNoWheels());
}
}
In the above example DefaultVehicle is the default implementation of Vehicle
interface. Whereas Bus is customized implementation Vehicle interface.

Note:

The class which is declared inside interface is always public static whether
we are declaring or not. Hence we can create class object directly without
having outer interface type object.

You might also like