460 likes | 992 Vues
Inner Classes. Nested Classes. An nested class is a class that is defined inside another class. To this point we have only studied top-level classes. at most one public per file arbitrarily many package-scope per file either package or public ONLY Nested classes introduced in jdk1.1.
E N D
Nested Classes • An nested class is a class that is defined inside another class. • To this point we have only studied top-level classes. • at most one public per file • arbitrarily many package-scope per file • either package or public ONLY • Nested classes introduced in jdk1.1
Why use nested classes? • Simplifies many coding tasks • can define small classes on the fly near the objects created from them + concise syntax • can access outer classes iv’s automatically – no need to pass a this pointer to the constructor of separate outer class • can be hidden from other classes in the same package • However, price to pay in terms of complexity, number of gotchas, etc.
Pre jdk1.1 • In jdk1.0, the clean and simple class rules were ballyhooed as a major improvement over C++ • Addition of inner classes complicates things significantly • However, they do make certain code much less awkard to write, particularly when writing GUIs • Still, you do not have to use them, but they can be quite cool and I do recommend it in moderation!
Types of nested classes • Inner classes • local • anonymous or named • non-local • named only • Static nested classes • non-local named only
Non-local inner classes • Simply a nested class that does not have the static attribute and is not defined within a class method. • Can be private, public, package, protected, abstract, etc. just like any class member. • Think of outer class as owning inner class – inner class can only be instantiated via outer class reference (including this) • Inner class has access to all outer class iv’s, private or otherwise!
Simple non-local inner class example class Outer{ private int x1; Outer(int x1){ this.x1 = x1; } public void foo(){ System.out.println(“fooing”);} public class Inner{ private int x1 = 0; void foo(){ System.out.println(“Outer value of x1: “ + Outer.this.x1); System.out.println(“Inner value of x1: “ + this.x1); } }
Simple example, cont -- driver • Rules for instantiation a little funny • public class TestDrive{ • public static void main(String[] args){ • Outer outer = new Outer(); // can create in regular way • Inner inner = outer.new Inner(); //must call new through • //outer object handle • inner.foo(); • // note that this can only be done if inner is visible • // according to the regular scoping rules • } • }
Inner class rules • Note that inner class can access outer class instance variables (even private ones). • It does this using the object reference <OuterClassName>.this • Refer to public inner class as <OuterClassName>.<InnerClassName>
Another example public class TalkingClock{ private int interval; private boolean beep; public TalkingClock(int interval, boolean beep){ …} public void start(){ …} public class TimePrinter implements ActionListener //inner class { …} }
When to use non-local inner classes • Most typically used when inner class is instantiated from outer class. • If classes naturally “belong together”, it is cumbersome to pass a this pointer to a separate outer class just so second class can access first class’s properties/methods. • Note that inner class can access outer class’s private data, making them even more powerful than mechanism implied above!
Local inner classes • Inner classes may also be defined within class methods. • These are called local inner classes. • Principle advantage is scoping: such classes are completely inaccessible anywhere but the method itself where they are defined. • Thus, they have no visibility attribute (public, etc.) • Also, can NOT access local variables other than those declared with final attribute.
Example: define TimePrinter in start() method public void start(){ class TimePrinter implements ActionListener{ public void actionPerformed(ActionEvent event){ Date now = new Date(); System.out.println(“At the tone, the time is “ + now); if (beep) Toolkit.getDefaultToolkit().beep(); } } ActionListener listener = new TimePrinter(); Timer t = new Timer(interval, listener) t.start(); }
Local anonymous inner classes • Local inner classes can be taken a step further – it is not required to give them an explicit name. • This is very convenient when you want to use a class only once and the code that it contains is succinct. • Very common example is defining Swing callback functions.
Anonymous inner class example public void start(int interval, final boolean beep){ ActionListener listener = new ActionListener(){ public void actionPerformed(ActionEvent event){ Date now = new Date(); System.out.println("At the tone, the time is " + now); if (beep) Toolkit.getDefaultToolkit().beep(); } }; Timer t = new Timer(interval, listener); t.start(); } }
Anonymous class example but.addActionListener( new ActionListener(){ public void actionPerformed(actionEvent ae){ //do work here } } );