Inner ClassesAgenda
Introduction
![]()
Without existing University object there is no chance of existing Department object hence we have to define Department class inside University class. Example1: ![]() Example 2: Without existing Bank object there is no chance of existing Account object hence we have to define Account class inside Bank class. Example: ![]() Example 3: Without existing Map object there is no chance of existing Entry object hence Entry interface is define inside Map interface. Map is a collection of key-value pairs, each key-value pair is called an Entry. Example: ![]() Diagram: ![]() Note : Without existing Outer class Object there is no chance of existing Inner class Object. Note: The relationship between outer class and inner class is not IS-A relationship and it is Has-A relationship. Based on the purpose and position of declaration all inner classes are divided into 4 types.They are:
1. Normal (or) Regular inner class:If we are declaring any named class inside another class directly without static modifier such type of inner classes are called normal or regular inner classes.Example: class Outer { class Inner { } } Output: ![]() Example: class Outer { class Inner { } public static void main(String[] args) { System.out.println("outer class main method"); } } Output: ![]()
class Outer { class Inner { public static void main(String[] args) { System.out.println("inner class main method"); } } } Output: E:\scjp>javac Outer.java Outer.java:5: inner classes cannot have static declarations public static void main(String[] args) Accessing inner class code from static area of outer class: Example: class Outer { class Inner { public void methodOne(){ System.out.println("inner class method"); } } public static void main(String[] args) { Accessing inner class code from instance area of outer class: Example: class Outer { class Inner { public void methodOne() { System.out.println("inner class method"); } } public void methodTwo() { Inner i=new Inner(); i.methodOne(); } public static void main(String[] args) { Outer o=new Outer(); o.methodTwo(); } } Output: E:\scjp>javac Outer.java E:\scjp>java Outer Inner class method Accessing inner class code from outside of outer class: Example: class Outer { class Inner { public void methodOne() { System.out.println("inner class method"); } } } class Test { public static void main(String[] args) { new Outer().new Inner().methodOne(); } } Output: Inner class method ![]()
class Outer { int x=10; static int y=20; class Inner{ public void methodOne() { System.out.println(x);//10 System.out.println(y);//20 } } public static void main(String[] args) { new Outer().new Inner().methodOne(); } }
class Outer { int x=10; class Inner { int x=100; public void methodOne() { int x=1000; System.out.println(x);//1000 System.out.println(this.x);//100 System.out.println(Outer.this.x);//10 } } public static void main(String[] args) { new Outer().new Inner().methodOne(); } } The applicable modifiers for outer classes are:
Diagram: ![]() Nesting of Inner classes :We can declare an inner class inside another inner class Diagram: ![]() Method local inner classes:
class Test { public void methodOne() { class Inner { public void sum(int i,int j) { System.out.println("The sum:"+(i+j)); } } Inner i=new Inner(); i.sum(10,20); ;;;;;;;;;;;;; i.sum(100,200); ;;;;;;;;;;;;;;; i.sum(1000,2000); ;;;;;;;;;;;;;;;;; } public static void main(String[] args) { new Test().methodOne(); } } Output: The sum: 30 The sum: 300 The sum: 3000
class Test { int x=10; static int y=20; public void methodOne() { class Inner { public void methodTwo() { System.out.println(x);//10 System.out.println(y);//20 } } Inner i=new Inner(); i.methodTwo(); } public static void main(String[] args) { new Test().methodOne(); } }
class Test { int x=10; public void methodOne() { int y=20; class Inner { public void methodTwo() { System.out.println(x);//10 System.out.println(y); //C.E: local variable y is accessed from within inner class; needs to be declared final. } } Inner i=new Inner(); i.methodTwo(); } public static void main(String[] args) { new Test().methodOne(); } }
class Test { int i=10; static int j=20; public void methodOne() { int k=30; final int l=40; class Inner { public void methodTwo() { System.out.println(i); System.out.println(j); //-->line 1 System.out.println(k); System.out.println(l); } } Inner i=new Inner(); i.methodTwo(); } public static void main(String[] args) { new Test().methodOne(); } } At line 1 which of the following variables we can access ?
Anonymous inner classes:
Anonymous inner class that extends a class: class PopCorn { public void taste() { System.out.println("spicy"); } } class Test { public static void main(String[] args) { PopCorn p=new PopCorn() { public void taste() { System.out.println("salty"); } }; p.taste();//salty PopCorn p1=new PopCorn() p1.taste();//spicy } }Analysis:
Note: Inside Anonymous inner classes we can take or declare new methods but outside of anonymous inner classes we can't call these methods directly because we are depending on parent reference.[parent reference can be used to hold child class object but by using that reference we can't call child specific methods]. These methods just for internal purpose only. Example 1:class PopCorn { public void taste() { System.out.println("spicy"); } } class Test { public static void main(String[] args) { PopCorn p=new PopCorn() { public void taste() { methodOne();//valid call(internal purpose) System.out.println("salty"); } public void methodOne() { System.out.println("child specific method"); } }; //p.methodOne();//here we can not call(outside inner class) p.taste();//salty PopCorn p1=new PopCorn(); p1.taste();//spicy } } Output: Child specific method Salty SpicyExample 2: class Test { public static void main(String[] args) { Thread t=new Thread() { public void run() { for(int i=0;i<10;i++) { System.out.println("child thread"); } } }; t.start(); for(int i=0;i<10;i++) { System.out.println("main thread"); } } } Anonymous Inner Class that implements an interface: Example: class InnerClassesDemo { public static void main(String[] args) { Runnable r=new Runnable() //here we are not creating for Runnable interface, we are creating implements class object. { public void run() { for(int i=0;i<10;i++) { System.out.println("Child thread"); } } }; Thread t=new Thread(r); t.start(); for(int i=0;i<10;i++) { System.out.println("Main thread"); } } } Anonymous Inner Class that define inside method arguments: Example: class Test { public static void main(String[] args) { new Thread( new Runnable() { public void run() { for(int i=0;i<10;i++) { System.out.println("child thread"); } } }).start(); for(int i=0;i<10;i++) { System.out.println("main thread"); } } } Output:
Main thread Main thread Main thread Main thread Main thread Main thread Main thread Main thread Main thread Main thread Child thread Child thread Child thread Child thread Child thread Child thread Child thread Child thread Child thread Child thread Difference between general class and anonymous inner classes:
Explain the application areas of anonymous inner classes ?anonymous inner classes are best suitable to define call back functions in GUI componentsimport java.awt.*; import java.awt.event.*; public class AnonymousInnerClassDemo { public static void main(String args[]) { Frame f=new Frame(); f.addWindowListener(new WindowAdaptor(){ public void windowClosing(WindowEvent e) { System.exit(0); } }); f.add(new Label("Anonymous Inner class Demo !!!")); f.setSize(500,500); f.setVisible(true); } } Without Anonumous Inner class : class GUI extends JFrame implements ActionListener { JButton b1,b2,b3,b4; ----------------- public void actionPerformed(ActionEvent e) { if(e.getSource()==b1) { //perform b1 specific functionality } else if(e.getSource==b2){ //perform b2 specific functionality } --------------------- } ---------------- } With Anonumous Inner class : class GUI extends JFrame { JButton b1,b2,b3,b4 ; -------------------- b1.addActionListener(new ActionListener() { public void actionPerformed(ActionEvent e) { //perform b1 specific functionality } }); b2.addActionListener(new ActionListener() { public void actionPerformed(ActionEvent e) { //perform b2 specific functionality } }); --------- } Static nested classes:
class Test { static class Nested { public void methodOne() { System.out.println("nested class method"); } } public static void main(String[] args) { Test.Nested t=new Test.Nested(); t.methodOne(); } }
class Test { static class Nested { public static void main(String[] args) { System.out.println("nested class main method"); } } public static void main(String[] args) { System.out.println("outer class main method"); } } Output: E:\SCJP>javac Test.java E:\SCJP>java Test Outer class main method E:\SCJP>java Test$Nested Nested class main method
class Test { int x=10; static int y=20; static class Nested { public void methodOne() { System.out.println(x);//C.E:non-static variable x cannot be referenced from a static context System.out.println(y); } } } Compression between normal or regular class and static nested class ?
Various possible combinations of nested class & interfaces :1. class inside a class :
class University { class Department { } }Without existing University object, there is no chance of existing Department object. i.e., Department object is always associated with University 2. interface inside a class :We can declare interface inside a classclass X { interface Y { } }Inside class if we required multiple implements of an interface and these implementations of relevant to a perticular class, then we should declare interface inside a class. class VehicleType { interface Vehicle { public int getNoOfWheels(); } class Bus implements Vehicle { public int getNoOfWheels() { return 6; } } class Auto implements Vehicle { public int getNoOfWheels() { return 3; } } } 3. interface inside a interface :We can declare an interface inside another interface.interface Map { interface Entry { public Object getKey(); public Object getValue(); public Object getValue(Object new ); } }Nested interfaces are always public,static whether we are declaring or not. Hence we can implements inner inteface directly with out implementing outer interface. interface Outer { public void methodOne(); interface Inner { public void methodTwo(); } } class Test implements Outer.Inner { public void methodTwo() { System.out.println("Inner interface method"); } public static void main(String args[]) { Test t=new Test(); t.methodTwo(); } }Whenever we are implementing Outer interface , it is not required to implement Inner interfaces. class Test implements Outer { public void methodOne() { System.out.println("Outer interface method "); } public static void main(String args[]) { Test t=new Test(); t.methodOne(); } }i.e., Both Outer and Inner interfaces we can implement independently. 4. class inside a interface :We can declare a class inside interface. If a class functionality is closely associated with the use interface then it is highly recommended to declare class inside interfaceExample: interface EmailServer { public void sendEmail(EmailDetails e); class EmailDetails { String from; String to; String subject; } }In the above example Emaildetails functionality is required for EmailService and we are not using anyware else . Hence we can declare EmailDetails class inside EmailService interface . We can also declare a class inside interface to provide default implementation for that interface. Example : interface Vehicle { public int getNoOfWheels(); class DefaultVehicle implements Vehicle { public int getNoOfWheels() { return 3; } } } class Bus implements Vehicle { public int getNoOfWheels() { return 6; } } class Test { public static void main(String args[]) { Bus b=new Bus(); System.out.println(b.getNoOfWheels()); Vehicle.DefaultVehicle d=new Vehicle.DefaultVehicle(); System.out.println(d.getNoOfWheels()); } }In the above example DefaultVehicle in the default implementation of Vehicle interface where as Bus customized implementation of Vehicle interface. The class which is declared inside interface is always static ,hence we can create object directly without having outer interface type object. Conclusions :
|